title: Correct way to setup IdentityServer4 Cookies for login, JWT token for API authorization
body: <p>We have one application that uses an IdentityServer4 cookies authorization scheme for user login like this:</p>
  <pre class="lang-cs prettyprint-override"><code>services.AddAuthentication(options =&gt;
          {
              options.DefaultAuthenticateScheme = &quot;Cookies&quot;;
              options.DefaultChallengeScheme = &quot;oidc&quot;;
          })
          .AddCookie(&quot;Cookies&quot;)
          .AddOpenIdConnect(&quot;oidc&quot;, options =&gt;
          {
              options.SignInScheme = &quot;Cookies&quot;;
              options.Authority = &lt;local IDP server with IdentityServer4&gt;;
              options.ClientId = &lt;ClientId&gt;;
              options.ClientSecret = &lt;secret&gt;
              options.ResponseType = &quot;code id_token&quot;;
              options.SaveTokens = true;
              options.GetClaimsFromUserInfoEndpoint = true;
              options.Scope.Add(&quot;openid&quot;);
              options.Scope.Add(&quot;profile&quot;);
              options.Scope.Add(&quot;offline_access&quot;);
          })
  </code></pre>
  <p>The client on the IDP looks like this:</p>
  <pre class="lang-cs prettyprint-override"><code>new Client
  {
      ClientId = &lt;ClientID&gt;,
      ClientName = &lt;ClientName&gt;,
      AllowedGrantTypes = GrantTypes.HybridAndClientCredentials,
      RequireConsent = true,
      ClientSecrets = { new Secret(&lt;secret&gt;.Sha256()) },
      AllowOfflineAccess = true,
      RedirectUris = { &quot;http://&quot; + ip + &quot;/signin-oidc&quot; },
      PostLogoutRedirectUris = { &quot;http://&quot; + ip + &quot;/signout-callback-oidc&quot; },
      AllowedScopes = {
              IdentityServerConstants.StandardScopes.OpenId,
              IdentityServerConstants.StandardScopes.Profile
          }
  };
  </code></pre>
  <p>We also have a WebAPI located at /api/...</p>
  <p>The goal is to add JWT Bearer Token authorization to the API. For that I have added the following code:</p>
  <pre class="lang-cs prettyprint-override"><code>        .AddJwtBearer(jwtOptions =&gt;
          {
              jwtOptions.Authority = &lt;local IDP server with IdentityServer4&gt;;
              jwtOptions.Audience = &lt;ClientID&gt;
              jwtOptions.SaveToken = true;
          })
  </code></pre>
  <p>The API is guarded with</p>
  <pre class="lang-cs prettyprint-override"><code>[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
  </code></pre>
  <p>After login, I get the token with</p>
  <pre class="lang-cs prettyprint-override"><code>await HttpContext.GetTokenAsync(&quot;access_token&quot;);
  </code></pre>
  <p>However, when I try to use that token to access the API, I get the following error:</p>
  <blockquote>
  <p>AuthenticationFailed: IDX10214: Audience validation failed. Audiences: 'http://localhost:50059/resources'. Did not match: validationParameters.ValidAudience: ClientID or validationParameters.ValidAudiences: 'null'.</p>
  </blockquote>
  <p>And indeed, when I decode the token using jwt.io, <code>aud</code> is set to <code>http://localhost:50059/resources</code>, while the ClientID appears as a new field <code>'client_id': '&lt;ClientID&gt;'</code>.</p>
  <p>What I found out so far suggests that <code>aud</code> is always set to <code>&lt;idp&gt;/resources</code> for access tokens and that API access is handled with scope claims inside the token. However, I do not understand how to set that up correctly.</p>
  <p>Does anybody know where the problem lies and how I can fix it?</p>