Is it still possible to do server side verification of tokens in Firebase 3?
Solution 1:
The short answer is yes. The full answer is that, in most cases, we have a more appropriate tool now. So a lot depends on the use case you are trying to resolve.
The new SDK version is quite a bit more powerful, and we haven't done a great job of summarizing the capabilities. This seems like a good place to contrast the tools available and their uses, and then I'll tack on some third-party (i.e. Go) specific notes at the end.
Using an external authentication tool for client authentication
The primary use of minting custom tokens is to allow users to authenticate against an external/legacy auth mechanism you control, such as your LDAP server. The basic process for this is covered here: iOS, Android, Web.
Essentially, your service just mints the JWT token and passes this to the client. The client does the verification/authentication using the custom token you provide.
Authenticating your privileged workers
It's no longer necessary to use custom tokens to authenticate your server process. This is done by creating a service account, which is covered step-by-step in Adding Firebase to your Server. When done, you'll end up with a JSON file that contains a private key.
Then, you include your service account credentials by referencing that JSON using the serviceAccount
attribute in firebase.initializeApp()
, and you're in! That's documented here and looks like this (see link for Java version):
var firebase = require("firebase");
// Initialize the app with a service account, granting admin privileges
firebase.initializeApp({
databaseURL: "https://databaseName.firebaseio.com",
serviceAccount: "./serviceAccountCredentials.json"
});
Emulating users or limiting access from a server process
It's fairly trivial to emulate a user or to limit access (highly recommended) from a server process. You don't really need to mint a custom token for this anymore.
This just requires adding the databaseAuthVariableOverride
into your call to database.initializeApp()
:
firebase.initializeApp({
databaseURL: "https://databaseName.firebaseio.com",
serviceAccount: "./serviceAccountCredentials.json",
databaseAuthVariableOverride: {
uid: "my-service-worker-or-user-uid"
}
});
Validating client identity via security
First of all, you can usually avoid dealing with server-side verification if you are using Firebase Database, by having your client write to the database and using security rules to validate their identity. If your server listens on a path that requires authentication to write into, then this is already solved without any special security at the server.
By modeling this as an event queue, it creates a simple, modular, and scalable server worker strategy. See firebase-queue for some great Node.js tools. It supports 3.x.
Verifying client ID tokens on the server
If you aren't using the Realtime Database and need to receive client tokens (e.g. via REST calls) and verify that they are valid, you can do so by using verifyIdToken()
as described here. This would look like the following:
auth.verifyIdToken(idToken).then(function(decodedToken) {
var uid = decodedToken.sub;
});
If you then want to authenticate as that user to write to the database and enforce security, you would use the Emulating Users section above. In other words, call initializeApp()
with a databaseAuthVariableOverride
set to the appropriate uid.
Note that, if you try to call initializeApp()
multiple times and run into an error similar to the following: Error: Firebase App named '[DEFAULT]' already exists.
You can initialize multiple app contexts by adding a second argument to the initializeApp() call (e.g. database.initializeApp({...}, 'asUser'+uid)
) and then reference that app instance by using firebase.database('asUser'+uid)
.ref(...). To read more on using multiple app instances, look here.
Java code available at the links above. Go and other third party solutions covered below.
Creating a token for use in the REST API
Michael Bleigh covered this scenario here and deserves some rep for working this out.
Creating tokens or verifying them via REST
This isn't supported. Sorry.
Golang and others: More to come
We're working on a Go token minting and verification library. We'll also be adding Python tools for this soon as well. No release date or ballparks for this. In the mean time, if you'd like to verify client ID tokens without using the official Firebase Node.js or Java libraries (which have built-in verification methods), you will need to ensure the ID token (which is a JWT) conforms to the following:
- Its decoded header has an
alg
(algorithm) claim equal to"RS256"
. - Its decoded payload has an
aud
(audience) claim equal to your Firebase project ID. - Its decoded payload has an
iss
(issuer) claim equal to"https://securetoken.google.com/<projectId>"
. - Its decoded payload has a non-empty string
sub
(subject) claim. Note that this is theuid
for that Firebase user. - Its decoded header has a
kid
(key ID) claim that corresponds to one of the public keys listed athttps://www.googleapis.com/robot/v1/metadata/x509/[email protected]
. - You also need to use a JWT library to verify the token with the public key to prove the token was signed with the public keys' corresponding private key.
For Go, it looks like you can use jwt-go
to decode and validate the client ID token.