FR: roles from microsoft ID token
Describe your environment
- Operating System version: macOS 10.14.6 (Mojave)
- Browser version: Chrome 76 (and others)
- Firebase SDK version: 6.4.1
- Firebase Product: auth
Describe the problem
TLDR: Can we get the ID-Token (or the claims it contains) from the Microsoft Azure AD authentication provider in the client side AuthCredential
We are setting up Firebase Auth using Microsoft Azure Active Directory as described at https://firebase.google.com/docs/auth/web/microsoft-oauth This works great, but we also use the feature in Azure AD to define application-roles. These can be mapped to individual users or groups within the active directory. Details on how to configure this are at https://docs.microsoft.com/en-us/azure/active-directory/develop/howto-add-app-roles-in-azure-ad-apps
The roles that are assigned to the user are put into the ID-Token by Azure Active Directory. If we login directly (not using Firebase) we can see this in the token:
{
"aud": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"iss": "https://sts.windows.net/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx/",
...
"name": "Test User",
"roles": [
"normal-user"
],
"unique_name": "[email protected]",
"upn": "[email protected]",
}
However, if we use Firebase Auth to connect to Microsoft, we obviously get a token from firebase (not microsoft). The closest we can get is using firebase.auth.Auth.getRedirectResult to get the UserCredential . This contains a key credential which contains aAuthCredential. According to the documentation, this should contain the credentials returned by an auth provider.
However this only contains a few keys: providerId, signInMethod, oauthAccessToken and pendingToken. As the name implies, the oauthAccessToken is the access token supplied by microsoft and not the ID-token.
Would it be possible to also include the id-token from the auth provider in the AuthCredential? This can contain valuable information for the user-interface (such as the roles). If you do not want to include the entire token, perhaps it would be possible to only include the claims or the roles?
Most enterprises already manage their users and roles in Azure AD and having access to the application roles through firebase would make Firebase+AzureAD a real killer for enterprise apps.
Hey @wvanderdeijl, we currently do not use the OIDC flow for Microsoft sign-in. We originally did not use this flow because the ID token returned has a “sub” claim that is different from the one returned from the userinfo endpoint which could result in some confusion. So we opted not to use that flow. However, we understand the value of having the ID token and we will look into it again.
It would be great if you could reconsider including the idtoken. I could always try to roll my own. First login using Azure and then use that token to invoke a trusted backend that can mint a token for custom firebase auth. But using two authentication systems in the same app seems a bit weird.
Any news on this? We ended up with first triggering the Azure AD login flow from the app which returns the MS ID token to the client. We use that to invoke a firebase function to create a custom firebase signin token with custom claims. The return that custom signing token to the client and use that to sign in with firebase. This works but it involves quite a number of network roundtrips and some brittle async code on the client. It would be so much better if the normal MS login with firebase would get the custom claims from the MS token.
I don't recall the details for this issue, but I know that we now start returning the Microsoft ID token:
Quoting the docs:
"In addition to the OAuth access token, the user's OAuth ID token can also be retrieved from the firebase.auth.UserCredential object. The sub claim in the ID token is app-specific and will not match the federated user identifier used by Firebase Auth and accessible via user.providerData[0].uid. The oid claim field should be used instead. When using a Azure AD tenant to sign-in, the oid claim will be an exact match. However for the non-tenant case, the oid field is padded. For a federated ID 4b2eabcdefghijkl, the oid will have have a form 00000000-0000-0000-4b2e-abcdefghijkl."
I have not tested it but can you check that the Microsoft ID token claims are propagated to the Firebase ID token claims? We do propagate them from OIDC ID tokens.
I just tested this and it has improved somewhat since I filed this issue. In auth().getRedirectResult() we get a promise with a AuthCredential object. This contains credentials.idToken with the encoded JWT ID token from Azure. (When using Typescript you first have to cast the credentials property to auth.OAuthCredential to get to this property by the way).
It's fairly simple to decode that ID token and in my case that contains the application roles:
{
...
"aud": "xxxxxxx-1f69-4940-xxxxx-xxxxxx",
"iss": "https://login.microsoftonline.com/xxxxxxxx-853c-48e4-9e55-xxxxxxxx/v2.0",
"iat": 1579812039,
...
"preferred_username": "[email protected]",
"roles": [
"any-role"
],
...
"ver": "2.0"
}
However, the claims (especially roles) are not included in the Firebase ID token:
{
"iss": "https://securetoken.google.com/project-xxxxx",
"aud": "project-xxxxx",
...
"firebase": {
"identities": {
"microsoft.com": [
"xxxxxxx-08fa-44f0-xxxx-xxxxxxxxxxxxx"
],
"email": [
"[email protected]"
]
},
"sign_in_provider": "microsoft.com"
}
}
The client application could simply look at the roles from the azure token, to change client side behavior. But it would be much better if the roles claim is also included in the Firebase token so we can use it in database rules and firebase functions.
We could use client code to invoke a firebase cloud function with the microsoft ID token, then modify the user claims from that trusted firebase cloud function and then refresh the firebase token on the client. But that seems a bit hacky (and slow).
Hello, same use case here, we are setting roles directly on Azure AD to manage users at scale. Being able to get the roles defined in AAD within the firebase id token would be a very useful addition for enterprise apps.
Hey @wvanderdeijl @DavMig, did you able to find any workaround for getting a role?
I tried to decode the IdToken but didn't get the role It would be great If you share the repo or sample code or any resource.
Thanks
@Shahzad6077 I am not the OP, but maybe this can help as I recently tried to sort this out myself.
Here I am using Angular/Typescript with the AngularFire plugin:
const provider = new OAuthProvider('microsoft.com');
signInWithPopup(this.auth, provider)
.then((result) => {
// The result object is NOT typed to include _tokenResponse, I found this property hidden in the console
let token = result['_tokenResponse']?.oauthIdToken;
// Azure returns the roles in THEIR oauth token which is found under this oauthIdToken property. This is NOT firebase's token
// This is the only place I have found where I can pickup the azure token
if (token) {
// JWT token has 3 parts; header, payload, signature, we only want the payload, split by '.' and get the 2nd entry
let payload = token.split('.')[1];
// Payload is a base64'd json string, parse and grab the roles
let roles = JSON.parse(atob(payload))?.roles;
// Do something with the roles variable
}
})
Hey! we have the same user case, any fix/workaround for this?