microsoft-authentication-library-for-js: Invalid Issuer (iss: when acquiring token

I’m submitting a…

  • Regression (a behavior that used to work and stopped working in a new release)
  • Bug report
  • Performance issue
  • Feature request
  • Documentation issue or request
  • Other… Please describe: Help


  • Chrome version XX
  • Firefox version XX
  • IE version XX
  • Edge version XX
  • Safari version XX

Library version

Library version: 0.2.4

Current behavior

The acquired access_token appears to have the wrong issuer, and my ASP.NET Core API rejects the token due to The issuer is invalid.

The decoded access token looks like:

  "aud": "api://{clientId}",
  "iss": "{tenantId}/",
  "ver": "1.0"

Shouldn’t the token issuer be:{tenantId}/v2.0? Is this an issue with my Azure AD, or a MSAL.js configuration issue?

When I change to my API options to o.TokenValidationParameters.ValidateIssuer = false; it works fine. The registered app is meant to be isolated to a single AAD tenant.

Expected behavior

The access token’s issuer should be:{tenantId}/v2.0

Minimal reproduction of the problem with instructions

When I use MSAL.js to acquire token via:

msal = new msal.UserAgentApplication(
      () => {},
        redirectUri: 'http://localhost:3001/',
        storeAuthStateInCookie: true,
        cacheLocation: 'sessionStorage'

      (accessToken) => {
        return accessToken;
      () => {
        // Open a redirect page in case the token is bad

The returned access token is:

  "aud": "api://{clientId}",
  "iss": "{tenantId}/",
  "ver": "1.0"

When I use the accessToken to hit my ASP.NET Core Web API, I get a response with error="invalid_token", error_description="The issuer is invalid".

When I configure the API to skip checking the issuer, the API calls works fine.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 29 (6 by maintainers)

Most upvoted comments

I believe this is a configuration issue in the Azure AD App Registration. There is a field called accessTokenAcceptedVersion then when left null defaults to v1.0. It must be changed to 2 so that tokens are generated in the v2.0 format.

@mpalumbo7 Thank you for this hint. I’ve updated Azure App manifest file with the "accessTokenAcceptedVersion": 2, and it started to generate correct token.

The most strange thing is getting v1.0 token if I’m asking for token from the{tenant}/oauth2/v2.0/token endpoint…

@jasonnutter I understand that, but I find it strange that by default, the issuer in the token doesn’t match the one in the metadata. If you just rely on the metadata to configure token validation (which I usually do), it’s broken by default; that’s hardly ideal…

Changing the token version will not change the issuer. The issuer is changed when you use a different endpoint; so use the Azure AD V2 endpoint instead of the V1 endpoint (e.g. the one like

@tinodo this is not accurate. When an API (the resource AKA target AKA scope-owner of the access token) changes their token version, it does change the issuer of the access tokens issued for that API. Every API sets this differently, so depending on the API you plan to call, you may get tokens with different issuers and token versions. If you have encountered behavior that runs opposite to this I’d love to investigate it as it means we have issues in our token service.

ID tokens are issue based on the endpoint used, so all ID tokens issued to MSAL will be v2.0 and have the issuer.

For reference:

  1. Every single token (access or ID) issued with a v1.0 fomat will have issuer (assuming the worldwide cloud and not a national one)
  2. Every single token (access or ID) issued with a v2.0 format will have issuer
  3. Every single ID token issued by the v1 endpoint (used by ADAL) is v1 format.
  4. Every single ID token issued by the v2 endpoint (used by MSAL) is v2 format.
  5. Every single access token is issued with the format from the API’s registration, and can be issued from either endpoint.

So @saurabhjain-MA - can you clarify that you are getting a token for the same resource in both calls? And that both are access tokens? And they have different issuers?

As a closing reminder - only the app in the audience of a token should ever, ever, ever look inside the access token. Access tokens are completely and utterly controlled by the API, and never, in any way, by the client requesting them. They can be encrypted, change versions, or have claims added or removed without warning to you. If your app takes a dependency on the format or on validating tokens for other applications, you have a potential security issue and a guaranteed reliability issue.