title: IDW10201: Neither scope or roles claim was found in the bearer token
body: <p>I have a ASP.NET Core 3.1 project like this sample: <a href="https://github.com/Azure-Samples/active-directory-dotnet-native-aspnetcore-v2/tree/master/1.%20Desktop%20app%20calls%20Web%20API" rel="noreferrer">Sign-in a user with the Microsoft Identity Platform in a WPF Desktop application and call an ASP.NET Core Web API</a>.</p>
  <p>I'm using <a href="https://github.com/AzureAD/microsoft-identity-web" rel="noreferrer"><code>Identity web</code></a> version 1.0 and Azure AD, single-tenant application.</p>
  <p>I've edited the manifest adding <code>appRoles</code> since I'm requesting an application token only, and not a user token:</p>
  <pre class="lang-json prettyprint-override"><code>[... more json ...]
  &quot;appId&quot;: &quot;&lt;guid&gt;&quot;,
  &quot;appRoles&quot;: [
      {
          &quot;allowedMemberTypes&quot;: [
              &quot;Application&quot;
          ],
          &quot;description&quot;: &quot;Accesses the application.&quot;,
          &quot;displayName&quot;: &quot;access_as_application&quot;,
          &quot;id&quot;: &quot;&lt;unique guid&gt;&quot;,
          &quot;isEnabled&quot;: true,
          &quot;lang&quot;: null,
          &quot;origin&quot;: &quot;Application&quot;,
          &quot;value&quot;: &quot;access_as_application&quot;
      }
  ],
  &quot;oauth2AllowUrlPathMatching&quot;: false,
  [... more json ...]
  </code></pre>
  <p>I've also enabled the <code>idtyp</code> access token claim, to specify that this is an application token.:</p>
  <pre class="lang-json prettyprint-override"><code>[... more json ...]
  &quot;optionalClaims&quot;: {
      &quot;idToken&quot;: [],
      &quot;accessToken&quot;: [
          {
              &quot;name&quot;: &quot;idtyp&quot;,
              &quot;source&quot;: null,
              &quot;essential&quot;: false,
              &quot;additionalProperties&quot;: []
          }
      ],
      &quot;saml2Token&quot;: []
  [... more json ...]
  </code></pre>
  <p>The following request is made with Postman. Please notice the use of <code>/.default</code> with the scope, which is mentioned in the documentation in relation to the <a href="https://docs.microsoft.com/en-us/azure/active-directory/develop/v2-permissions-and-consent#client-credentials-grant-flow-and-default" rel="noreferrer">client credentials grant flow</a>.</p>
  <pre class="lang-bash prettyprint-override"><code>POST /{tenant_id}/oauth2/v2.0/token HTTP/1.1
  Host: login.microsoftonline.com
  Content-Type: application/x-www-form-urlencoded
  
  scope=api%3A%2F%2{client_id}%2F.default
  &amp;client_id={client_id}
  &amp;grant_type=client_credentials
  &amp;client_secret={secret_key}
  </code></pre>
  <p>The request returns an <code>access_token</code> which can be viewed with <a href="https://jwt.ms" rel="noreferrer">jwt.ms</a> and looks like this, where actual data have been replaced by placeholders for security reasons.:</p>
  <pre class="lang-json prettyprint-override"><code>{
    &quot;typ&quot;: &quot;JWT&quot;,
    &quot;alg&quot;: &quot;RS256&quot;,
    &quot;x5t&quot;: &quot;[...]&quot;,
    &quot;kid&quot;: &quot;[...]&quot;
  }.{
    &quot;aud&quot;: &quot;api://&lt;client_id&gt;&quot;,
    &quot;iss&quot;: &quot;https://sts.windows.net/&lt;tenant_id&gt;/&quot;,
    &quot;iat&quot;: 1601803439,
    &quot;nbf&quot;: 1601803439,
    &quot;exp&quot;: 1601807339,
    &quot;aio&quot;: &quot;[...]==&quot;,
    &quot;appid&quot;: &quot;&lt;app id&gt;&quot;,
    &quot;appidacr&quot;: &quot;1&quot;,
    &quot;idp&quot;: &quot;https://sts.windows.net/&lt;tenant_id&gt;/&quot;,
    &quot;idtyp&quot;: &quot;app&quot;,
    &quot;oid&quot;: &quot;&lt;guid&gt;&quot;,
    &quot;rh&quot;: &quot;[..].&quot;,
    &quot;roles&quot;: [
      &quot;access_as_application&quot;
    ],
    &quot;sub&quot;: &quot;&lt;guid&gt;&quot;,
    &quot;tid&quot;: &quot;&lt;guid&gt;&quot;,
    &quot;uti&quot;: &quot;[...]&quot;,
    &quot;ver&quot;: &quot;1.0&quot;
  }
  </code></pre>
  <p>I notice that the token above does not include <code>scp</code>. This seem correct as this is an application token and not a user token. Instead it includes `”roles”´ as appropiate for an application token.</p>
  <p>The <code>access_token</code> can now be used as bearer in a Postman Get:</p>
  <pre class="lang-bash prettyprint-override"><code>GET /api/myapi
  Host: https://localhost:5001
  Authorization: Bearer {access_token}
  </code></pre>
  <p>The reponse to this request is <code>500 internal error</code>. I.e. something is wrong. The <code>access_token</code> looks like a corrent application token, so the error seems to be on the ASP.NET Core 3.1 controller side.</p>
  <p>The ASP.NET Core 3.1. project hosting the custom API, has a <code>startup.cs</code> which includes the following code:</p>
  <pre class="lang-cs prettyprint-override"><code>services.AddMicrosoftIdentityWebApiAuthentication(Configuration);
  
  // This is added for the sole purpose to highlight the origin of the exception.
  services.Configure&lt;JwtBearerOptions&gt;(JwtBearerDefaults.AuthenticationScheme, options =&gt;
  {
      var existingOnTokenValidatedHandler = options.Events.OnTokenValidated;
      
      options.Events.OnTokenValidated = async context =&gt;
      {
          if (context.Principal.Claims.All(x =&gt; x.Type != ClaimConstants.Scope)
              &amp;&amp; context.Principal.Claims.All(y =&gt; y.Type != ClaimConstants.Scp)
              &amp;&amp; context.Principal.Claims.All(y =&gt; y.Type != ClaimConstants.Roles))
          {
              // This where the exception originates from:
              throw new UnauthorizedAccessException(&quot;Neither scope or roles claim was found in the bearer token.&quot;);
          }
      };
  });
  </code></pre>
  <p>The <code>appsettings.json</code> for the project includes:</p>
  <pre class="lang-json prettyprint-override"><code>&quot;AzureAD&quot;: {
      &quot;Instance&quot;: &quot;https://login.microsoftonline.com/&quot;,
      &quot;Domain&quot;: &quot;mydomain.onmicrosoft.com&quot;,
      &quot;ClientId&quot;: &quot;&lt;client_id&gt;&quot;,
      &quot;TenantId&quot;: &quot;&lt;tenant_id&gt;&quot;,
      &quot;Audience&quot;: &quot;api://&lt;client_id&gt;&quot;
  },
  </code></pre>
  <p>... and the controller looks like this:</p>
  <pre class="lang-json prettyprint-override"><code>[Authorize]
  [Route(&quot;api/[controller]&quot;)]
  public class MyApiController : Controller
  {
      [HttpGet]
      public async Task&lt;string&gt; Get()
      {
          return &quot;Hello world!&quot;;
      }
  }
  </code></pre>
  <p>The underlying cause of the <code>500 internal error</code> is that this exception is thrown: <code>IDW10201: Neither scope or roles claim was found in the bearer token.</code> exception.</p>
  <p><strong>UPDATE:</strong></p>
  <p>(Please see the answer below for even more details).</p>
  <p>This video on &quot;<a href="https://youtu.be/LRoc-na27l0?t=954" rel="noreferrer">Implementing Authorization in your Applications with Microsoft identity platform - june 2020</a>&quot; suggests that the missing piece is this flag <code>JwtSecurityTokenHandler.DefaultMapInboundClaims = false;</code> which need to be set in <code>startup.cs</code> - e.g:</p>
  <pre class="lang-cs prettyprint-override"><code>public void ConfigureServices(IServiceCollection services)
  {
      // By default, the claims mapping will map clain names in the old format to accommodate older SAML applications.
      //'http://schemas.microsodt.com/ws/2008/06/identity/clains/role' instead of 'roles'
      // This flag ensures that the ClaimsIdentity claims collection will be build from the claims in the token
      JwtSecurityTokenHandler.DefaultMapInboundClaims = false;
      
      [...more code...]
  
  </code></pre>