4
votes

I am trying to secure my web api (.net core 2.2) with Azure Ad using implicit flow.

I registered my application in Azure AD using the Azure Portal > Azure Active Directoy > App Registrations > New Application Registration:

Name = MyWebApi

Application Type = Web app / API

Sign-on URL = http://localhost:55000

Once this app is created, I opened its Manifest file and changed oauth2AllowImplicitFlow from false to true.

Thats all I did for the app registration in azure portal.

Then I called the following URL manually from my chrome browser to get access_token:

https://login.microsoftonline.com/MY-AD-TENANT-GUID/oauth2/v2.0/authorize?client_id=MY-REGISTERED-APP-GUID&response_type=token&redirect_uri=http%3A%2F%2Flocalhost%3A55000&scope=openid&response_mode=fragment

the response from calling the above url is:

http://localhost:55000/#access_token=MY-ACCESS-TOKEN&token_type=Bearer&expires_in=3600&scope=profile+openid+email+00000003-0000-0000-c000-000000000000%2fUser.Read&session_state=b2be972a-cfbc-49f1-bfc0-6c93f6c87d02

when I pass MY-ACCESS-TOKEN as Bearer token in Authorization header to my Web API (.net core 2.2) I get the following exception:

Microsoft.IdentityModel.Tokens.SecurityTokenInvalidSignatureException: IDX10511: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.X509SecurityKey , KeyId: N-lC0n-9DALqwhuHYnHQ63GeCXc'.

I then tried manually verifying the signature:

when I paste MY-ACCESS-TOKEN in https://jwt.io/ the header is:

{

  "typ": "JWT",

  "nonce": "AQABAAAAAACEfexXxjamQb3OeGQ4Gugvm6YdOT-bkA0IPllKMt06-J8If5AQ075TVCav94X_ZYcEYKaPneqdJcqYry-Z4XjX0eMN_fiJX_8wXe9D2b6eRiAA",

  "alg": "RS256",

  "x5t": "N-lC0n-9DALqwhuHYnHQ63GeCXc",

  "kid": "N-lC0n-9DALqwhuHYnHQ63GeCXc"

}

I then went to this URL to obtain the public key for kid: N-lC0n-9DALqwhuHYnHQ63GeCXc

https://login.microsoftonline.com/common/discovery/keys

I then pasted the following as a public key on jwt.io to validated token signature:

-----BEGIN CERTIFICATE-----

OBTAINED-PUBLIC-KEY-FROM-THE-ABOVE-URL-HERE

-----END CERTIFICATE-----

and I again get Invalid Signature.

I have been to this thread: https://github.com/AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet/issues/609, but I am not sure why does my token header has nonce value or if this is an issue at all in my case or not.

Any ideas what I am doing wrong here?

2
I see that the access token you're getting back also includes a scope for Microsoft Graph API.. I think that's the reason for Nonce also coming along.. and when an access token is meant for Microsoft Graph, you won't be able to validate it.. specifically 00000003-0000-0000-c000-000000000000/User.Read scope.. where 00000003-0000-0000-c000-000000000000 is the resource Id for Microsoft Graph API.. - Rohit Saigal
Any ideas why i am getting the scope for Microsoft Graph ? I have not requested it in my request. - M. Ali Iftikhar
In my opinion you should change your app to acquire an access token for your API. Since at the moment you aren't specifying which API you want it for. You can register the API as an app, define OAuth permissions on it, and assign permissions to your front-end app acquiring the token. - juunas
That is the eventual plan, but the concept is still the same. I have created the app registration for the API, and i am trying to access that API after obtaining its access token from azure AD. The issue is i guess related to nonce, and i am not sure why my azure ad tokens contain nonce when i am not requesting Microsoft graph scope. - M. Ali Iftikhar
It's good to see that you're already clear on registering API and eventual plan as you say. Another thing to notice.. You registered the application from regular Azure Portal (so it would accept v1 tokens by default).. but you're working with v2 endpoint to acquire token.. and as you aren't specifying which API you want token for, the endpoint is returning you a token for all the permissions that were statically defined at the time of registering your application. I think your app registraion might be having Microsoft Graph with User.Read selected under required permissions currently. - Rohit Saigal

2 Answers

4
votes

I tried this on my side, it worked well.

Request url:

https://login.microsoftonline.com/tenant-name/oauth2/v2.0/authorize?client_id=application_id&response_type=token&redirect_uri=https://snv2app.azurewebsites.net&scope=api://f3d966c0-517e-4e13-a5bb-9777a916b1a0/User.read openid&response_mode=fragment

And when I got the access_token, I parsed it in the jwt.io and entered the public key, I got the result:

enter image description here

3
votes

What is happening here is the token you are receiving is an access_token for the userInfo endpoint. The audience is graph. Tokens for graph have been modified in a special way so that they must be transformed before the signature can be validated. This allows for graph to forward the token downstream (after transforming) and not worry about a forwarding attack to occur.

To validate see if 'aud == graph'.