Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Invalid Token - The audience 'empty' is invalid

I have the following Identity Server 4 configuration on ASP.NET Core 3.1 projects:

services
  .AddIdentityServer(y => {
    y.Events.RaiseErrorEvents = true;
    y.Events.RaiseInformationEvents = true;
    y.Events.RaiseFailureEvents = true;
    y.Events.RaiseSuccessEvents = true;
  })
  .AddDeveloperSigningCredential()
  .AddInMemoryPersistedGrants()
  .AddInMemoryIdentityResources(Config.IdentityResources())
  .AddInMemoryApiResources(Config.ApiResources())
  .AddInMemoryApiScopes(Config.GetApiScopes())
  .AddInMemoryClients(Config.Clients)
  .AddProfileService<ProfileService>()
  .AddAspNetIdentity<User>();

The Config is the following:

public static class Config {

  public static List<ApiResource> ApiResources() {
    return new List<ApiResource> { 
      new ApiResource("api", "API Resource")
    };
  }

  public static List<ApiScope> ApiScopes() {
    return new List<ApiScope> { 
      new ApiScope("api", "API Scope") 
    };
  }

  public static List<IdentityResource> IdentityResources() {
    return new List<IdentityResource> { 
      new IdentityResources.OpenId(),
      new IdentityResources.Profile(),
      new IdentityResources.Email() 
    };
  }   

  public static List<Client> Clients() {
    return new List<Client> { 
      new Client {
        ClientId = "mvc",
        ClientName = "MVC Client",
        AllowedGrantTypes = GrantTypes.ClientCredentials,
        ClientSecrets = { new Secret("Secret".Sha256()) }
        AllowedScopes = { 
          IdentityServerConstants.StandardScopes.OpenId,
          IdentityServerConstants.StandardScopes.Profile, 
          IdentityServerConstants.StandardScopes.Email, 
          IdentityServerConstants.StandardScopes.OfflineAccess,
          "api"
        }         
      }
    };
  }

}

And on the API I have:

  services
    .AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
    .AddIdentityServerAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme, x => {
      x.ApiName = "api";
      x.ApiSecret = "Secret"
      x.Authority = Config.AuthorityUrl;
      x.RequireHttpsMetadata = true;
      x.EnableCaching = true;
      x.CacheDuration = TimeSpan.FromMinutes(20);
    });

I called one API endpoint using Insomnia client with OAuth2:

enter image description here

I was able to get the Access token but when calling the API I got the error:

Bearer error="invalid_token", error_description="The audience 'empty' is invalid"

I checked the Access token using JWT and I got the following:

Header

{
  "alg": "HS256",
  "kid": "A1042705E52832C676596F36BB1898AB",
  "typ": "at+jwt"
}

Payload

{
  "nbf": 1598478410,
  "exp": 1598482010,
  "iss": "https://localhost:5000",
  "client_id": "mvc",
  "jti": "23525FF997FD4D71E13C786A7AD07B5D",
  "iat": 1598478410,
  "scope": [
    "api"
  ]
}

The aud is missing. But do I need it? After reading the IS4 docs I tried adding:

.AddIdentityServer(y => {
  y.EmitStaticAudienceClaim = true;

Now the Access token has aud field but its value is not api. Shouldn't it be?

"aud": "https://localhost:5000/resources"

When calling the API I now get the error:

Bearer error="invalid_token", error_description="The audience 'https://localhost:5000/resources' is invalid"

I read the docs and IS4 examples but couldn't find a solution.

What am I missing?

like image 651
Miguel Moura Avatar asked Dec 30 '22 21:12

Miguel Moura


1 Answers

What you need to do is connect the ApiScope with the APIRespource to get api to be the desired scope. The https://localhost:5000/resources aud claim is a generic audience when the scopes and api's are not "connected".

In your API definition you need to do something like in this example (Look at the Scopes property below)

var invoiceApi = new ApiResource()
{
    Name = "invoice",   //This is the name of the API
    Description = "This is the invoice Api-resource description",
    Enabled = true,
    DisplayName = "Invoice API Service",
    Scopes = new List<string> { "shop.admin", "shop.employee" },
};

See this link for details about the generic resource scope that is ussued.

It says:

When using the scope-only model, no aud (audience) claim will be added to the token, since this concept does not apply. If you need an aud claim, you can enable the EmitStaticAudience setting on the options. This will emit an aud claim in the issuer_name/resources format. If you need more control of the aud claim, use API resources.

You can try to set the EmitStaticAudience option to false.

You can also ignore the two audiences in the token.

like image 188
Tore Nestenius Avatar answered Jan 05 '23 05:01

Tore Nestenius