I'm building an enterprise app using Microsoft Graph to sign in. After a successful signing i want to use the token to be sent to authenticate to Firebase Auth (so i can secure the access to the database).
The token recieved after a successful sign in cannot be used directly to Firebase.
On the Firebase custom Auth instructions page it says:
Get your project's server keys:
- Go to the Service Accounts page in your project's settings.
- Click Generate New Private Key at the bottom of the Firebase Admin SDK section of the Service Accounts page.
- The new service account's public/private key pair is automatically saved on your computer. Copy this file to your authentication server.
The third point says that you need to enter the key to the authentication server. Is this possible using Microsoft Graph or Azure AD?
The key that Firebase gives you is a JSON
file. I've checked Microsoft App registration portal which allows you to edit the apps Manifest, but with no luck.
The JSON
file looks like this:
{
"type": "service_account",
"project_id": "APP_ID",
"private_key_id": "KEY_ID_VALUE",
"private_key": "-----BEGIN PRIVATE KEY----<KEY VALUE>-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-0ubvc@********.iam.gserviceaccount.com",
"client_id": "XXXXXXXXXXXX",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://accounts.google.com/o/oauth2/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-0ubvc%XXXXXXXX.iam.gserviceaccount.com"
}
I can't seem to find any github projects or stackoverflow threads that covers this issue.
How can you recieve custom tokens with MS Graph or Azure AD?
I have now fully worked this out. Through extensive research and a lot of help here on Stackoverflow i managed to solve this.
Database secrets are currently deprecated and use a legacy Firebase token generator. Now Firebase Admin
import is good enough.
1. You DO need to send your private keys to your firebase functions when minting a Firebase Token. In the Firebase console, you can extract the key and rename the file to service-account.json
. This should be put in your Functions folder before performing your Firebase deploy
In your index.js
file, you can get your service file by entering this code:
const admin = require('firebase-admin');
Write the function for accepting information from the other Authentication service:
// Create a Firebase token from any UID
exports.createFirebaseToken = functions.https.onRequest((req, res) => {
// The UID and other things we'll assign to the user.
const uid = req.body.uid;
const additionalClaims = {
name: req.body.name,
email: req.body.email
};
// Create or update the user account.
const userCreationTask = admin.auth().updateUser(uid, additionalClaims).catch(error => {
if (req.method === 'PUT') {
res.status(403).send('Forbidden!');
}
if (req.method === 'GET') {
res.status(403).send('Please use POST for this function');
}
// If user does not exists we create it.
if (error.code === 'auth/user-not-found') {
console.log(`Created user with UID:${uid}, Name: ${additionalClaims.name} and e-mail: ${additionalClaims.email}`);
return admin.auth().createUser({
uid: uid,
displayName: additionalClaims.name,
email: additionalClaims.email,
});
}
throw error;
console.log('Error!');
});
return Promise.all([userCreationTask]).then(() => {
console.log('Function create token triggered');
// Create a Firebase custom auth token.
admin.auth().createCustomToken(uid, additionalClaims).then((token) => {
console.log('Created Custom token for UID "', uid, '" Token:', token);
res.status(200).send(token);
return token
});
});
});
It's very important to respond with a res.status
since this will finish the task. A single return
statement will not do this.
A fully working sample from Firebase themself can be found on github
You can now make a HTTP-request that could look something like this using Alamofire and swift
Alamofire.request("https://us-central1-<YOUR DATABASE REFERENCE>.cloudfunctions.net/createFirebaseToken",
method: .post, parameters: parameters, encoding: JSONEncoding.default).
responseString(completionHandler: { (token) in
// Handle the result here
})
In this case, the Parameters
is a regular JSON
file that contains whatever you want to add to the users Firebase account.
IMPORTANT Anyone with your cloudfunctions URL can trigger this token minting. So make sure you add security measures to handle this. This is briefly mentioned in a Firecast video on youtube made by Firebase and has also been discussed in this thread in Stackoverflow
When your client received the token you a custom auth sign in iOS or in Android as described in the documentation.
You are now authenticated both towards Firebase and Microsoft
I have also added an extra layer of security, by checking that the ID
i got from Microsoft, is the same ID
stored in the authenticated account from Firebase.
I've created an example here for Firebase web and browser-based federated authentication. The authentication response from Azure AD is validated by a function, a custom firebase token is minted and sent to the front-end; which is sent to the Firebase Auth service.
Guide with more elaboration on the flow: https://medium.com/@alex.wauters/how-to-integrate-a-firebase-web-app-with-azure-active-directory-b5c0f01a0c24
It's a lot simpler than you think. After you authenticate with Microsoft, and you get a Microsoft credential, you just need to get the associated Microsoft user ID for that credential. You can then mint a Firebase custom token and set the Firebase uid
to that same Microsoft user ID. For example you can do it as follows with the Firebase Admin Node.js SDK:
admin.createCustomToken(msftUid, additionalUserClaims)
.then(customToken => {
// Return this to the client.
})
After you send it back to the client, you then call signInWithCustomToken(customToken)
which would sign in the same user with Firebase Auth. That user will have currentUser.uid
equal to the Microsoft user ID.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With