Skip to content

Cannot validate signature. #609

@jvandervelden

Description

@jvandervelden

I am trying to use this library to validate the tokens I receive from our UI. The UI gets it from a login web app that is registered with Azure AD.

I have setup a simple application that takes a token and tries to validate the signature found here: https://github.com/jvandervelden/test-azure-ad-identiymodel-connect
The class that's doing the validation is here: https://github.com/jvandervelden/test-azure-ad-identiymodel-connect/blob/master/TestStuff/TokenValidator.cs

The error I am getting is: 'IDX10503: Signature validation failed. Keys tried: 'Microsoft.IdentityModel.Tokens.X509SecurityKey , KeyId: z039zdsFuizpBfBVK1Tn25QHYO0'

Simple application with the error:

Any help would be appreciated.

Using NuGet packages:

Microsoft.IdentityModel.Protocols v2.1.3
Microsoft.IdentityModel.Protocols v2.1.3
Microsoft.IdentityModel.Tokens v5.1.3
System.IdentityModel.Tokens.Jwt v5.1.3

Activity

brentschmaltz

brentschmaltz commented on May 3, 2017

@brentschmaltz
Member

@jvandervelden is there a possibility you can share the 'jwt'. You can email me directly if it contains sensitive info.

jvandervelden

jvandervelden commented on May 3, 2017

@jvandervelden
Author

@brentschmaltz No Problem, it's in the image anyway, and it's a test tenancy.

deleted this token as I now understand it's purpose

jvandervelden

jvandervelden commented on May 5, 2017

@jvandervelden
Author

@brentschmaltz We have a custom web app registered with our AD that does logins. When you request a login from our app it redirects you to the login.microsoftonline.com page: (https://login.microsoftonline.com/common/oauth2/authorize?response_type=code%20id_token&scope=openid&response_mode=form_post&redirect_uri=http%3A%2F%2Flocalhost%3A8089%2Fsecure%2Flogin&client_id=409e2f16-9ace-4e18-acc3-4c7f6a6fba3a&resource=https://graph.microsoft.com/&nonce=da3d8159-f9f6-4fa8-bbf8-9a2cd108a261&site_id=500879). This posts pack and access code we then use to get a token from: (https://login.microsoftonline.com/common/oauth2/token) which then gives us back the JWT token that I posted.

We use the ADAL for java library to get the token.

brentschmaltz

brentschmaltz commented on May 5, 2017

@brentschmaltz
Member

@jvandervelden OK that explains it then. I missed it before, but if look at the Jwt.Header you will see a 'nonce'. This means you need special processing. Normal processing will fail.

jvandervelden

jvandervelden commented on May 5, 2017

@jvandervelden
Author

@brentschmaltz So what's your suggestion? Should I remove the nonce from the login url? We are going to attempt to validate these in nginx lua and I don't really want to add extra pain.

brentschmaltz

brentschmaltz commented on May 5, 2017

@brentschmaltz
Member

@jvandervelden i need to understand your topology better.
Also what scenario are you trying to implement? The token you have is for graph, why are you trying to validate it?

brentschmaltz

brentschmaltz commented on May 6, 2017

@brentschmaltz
Member

@jvandervelden I am going to close this as not supported.

jvandervelden

jvandervelden commented on May 8, 2017

@jvandervelden
Author

@brentschmaltz Here (https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-token-and-claims) states I should be able to validate the id_token and the access_token the same way. When I get to this section (https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-token-and-claims#validating-tokens) it gives an example project for manually validating tokens (https://github.com/Azure-Samples/active-directory-dotnet-webapi-manual-jwt-validation). I ran this project and gave it an id_token which worked, I then gave it my access token which failed with the same error I was seeing.

I tried updating my login url so I didn't have to provide an 'NONCE' parameter which was fine, I got the access_code and sent that on to the token endpoint. No matter what I do the 'NONCE' value is always in the header of my access_token:

Getting the access_token:
image

Token:
eyJ0eXAiOiJKV1QiLCJub25jZSI6IkFRQUJBQUFBQUFCbmZpRy1tQTZOVGFlN0NkV1c3UWZkcl92QTF0ZF9LSjU1dWV3elY4dUEtc0dPaXBSS3puUEZQenZxNTVmUDhlaTFDcm95Qk9HWThWVjdtTVhJNndKUlNNbkxUUGxPdlNValV2NFlvLUswX3lBQSIsImFsZyI6IlJTMjU2IiwieDV0IjoiejAzOXpkc0Z1aXpwQmZCVksxVG4yNVFIWU8wIiwia2lkIjoiejAzOXpkc0Z1aXpwQmZCVksxVG4yNVFIWU8wIn0.eyJhdWQiOiJodHRwczovL2dyYXBoLm1pY3Jvc29mdC5jb20vIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvNWFmYTgwYjUtN2FjNS00MWY3LWIxZjktMDU4MDE5NWIwZDk5LyIsImlhdCI6MTQ5NDI1NTY0MCwibmJmIjoxNDk0MjU1NjQwLCJleHAiOjE0OTQyNTk1NDAsImFjciI6IjEiLCJhaW8iOiJZMlpnWUxpVXZuYnFkcjM5YWVKYzJtR01MaGRtSjdQY0tlallGSk84NVZlZHd1c1pMaDBBIiwiYW1yIjpbInB3ZCJdLCJhcHBfZGlzcGxheW5hbWUiOiJUZXN0QyMiLCJhcHBpZCI6IjQwOWUyZjE2LTlhY2UtNGUxOC1hY2MzLTRjN2Y2YTZmYmEzYSIsImFwcGlkYWNyIjoiMSIsImlwYWRkciI6IjY0LjIzNS4xMDAuNiIsIm5hbWUiOiJKYXNwZXIgVXB0dXJuIiwib2lkIjoiMGZlNzE4ZjQtNWUxYS00MDI5LTk4MmQtZjU0YjQxZTRkMzA2IiwicGxhdGYiOiIzIiwicHVpZCI6IjEwMDM3RkZFQTBDNEZBMkEiLCJzY3AiOiJEaXJlY3RvcnkuQWNjZXNzQXNVc2VyLkFsbCBVc2VyLlJlYWQiLCJzdWIiOiJKcl80X2U5cnRCNS0zZUdtbmxjMmhqWEpyNXZHMVRoUmZyLXhOeHhSR3drIiwidGlkIjoiNWFmYTgwYjUtN2FjNS00MWY3LWIxZjktMDU4MDE5NWIwZDk5IiwidW5pcXVlX25hbWUiOiJqYXNwZXJAdmFuZGVydmVsZGVucy5jYSIsInVwbiI6Imphc3BlckB2YW5kZXJ2ZWxkZW5zLmNhIiwidXRpIjoiRDFqanZXUGVQMDZLZElKSGdPUS1BQSIsInZlciI6IjEuMCIsIndpZHMiOlsiNjJlOTAzOTQtNjlmNS00MjM3LTkxOTAtMDEyMTc3MTQ1ZTEwIl19.ARoy6EBl1UM1U3_uStikPvOND-Y7otrZxVvyunAMrV6D1Wga1CIJJ5UxFpUE-MAwdebj1Pv_YsQ9o3Ys3i9qroAYoiJUDtycqW0iX1sNeoCndm147K3OlcnIQpcw2zupxOFCkecV_kmVroQGTcod4Gtni3P2uTdmeGAJABgf0wa6D0fplYd_GLwkuz1QAXjHe6LsmGwj-5iG7Oquy1mLTEZ4ptyaGSiM5Bv9GGXK1ZyJrDyJVV06cX-VbHF_EiKZlHFzH2OC8hFgyjdP5hPmQAaeSeFPCIir1qEhhSwIIzl7lzDJzNJjU5_dH88QBgA2NVcN8uWI-QniBvr6GrBG3A

Header:
{
"typ": "JWT",
"nonce": "AQABAAAAAABnfiG-mA6NTae7CdWW7Qfdr_vA1td_KJ55uewzV8uA-sGOipRKznPFPzvq55fP8ei1CroyBOGY8VV7mMXI6wJRSMnLTPlOvSUjUv4Yo-K0_yAA",
"alg": "RS256",
"x5t": "z039zdsFuizpBfBVK1Tn25QHYO0",
"kid": "z039zdsFuizpBfBVK1Tn25QHYO0"
}

So what we are doing is, we have a login web app that handles the authentication portion of our system. The user hits 'https://login.ourwebapp.com/secure/login?webApp=https://cloud.ourwebapp.com/'. This redirects them to 'https://login.microsoftonline.com?redirect=https://login.ourwebapp.com&client_id...'. Once the user logins to the azure portal it posts back the access_token to the login webapp. The login web app then uses the ADAL4j library to get the access_token using the access_code provided. It then redirects the user to the webApp url passed in the initial request with the access_token. The second webApp then utilizes this token to validate the user is authenticated and can access it's data. This second web app is where we need to validate the token to make sure the user is authenticated.

jvandervelden

jvandervelden commented on May 10, 2017

@jvandervelden
Author

@brentschmaltz thank you for your help, I figured out my issue. I was trying to validate an access token that was for the graph api. I created an access token for my web app and I can validate the token now.

chetanku

chetanku commented on Apr 16, 2018

@chetanku

Hello,
How was this resolved?
I have an access token that I receive from Graph API. I am trying to validate it with the key found in the https://login.microsoftonline.com/common/discovery/keys. I am using jwt.io. But it fails with Invalid Signature. The token has nonce value. What kind of special processing is required? My goal is to send the token in headers to my api and get the token validated using jwt token validation method. Any help will be great, stuck in this since past few days.

brentschmaltz

brentschmaltz commented on Apr 16, 2018

@brentschmaltz
Member

@chetanku a token from Graph that has a 'nonce' requires special processing to validate the signature

77 remaining items

alfonsrv

alfonsrv commented on Jan 27, 2024

@alfonsrv

But why does the https://login.microsoftonline.com/common/discovery/keys endpoint have to expose the same kids as referenced in the tokens used for Graph API? I feel like this just adds unnecessary confusion.

While all of this makes sense (still I don't quite get why we cannot validate a Graph API token), this evidently very common misunderstanding and dozens of hours troubleshooting could have easily been avoided. Not surprised – since: Micro$oft – but what a frustrating shit show journey it has been.

DinoChiesa

DinoChiesa commented on Jan 29, 2024

@DinoChiesa

still I don't quite get why we cannot validate a Graph API token

It's not a JWT. It is a TOKEN, of course, but not a JSON Web TOKEN (JWT). Because it's not a JWT, It cannot be validated as if it is a JWT. It looks similar to a JWT, and that has been a source of confusion. But it's not a JWT. That is why you cannot validate it, as if it were a JWT.

why does the https://login.microsoftonline.com/common/discovery/keys endpoint have to expose the same kids as referenced in the tokens used for Graph API? I feel like this just adds unnecessary confusion.

I agree.

chandankgonu

chandankgonu commented on Feb 14, 2024

@chandankgonu

I have same issue Azure AD as has two types of token one is Application Token(able to validate through the Springboot application), 2nd is user token(generated through redirect to your windows login postman://app/oauth2/callback?code=0.AVQAURia5c-_**** login) this token not able to validate.

getting error --- Failed to authenticate since the JWT was invalid

maxkoryukov

maxkoryukov commented on May 6, 2024

@maxkoryukov

It's not a JWT. It is a TOKEN, of course, but not a JSON Web TOKEN (JWT). Because it's not a JWT, It cannot be validated as if it is a JWT. It looks similar to a JWT, and that has been a source of confusion. But it's not a JWT. That is why you cannot validate it, as if it were a JWT.

it is the best explanation for what happened. we just must not validate those MS tokens


on the other hand, the access_token looks like JWT, it behaves like JWT, we find it where we usually see JWT, his neighbor id_token is a JWT (still), and there is a JWKS-architecture — everything tells us "it is JWT". and in fact it is "almost JWT", but "improved" by Microsoft and we get it from another public Identity Provider.

we have a number of Identity Providers, how many of them use such "customizations"?

actually, I wouldn't sob here "MS stole hours of my time", in fact - my bad, I should read the docs better because they don't call it "JWT".

now, it's time for conspiracy theories: it is not the first time we have seen this iconic MS approach. At least, with Entra and its tokens, they won't be able to "embrace" [/conspiracy mode off]

jmprieur

jmprieur commented on May 6, 2024

@jmprieur
Contributor

@maxkoryukov : why would you validate an MS token if you are not the owner of the web API that accepts this token?

maxkoryukov

maxkoryukov commented on May 6, 2024

@maxkoryukov

@jmprieur most probably after the whole discussion, I'm way out of the topic.

answering the question: I use several fields from the token and sometimes I need to call Graph API (but in many cases, info from the token is enough).

anyway, the issue's header says "Cannot validate signature". Also my question was: why can't I validate something that is supposed to be "validatable"? It is an open standard of JWT that MS has adopted, excepting the "validation" step where a "special processing" is required (deja vu).

now my application (which strives to be IdP independent) can validate any token, with an exception for Entra's ones.

maxkoryukov

maxkoryukov commented on May 8, 2024

@maxkoryukov

@jmprieur @brentschmaltz (or ping other MS people who could help)

this page: https://learn.microsoft.com/en-us/entra/identity-platform/access-token-claims-reference --- also needs an update, because it still states "Access tokens are JSON web tokens" and there is nothing about "special processing" on the page.

A lot of other pages already have warnings "do not try to validate accessToken at home", with these warnings it is easier to avoid a lot of troubles and wasted time

mmuzammil196

mmuzammil196 commented on Aug 8, 2024

@mmuzammil196

When working with Azure Entra ID, it's important to understand the purpose of the tokens provided:

Access Token: This token is primarily used for authorizing access to APIs like Microsoft Graph. It is issued for a specific audience (API/resource) and may not contain the necessary claims for user authentication. If you're trying to validate this token for user identity, it might not work as expected because it's not designed for that purpose.

ID Token: The id_token is specifically designed for user authentication. It contains claims such as the user's identity, email, and other profile information. This token is what you should validate when you want to verify the user's identity in your application.

DinoChiesa

DinoChiesa commented on Mar 30, 2025

@DinoChiesa

When working with Azure Entra ID, it's important to understand the purpose of the tokens provided:

Access Token: This token is primarily used for authorizing access to APIs like Microsoft Graph. It is issued for a specific audience (API/resource) and may not contain the necessary claims for user authentication. If you're trying to validate this token for user identity, it might not work as expected because it's not designed for that purpose.

You're saying the access token is not an ID token. OK, this is true, and beside the point. The discussion here is that people are trying to validate the signature on the access token. Nobody above (as far as I know, I haven't reviewed the entire thread carefully) said anything about "validate this token for user identity". The main problem is people are trying to validate the signature and are confused (justifiably in my opinion) about why it does not work. As explained above, the signature cannot be verified because despite appearances, the token is not a JWT.

About all the trouble using tokens dispensed from this endpoint,

  • Microsoft will say to developers: you're using the wrong scope.
  • Developers will say to Microsoft: you made it very confusing for us.

Both are right.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Customer reportedIndicates issue was opened by customerInvestigateWe are not quite sure what the issue is.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      No branches or pull requests

        Participants

        @zbrad@DinoChiesa@homutov@metaclassing@somdey

        Issue actions

          Cannot validate signature. · Issue #609 · AzureAD/azure-activedirectory-identitymodel-extensions-for-dotnet