How to retrieve a Firebase-Instance-ID-token? - javascript

I am using the Firebase Functions Shell to interactively test a callable HTTPS function. The documentation (Test functions interactively) states that I can pass a Firebase-Instance-ID-token for authentication but doesn't say how to acquire one.
Optionally, you may pass in a Firebase-Instance-ID-token as the second
parameter. This must be a string.
# invoke with Instance ID token
myCallableFunction('test data', {instanceIdToken: 'sample token'})
It also says,
Emulation of context.auth is currently unavailable.
Does this mean even if I pass a token my function will not receive context: { auth: uid }, etc? If so, what would be a good way to mock this for testing purposes?
FYI, I am not using Firebase Messaging.

If you don't know exactly what you want there, then don't pass anything at all. If you're not using FCM, then the string will be useless to your function. It's only really used to in the API call to send messages, or to be stored for later use with FCM.
This token has nothing to do with user auth. FCM tokens don't identify an authenticated user. They identify a device that the user is using your app on.
I will point out also that the documentation states:
Emulation of context.auth is currently unavailable.
So there's nothing you can do to get context.auth populated in your function, from the perspective of this local testing tool.

Related

Javascript - Firebase Functions on how to get user id

I want to define custom functions on Firebase using firebase-tools. Is there a way to get userId from firebase-functions?
Say on this code sample, is it possible to get the user who sent the request?
const functions = require('firebase-functions');
exports.helloWorld = functions.https.onRequest((request, response) => {
response.send("Hello from Firebase!");
});
I have tried getting it with the following code unsuccessfully functions.auth.user().uid.
I am quite new to both js and firebase, so go easy on me please, I am trying to learn.
You're over-simplifying the way HTTP triggers work. They have no knowledge of anything about the entity on the end making the request. It could be a user, or just some automated program. The user doesn't have to be authenticated in order to access your function.
If you want to limit access to your HTTP trigger to only authenticated users, you could try something as described in this other question. There is official sample code that shows what you need to do.
Bottom line is this. Unless you do something to safely transmit to the function who the user is (identified by an id token), then you really have no idea who they are.
Think I find a better answer from this post :
https://medium.com/super-declarative/dev-snack-testing-firebase-cloud-functions-with-user-id-tokens-83841d3f06c.
Basically 2 ways for http functions
functions.https.onRequest : You may get, if available, the token from the request and then use firebase admin api to get user UID;
functions.https.onCall for authenticated request : You get it from exposed context object

External Firebase communication to Elm via Ports?

I have custom Firebase auth processes (Auth0 => Firebase), so I run all my login logic using TypeScript with Svelte, once I have a successful JWT token, either from sessionStorage or from a fresh login, I boot off my Elm app, sending it some JWT and profile info via a flag. It's a SPA, with a routeing and pages, all componentized and working fine.
My only real problem now is, when it comes to firebase, sure, ElmFire exists, but how do I just give it an active auth token etc. And without loading Firebase for JS and also ElmFire for Elm, it just seems like way too many Kb's.
Is there a nice and efficient way to let Elm port out a "hey listen to this ref", with a "hey Elm, I have some new data for you for this ref". Ports to tell JS to listen, and subscriptions to tell Elm about new data. Without having a port for every listener, and a subscription for every data callback.
Ideally, I'd like my update, to send off a CMD that accepts a callback Msg, to update the function to call and a ref. So that way I can store that in a List of some sort, and when I get a new data payload from JS, I can loop through my List to find the item that matches the ref, execute the update, send in the Msg with the string value, so decoding happens on the pages' update.
Someone feel free to abstract this question into something more general. Feel like this question is something more people might have.
The problem is that port/sub must be typed in Elm.
So, a single port / sub with one argument could listen to multiple refs as long as they all have the same type.
If not, you could define the port / sub with multiple arguments, one for each type of data you want to exchange, and pass any particular data in the proper argument. The other arguments would be null.

Firebase Authentication data mismatch between web and jvm

I’m trying out the Authentication component in Firebase.
A) I have a situation where the web client javascript code firebase-app.js and firebase-auth.js 3.3.0...
firebase.auth().onAuthStateChanged and
firebase.auth().currentUser
... return different expected logged in user values, than the jvm
client [com.firebase/firebase-client-jvm "2.5.2"]. The JVM client
returns null user data.
My JVM client code is taken from Firebase’s QuickStart Guide. In
the JVM client, neither onAuthStateChanged handler is called, nor
does firebaseObj.getAuth() return any data.
I’m wondering where the discrepancy is. The web client was initialized
with “codepairio.firebaseapp.com”.
var config = { ... authDomain: “<my-firebase-app>.firebaseapp.com"
};
firebase.initializeApp(config);
B) The java client was initialized with “https://.firebaseio.com”. I’m using this URL as it’s specified in the guide and mentioned here. Also, if you try
to use “.firebaseapp.com”, you’ll get an error:
“IllegalStateException For a custom firebase host you must first set your authentication server before using authentication features!”.
So with that out of the way, we have...
new Firebase("https://<my-firebase-app>.firebaseio.com”);
Any ideas on how to get them to observe the same source of truth?
====> [EDIT]
Ok, I've gotten a bit further. It turns out that I was using an older firebase API (A) than the latest (B).
A) https://www.firebase.com/docs/android/guide/user-auth.html
B) https://firebase.google.com/docs/auth/server/
So if we look at Firebase's documentation for how to handle user's, we see this:
A Firebase User object represents the account of a user who has signed
up to an app in your Firebase project. Apps usually have many
registered users, and every app in a Firebase project shares a user
database.
A Firebase User instance is independent from a Firebase Auth instance. This means that you can have several references to different
users within the same context and still call any of their methods.
But i) the notion of FirebaseAuth.getInstance().getCurrentUser() doesn't make sense if our app is dealing with multiple users. And further, the FirebaseAuth.getInstance().getCurrentUser() method doesn't even exist. The FirebaseAuth class file (in com.firebase/firebase-client-jvm "2.5.2"), doesn't reflect the documentation.
$ javap -classpath ~/.m2/repository/com/google/firebase/firebase-server-sdk/3.0.1/firebase-server-sdk-3.0.1.jar com.google.firebase.auth.FirebaseAuth
Compiled from "FirebaseAuth.java"
public class com.google.firebase.auth.FirebaseAuth {
public static com.google.firebase.auth.FirebaseAuth getInstance();
public static synchronized com.google.firebase.auth.FirebaseAuth getInstance(com.google.firebase.FirebaseApp);
public java.lang.String createCustomToken(java.lang.String);
public java.lang.String createCustomToken(java.lang.String, java.util.Map<java.lang.String, java.lang.Object>);
public com.google.firebase.tasks.Task<com.google.firebase.auth.FirebaseToken> verifyIdToken(java.lang.String);
static com.google.api.client.json.JsonFactory access$000();
static com.google.firebase.auth.internal.FirebaseTokenVerifier access$100(com.google.firebase.auth.FirebaseAuth);
static {};
}
C) So far, using Firebase's Authentication service, on the server is very opaque to me at the moment. Can someone clarify the semantics of handling multiple users, getting lists of logged in users, verifying users with request tokens, etc. Where's the working API for all this?
I actually got an answer back, from Firebase Support, on this. Turns out that, based on the documentation, the capabilities available for the server side (nodejs and java) in terms of authentication are only i) creating custom tokens and ii) verifying ID tokens. As of now, handling users or getting the current user is not supported yet.
For the creation and verifying tokens in the server side, you can refer to this guide for more information. You can also check these posts for more information.
Firebase Java client with custom authentication
Is it still possible to do server side verification of tokens in Firebase 3?
https://firebase.googleblog.com/2013/03/where-does-firebase-fit-in-your-app.html
Hth

Meteor: How to prevent client from accessing methods

All meteor methods can be called same way from client and server side.
Let's say user knows or can predict all the method names on server, then he is able to call them and use it's result however he want.
example:
A method which performs cross domain http request and return response can be used to overload server by calling huge amounts of data Meteor.call(httpLoad, "google.com");, or a method which load data from mongo can be used to access database documents if the client know document _id Meteor.call(getUserData, "_jh9d3nd9sn3js");.
So, how to avoid this situations, may be there is a better way to store server-only functions than in Meteor.methods({...})?
Meteor methods are designed to be accessed from the client, if you don't want this, you just need to define a normal javascript function on the server. A really basic example would be:
server/server.js:
someFunction = function(params) {
console.log('hello');
}
As long as it's in the server folder, the function won't be accessible from the client.
For coffeescript users, each file is technically a separate scope, so you would have to define a global variable with #, e.g.
#someFunction = (params) ->
console.log 'hello'
or if you want to scope the function to a package:
share.someFunction = (params) ->
console.log 'hello'
If you have methods that need to be accessible from the client but only for say admin users, you need to add those checks at the start of the meteor method definition:
Meteor.methods({
'someMethod': function(params) {
var user = Meteor.user();
if (user && (user.isAdmin === true)) {
// Do something
} else {
throw new Meteor.Error(403, 'Forbidden');
}
}
});
I'm not going to vouch for the security of this example - it's just that, an example - but hopefully it gives you some idea of how you would secure your methods.
EDIT: Noticed the other answers mention using a if (Meteor.isServer) { ... } conditional. Note that if you are doing this inside methods which are also accessible on the client, the user will be still be able to see your server code, even if they can't run it. This may or may not be a security problem for you - basically be careful if you're hardcoding any 3rd-party API credentials or any kind of sensitive data in methods whose code can be accessed from the client. If you don't need the method on the client, it would be better to just use normal JS functions. If you're wrapping the whole Meteor.methods call with a isServer conditional, the code will be on the server only, but can still be called from the client.
as rightly stated in other answers, your methods will always be accessible from the client (per design). yet, there is a simple workaround to check if the call originates from the client or from the server. if you do a
if ( this.connection == null )
this will return true if the method was called from server. like that you can restrict the method body execution to 'secure' calls.
I think this page explains it: http://meteortips.com/first-meteor-tutorial/methods/
I'm quoting:
"The safer approach is to move these functions to the isServer conditional, which means:
Database code will execute within the trusted environment of the server.
Users won’t be able to use these functions from inside the Console, since users don’t have direct access to the server.
Inside the isServer conditional, write the following:
Meteor.methods({
// methods go here
});
This is the block of code we’ll use to create our methods."
and so on. I hope this helps.
With proper app design, you shouldn't care whether a request was through the web UI or via something typed in a console window.
Basically, don't put generic, abuse worthy functions in Meteor.methods, implement reasonable access controls, and rate-limit and/or log anything that could be a problem.
Any server-side function defined in Meteor.methods will have access to the current user id through this.userid. This userid is supplied by Meteor, not a client API parameter.
Since that Meteor Method server-side code knows the login status and userid, it can then do all the checking and rate limiting you want before deciding to do that thing that the user asked it to do.
How do you rate limit? I've not looked for a module for this lately. In basic Meteor you would add a Mongo collection for user actions accessible server-side only. Insert timestamped, userid specific data on every request that arrives via a Meteor method. Before fulfilling a request in the server method code, do a Mongo find for how many such actions occurred from this userid in a relevant period. This is a little work and will generates some overhead, but the alternative of rate-limiting via a server-wide underscore-style debounce leaves a function open for both abuse and denial-of-service by an attacker.

Get an access token without being connected to facebook

I need to retrieve a facebook page's list of posts (feed) using their javascript SDK, just like they explain in their docs: https://developers.facebook.com/docs/graph-api/reference/v2.4/page/feed
/* make the API call */
FB.api(
"/{page-id}/posts",
function (response) {
if (response && !response.error) {
/* handle the result */
}
}
);
I need it to be my website's "news section", so users should see it even if they are not connected to facebook.
The problem
Cool, but there is a problem... It returns: An access token is required to request this resource.
Holy cow... I'd like to get some access token for you #facebook, but my app doesn't make use of your authentication tools/plugins.
ANYWAY, I tried with FB.getLoginStatus(); but doesn't work, because the only way it can return an access_token is if the user is actually connected to the application. My users may not even be logged to facebook!
So, ¿How can I get an access_token to be stored into a variable, and later be used to get /{my-page}/posts?
I've already payed a look to this SO question, but it doesn't solves my problem, simply because there are no such "generic tokens".
I've also read https://developers.facebook.com/docs/facebook-login/access-tokens/ and that also relies on tokens generated through facebook login methods... So, can't I display a list of fb page's posts in my website, without being connected into facebook, hence an application?
ADD: My app is build with angularJS, I'm not dealing with server-side code. I shall rely purely on javascript methods.
You could either use an page or an app access token, but as you'd be using them on the client-side, neither of them are an option.
See
https://developers.facebook.com/docs/facebook-login/access-tokens#apptokens
https://developers.facebook.com/docs/facebook-login/access-tokens#pagetokens
Note that because this request uses your app secret, it must never be made in client-side code or in an app binary that could be decompiled. It is important that your app secret is never shared with anyone. Therefore, this API call should only be made using server-side code.
I'd strongly recommend to build a simple server-side script (PHP for example) to proxy the request to the Graph API. You could then call this via AJAX for example and load the posts asynchronously (and alse get rid of the FB JS SDK!). There is NO way to handle this in a secure manner if you don't want to use FB Login for all of your users (which also doesn't make much sense IMHO).
I think it's straightforward :)
Since pages' posts are always public, it only needs a valid access token to retrieve page posts.
Quoting what you've written:
So, ¿How can I get an access_token to be stored into a variable, and later be used to get /{my-page}/posts?
You only require an access token.
My suggestion would be;
- Generate an access token for yourself (no extra permission needed)
- request page-id/posts
This way you don't require other users to be connected to facebook, you can simply requests page-id/posts to retrieve posts with access token you generated for yourself.
I hope it solves your problem :D
TIP: As long as posts are public, you only require a valid access token, it doesn't need to be user or page specific.

Categories