Creating and verifying custom token

The Firebase Admin SDK provides us an ability to authenticate the user with an external mechanism such as LDAP server, or third-party OAuth provider, which Firebase doesn't support, such as Instagram or LinkedIn. We can do all these things with Firebase custom tokens method, which is built-in Admin SDK, or we can use any third-party JWT libraries.

Let's see how we can create and validate token with Admin SDK.

For creating a custom token, we must have a valid uid, which we need to pass in the createCustomToken() method:

function createCustomToken(req,res){
const userId = req.body.uid "guest_user"
admin.auth().createCustomToken(userId)
.then(function(customToken) {
res.send(customToken.toJSON());
})
.catch(function(error) {
console.log("Error creating custom token:", error);
});
}

In the preceding function, we have uid from client side when the user signs in with username and password, and if the credentials are valid, we'll return custom JWT (JSON Web Token) from the server that can be used by a client device to authenticate with Firebase:

app.get('/login', function (req, res) {
if(validCredentials(req.body.username,req.body.password)){
createCustomToken(req,res);
}
})

Once it's authenticated, this identity will be used for accessing Firebase services like Firebase Realtime Database and Cloud Storage. 

If need be, we can also add some additional fields to be included in the custom token. Consider this code:

function createCustomToken(req,res){
const userId = req.body.uid
const subscription = {
paid:true
}
admin.auth().createCustomToken(userId)
.then(function(customToken) {
res.send(customToken.toJSON());
})
.catch(function(error) {
console.log("Error creating custom token:", error);
});
}

These additional fields will be available in the auth/request.auth object in security rules.

Once the token is generated and received by the react method, we'll authenticate the user to the app by passing the custom token to the Firebase signInWithCustomToken() method:

const uid = this.state.userId
fetch('http://localhost:3000/login', {
method: 'POST', // or 'PUT'
body: JSON.stringify({idToken:idToken}),
headers: new Headers({
'Content-Type': 'application/json'
})
}).then(res => res.json())
.catch(error => console.error('Error:', error))
.then(res => {
console.log(res,"after token valid");
firebase.auth().signInWithCustomToken(res.customToken).catch(function(error) {
var errorCode = error.code;
var errorMessage = error.message;
});
})

After the successful authentication, the user signed in to our application with account specified by the uid, which we included in creating the custom token method.

In the same way, the other Firebase authentication methods works like signInWithEmailAndPassword() and signInWithCredential(), and the auth/request.auth object will be available in Firebase Realtime database security rules with the user uid. In the preceding example, we specified why to generate the custom token.

//Firebase Realtime Database Rules
{
"rules": {
"admin": {
".read": "auth.uid === 'guest_user'"
}
}
}
//Google Cloud Storage Rules
service firebase.storage {
match /b/<firebase-storage-bucket-name>/o {
match /admin/{filename} {
allow read, write: if request.auth.uid == "guest_user";
}
}
}

In the same way, we can also access the additional passed objects, which are available in auth.token and request.auth.token:

//Firebase Realtime Database Rules
{
"rules": {
"subscribeServices": {
".read": "auth.token.paid === true"
}
}
}
service firebase.storage {
match /b/<firebase-storage-bucket-name>/o {
match /subscribeServices/{filename} {
allow read, write: if request.auth.token.paid === true;
}
}
}

Firebase can also provide us the way to get the uid once the user logged into the app; it creates a corresponding ID token that uniquely identifies them, and we can send this token to the server for verifying and give them access to several resources of the application. For example, when we create a custom backend server to communicate with an app, we might need to identify the currently signed-in user on that server securely using HTTPS.

To retrieve the ID token from Firebase, ensure that the user has signed in to the application, and we can use the following method to retrieve the ID token in your react application:

firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) {
// Send this token to custom backend server via HTTPS
}).catch(function(error) {
// Handle error
});

Once we have this ID token, we can send this JWT (JSON Web Token) to backend server Firebase Admin SDK or any third-party library to validate it.

For validating and decoding the ID token, Firebase Admin SDK has a built-in verifyIdToken(idToken) method; if the provided token is not expired, valid, and properly signed, this method returns the decoded ID token:

function validateToken(req,res){
const idToken= req.body.idToken;
admin.auth().verifyIdToken(idToken)
.then(function(decodedToken) {
var uid = decodedToken.uid;
//...
}).catch(function(error) {
// Handle error
});
}

Now, let's extend our existing application where the user can see only those tickets that they have submitted, and we'll also give the ability to the user to update the existing profile. We'll also create an admin panel in React and, based on the role, we show the admin UI to the user.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset