Andreas Sjöberg
Andreas Sjöberg

Reputation: 42

Wrong audience for id_token in IdentityServer4

I'm trying to setup a solution with the following:
- IdentityServer4 instance
- React / js client
- ASP.NET Core API (protected by IdentityServer)

Since I want to use roles and claims, I would like to use a reference token (id_token) and have the API verify the claims against the IdentityServer.

Reference token flow

Configuration for the IdentityServer instance:

  "IdentityServer": {
    "IdentityResources": [
      "openid",
      "email",
      "phone",
      "profile"
    ],
    "ApiResources": [
      {
        "Name": "b2a6f5a1-9317-4b2f-bb02-c2f7cd70ce9a",
        "DisplayName": "My API",
        "ApiSecrets": [ { "Value": "<BASE 64 ENCODED SHA256 HASH OF SECRET>" } ]
      }
    ],
    "Clients": [
      {
        "Enabled": true,
        "ClientId": "976d5079-f190-41a2-a6f6-be92470bacc0",
        "ClientName": "My JS client",
        "ClientUri": "http://localhost:3000",
        "LogoUri": "logo.png",
        "RequireClientSecret": false,
        "AllowAccessTokensViaBrowser": true,
        "RequireConsent": false,
        "ClientClaimsPrefix": null,
        "AccessTokenType": "reference",
        "AllowedGrantTypes": [ "implicit" ],
        "RedirectUris": [ "http://localhost:3000/authentication/login-callback" ],
        "PostLogoutRedirectUris": [ "http://localhost:3000/authentication/logout-callback" ],
        "AllowedCorsOrigins": [ "http://localhost:3000" ],
        "AllowedScopes": [ "openid", "email", "phone", "profile", "b2a6f5a1-9317-4b2f-bb02-c2f7cd70ce9a" ]
      }
    ]
  } 

Configuration for the (protected) API:

  "Identity": {
    "Authority": "https://localhost:44311",
    "ApiName": "b2a6f5a1-9317-4b2f-bb02-c2f7cd70ce9a",
    "ApiSecret": "<UNHASHED SECRET>"
  }

Startup.cs for the API:

services.AddAuthentication(options =>
    {
        options.DefaultAuthenticateScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
        options.DefaultChallengeScheme = IdentityServerAuthenticationDefaults.AuthenticationScheme;
    })
    .AddIdentityServerAuthentication(options =>
    {
        options.Authority = Configuration.GetValue<string>("Identity:Authority");
        options.ApiName = Configuration.GetValue<string>("Identity:ApiName");
        options.ApiSecret = Configuration.GetValue<string>("Identity:ApiSecret");
    });

I query IdentityServer for an id_token with the following parameters:

export const Settings: any = {
    authority: "https://localhost:44311",
    post_logout_redirect_uri: "http://localhost:3000/authentication/logout-callback",
    redirect_uri: "http://localhost:3000/authentication/login-callback",
    response_type: "id_token",
    scope: "openid email profile phone b2a6f5a1-9317-4b2f-bb02-c2f7cd70ce9a"
};

I get the following error: Requests for id_token response type only must not include resource scopes.

If I change the scope to:

export const Settings: any = {
    // ...
    scope: "openid email profile phone" // removed (protected) api resource
};

it works and I get an id_token like this:

{
  "nbf": 1573798909,
  "exp": 1573799209,
  "iss": "https://localhost:44311",
  "aud": "976d5079-f190-41a2-a6f6-be92470bacc0",
  "nonce": "d768a177af684324b30ba73116a0ae79",
  "iat": 1573798909,
  "s_hash": "HbWErYNKpgsiOIO82IiReA",
  "sid": "vVWVhLnVLiCMdLSBWnVUQA",
  "sub": "90f84a26-f756-4923-9d26-6104eef031ac",
  "auth_time": 1573798909,
  "idp": "local",
  "preferred_username": "noreply",
  "name": "noreply",
  "email": "[email protected]",
  "email_verified": false,
  "amr": [
    "pwd"
  ]
}

Note that the audience is 976d5079-f190-41a2-a6f6-be92470bacc0, which is the js client.
When I use this token on the protected API, it says:

Bearer error="invalid_token", error_description="The audience '976d5079-f190-41a2-a6f6-be92470bacc0' is invalid"

which is not that strange since the API has the id b2a6f5a1-9317-4b2f-bb02-c2f7cd70ce9a.

So my question is: Where am I wrong? How do I get the token for the correct audience?

Upvotes: 0

Views: 1959

Answers (1)

Nan Yu
Nan Yu

Reputation: 27528

The ID token will be validated by your client app (React/js) app to get user claims , so the audience is your client app's client ID . A token passe to your web api should be validated by web api , so the audience is web api's name .

The ID token contains information about an End-User which is not used to access protected resource , while Access token allows access to certain defined server resources .You can set response_type to id_token token , and add api name/scope to scope configuration . With implicit flow , after authentication , client will get one ID token and one Access token , you can now use access token to access the protected web api .

Upvotes: 1

Related Questions