latest
I do the requests to get an access token :
import * as Msal from 'msal';
const MSAL = new Msal.UserAgentApplication({
auth: {
clientId: ***,
authority: ***,
},
cache: {
cacheLocation: 'localStorage',
storeAuthStateInCookie: true
}
});
await MSAL.loginPopup({})
const tokenResponse = await MSAL.acquireTokenSilent({
scopes: ['user.read']
});
// Send to my server API => cannot validate the access token
I see that this issue exists on others libs https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609
I have a nonce in my token when I decode it in https://jwt.io/
Two options :
Shouldn't the first option be "Getting an access token __without__ a nonce" ?
Shouldn't the first option be "Getting an access token without a nonce" ?
edited
You shouldn't need to validate the Graph token. When you make a call to the Graph API, and if the token is expired/invalid, the graph api will spit back an appropriate 401/3, which you can detect. You can open the token and read the exp claim to predict if the token is expired.
You should also not use this token as authorization for your application, this token is specifically for the graph api. You should create your own application in Azure or some other Identity provider. This way you can validate that token to make sure the user is who they say they are.
Side note: If you utilize an Azure application you can perform an on-behalf-of flow with the user's token to generate the graph api token from your application's token preventing the user logging in twice.
@jvandervelden I think I'm in the same boat as @fabien-h because I tried to validate the Access Token. I'm not using the Graph API, I have my own API which serves protected data, and a Javascript SPA which calls the API to shows data to user.
So I was sending the Access Token as a Bearer in the Authorization header. I tried to validate this access token by calling https://login.microsoftonline.com/common/discovery/keys (or the one with my tenant) and extracting the public key. Unfortunately there is a special treatment made on the nonce in header of the access token which makes it not valid with the public key provided.
What I may have misunderstood, is that I should not use the access token for my own API, but the id token instead. If i refer to this doc : https://docs.microsoft.com/en-us/azure/active-directory/develop/single-page-application , it's stated :
- The browser calls the application鈥檚 web API back end with the ID token in the authorization header. The Azure AD authentication service issues an ID token that can be used as a bearer token if the resource is the same as the client ID (in this case, this is true as the web API is the app's own backend).
So in my case should I use the id token ? If so, the docs here https://docs.microsoft.com/en-us/azure/active-directory/develop/id-tokens is kind of confusing :
ID Tokens should be used to validate that a user is who they claim to be and get additional useful information about them - it shouldn't be used for authorization in place of an access token.
@cforycki what resource are you creating the token for? Can you provide a sample?
Our tokens don't haven an NONCE in the header, but we are still using v1 of the token api. But I doubt MS added an NONCE header in v2 for custom apps.
@jvandervelden Right now I can't provide a complete example but I can try to explain it.
I'm currently working on a JS app that shows data to user. As the data should be protected, and only employee should be able to access the app, I use this library to handle the authentication (I redirect them if they are not already logged in). All employee have a MS Enterprise account (don't know if it's the exact wording).
There is no data on the JS part on it's own. All data are coming from a REST Api made with Spring Boot. These kind of architecture is of classic these days.
Usually what I do for my own apps, account data are on my side, so I just authenticate the user with a /login endpoint, and if successful, I send back the JWT in a http-only cookie. The frontend then send back the JWT in Authorization header for each call it makes.
But, this time, the account are not managed by me, they are available through Azure AD. So for me it should be fairly similar, except I'm not the one creating the JWT. But I still need to validate this JWT on the backend, in order to authorize the user to access data.
The backend (REST Api), the frontend (JS SPA), database etc... everything is on our side, not hosted by Microsoft at all, but I do have a registered app in the portal for the client-side redirection.
I only want to protect my API and authorize the employee which are connected through Azure.
I hope it's better explained this way.
Yeah, that's what we are doing. We have an app registration in Azure and do an OAuth2.0 authorization code flow with that appid/secret (Spring Boot backend). The tokens we get back from MS can be validated with the well known url provided by MS.
Are you using v1 or v2 of the token api?
@jvandervelden At least I'm not doing something completely wrong 馃槃
I'm using the latest version of this library, and by default everything use v2.0.
I know we have some older apps that works with v1.0, and they don't have any problems.
Huh, I'll have to remember that when we look at migrating.
Hi , i am facing the same problem , i am using angular 7 , and for authentication using adal-angular 4 librabry . making an implicit grant callback, getting the token in adalObject . but when i make the api call to get the users , saying not authorized. and i validated my token in jwt.io , there is not nonce in the token.
my config to implicti way is :
config: {
app_displayname: "my-app-name",
response_type: 'id_token token',
instance: 'https://login.microsoftonline.com/',
tenant: 'mt tenant',
clientId: 'my client id',
endpoints: {
'https://graph.microsoft.com': 'my client id',
},
redirectUri: 'http://localhost:4200',
state: '12345S',
scopes: ['profile', 'offline_access'],
cacheLocation: 'localStorage',
}.
please help me how to get the nonce property in my token , or is there any other way to get the token with nonce.
i tried code authorization way also but didnt see any angular7 , azure ad example. not able to login in code way.
if code authorization is the way to get the nonce in my token , please help me how to do with angullar7 and adal-angular 4 version.
Thank you in advance.
Hi @vishwanathsunkari,
Make sure your application has the permissions required to get all users in your AD (https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis#add-permissions-to-access-web-apis). Querying all users requires the user to have more elevated permissions than just querying the user's information, so make sure the logged in user has access to the information.
Jasper
Closing this, as clients should not try to validate access tokens meant for Graph. Please see this comment for more info: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609#issuecomment-524434987
the funny part, is, that server just returns RS256 in header, but actually to valdate, it needs to be HS256, so if you change manually, and pack hader back to Base64 bit, chainging RS256 to HS265, validation passes
See my comment here: https://github.com/AzureAD/microsoft-authentication-library-for-js/issues/521#issuecomment-577400515
Thanks @funcelotwork! Working like a charm!
it needs to be HS256, so if you change manually, and pack hader back to Base64 bit, chainging RS256 to HS265, validation passes
I tried to do that too, but still got _invalid signature_
@funcelotwork @fippli Can you please detail exactly how you were able to correct the token by changing the value?
If anyone has an example in nodejs it would be perfect
@bzivyon I think this ended up being a false solution to the problem for me. Figured out that the access token is not supposed to be validated. The solution was to instead use the id token and validate it through my backend. Im doing something like this:
// Some frontend code
msalInstance
.acquireTokenSilent({ scopes: [ 'user.read' ] })
.then((response) => {
const { idToken: { rawIdToken } } = response;
});
I then validate the id token on backend with a relevant jwt library.
I wonder though -- the id_token only tells me WHO it is, not whether or not they are supposed to have access to my API (unless I keep my own db of users who are supposed to access my API). Therefore, I'd expect some mechanism to either validate the access_token returned from msal or one that can give me the access_token to my API.
Here is the solution
If you need access MS graph, in addition to your API, then you must manage two separate tokens
I don't know you, but for the next 24h, you are my favorite person in the world.
// REACT CODE
const msalSuccessHandler =(authResponse: Msal.AuthResponse) => {
console.log("MSAL Success.");
setError(undefined);
setAuthResponse(authResponse);
clientApplication.acquireTokenSilent({ scopes: ['openid', "api://xxxx/access"] })
.then((result: Msal.AuthResponse) => { console.log("access token with only openid", result); setAccessToken(result.accessToken); })
.catch((err) => { console.log(err); })
};
I've read too quickly over the article and in case it is yours, you could improve it in giving an example of the call (with openid+api scopes). Needed to reread multiple times to get it right.
Thanks for helping me out!
Most helpful comment
the funny part, is, that server just returns RS256 in header, but actually to valdate, it needs to be HS256, so if you change manually, and pack hader back to Base64 bit, chainging RS256 to HS265, validation passes