Audience is the wrong mistake

I have 3 projects: 1st Javascript SPA project 2- Web API, 3- IdentityServer with EF Core

I started debugging the API and Identity Server and got the jwt token successfully, but when I try to get the value from the API method that has the authorization attribute, I get the error:

WWW-Authenticate โ†’Bearer error="invalid_token", error_description="The audience is invalid"

      

I couldn't find audience properties in auth settings. This is my config in the API project

app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
        {
            ApiSecret="secret",
            Authority = "http://localhost:5000",
            ApiName="fso.Api",
            RequireHttpsMetadata = false,
        });

      

And my Config.cs file in Identity

 public class Config
{        
    public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource>
        {                
            new ApiResource()
            {
                Name = "fso.Api",                    
                DisplayName = "feasion API",
                Scopes =
                {
                    new Scope("api1"),
                    new Scope(StandardScopes.OfflineAccess)
                },
                UserClaims =
                {
                    JwtClaimTypes.Subject,
                    JwtClaimTypes.EmailVerified,
                    JwtClaimTypes.Email,
                    JwtClaimTypes.Name, 
                    JwtClaimTypes.FamilyName,
                    JwtClaimTypes.PhoneNumber,
                    JwtClaimTypes.PhoneNumberVerified,
                    JwtClaimTypes.PreferredUserName,
                    JwtClaimTypes.Profile, 
                    JwtClaimTypes.Picture, 
                    JwtClaimTypes.Locale, 
                    JwtClaimTypes.IdentityProvider,
                    JwtClaimTypes.BirthDate, 
                    JwtClaimTypes.AuthenticationTime
                }
            }
        };
    }
    public static List<IdentityResource> GetIdentityResources()
    {
        return new List<IdentityResource>
        {
            new IdentityResources.OpenId(),
            new IdentityResources.Email(),
            new IdentityResources.Profile(),
        };
    }

    // client want to access resources (aka scopes)
    public static IEnumerable<Client> GetClients()
    {
        return new List<Client>
        {
            new Client
            {
                ClientId = "fso.api",
                AllowOfflineAccess=true,
                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },
                AllowedGrantTypes = GrantTypes.ResourceOwnerPassword,                    
                AllowedScopes =
                {                       
                   StandardScopes.OfflineAccess,                    
                   "api1"
                }
            }
        };
    }
}

      

+7


source to share


2 answers


Look here for what this requirement is for:

The aud (audience) claim identifies the recipients for which the JWT is intended. Each principal intended to process a JWT MUST identify itself with a value in the audience request. If the principal handling the claim does not identify with the value in the aud claim when that claim is present, then the JWT MUST be rejected ....

So your API name must be present in the aud statement for the JWT to be valid when checked by the middleware in your API. You can use jwt.io to look at your token by the way, it might be helpful to help you understand it.



For IdentityServer to add your API name to the aud claim, your client code (which is trying to get a resource from the API and therefore needs an access token) must request a scope from your API. For example, like this (from an MVC client):

app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
    Authority = Configuration["IdpAuthorityAddress"],
    ClientId = "my_web_ui_id",
    Scope = { "api1" },

    //other properties removed...
});

      

+10


source


To avoid the error, the audience should be added in 4 sequential places

1. In my (eg MVC) client as a custom Scope.
2. In the API application as ApiName
3. In the configuration of IdentityServer clients as AllowedScope
4. In the setting of API resources as ApiResource

See details (previously available on the IdentityServer4 wiki):

When configuring a new API connection in identityServer4, you may receive an error:

WWW-Authenticate: Bearer error="invalid_token", 
error_description="The audience is invalid"

      

To avoid the error, the audience should be added in 4 sequential places

1. In my (eg MVC) client as a custom Scope:



app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions
{
    Authority = Configuration["IdpAuthorityAddress"],
    ClientId = "my_web_ui_id",
  Scope = { "openid", "profile", "offline_access", "MyApi" },               

//other properties removed for brevity...
});

      

2. In the API application as ApiName

  var identityServerAuthenticationOptions = new IdentityServerAuthenticationOptions()//Microsoft.AspNetCore.Builder.IdentityServerAuthenticationOptions
        {
            Authority = Configuration["Authentication:IdentityServer:Authority"],
            RequireHttpsMetadata = false,

            EnableCaching = false,

            ApiName = "MyApi",
            ApiSecret = "MyApiSecret"
        };

      

  1. In IdentityServer \ IdentityServerHost \ Configuration \ Clients.cs (or corresponding client record in the database)

    var client = new Client
    {
        ClientId = clientId,  
        //other properties removed for brevity...   
        AllowedScopes =
        {
            IdentityServerConstants.StandardScopes.OpenId,
            IdentityServerConstants.StandardScopes.Profile,
            //IdentityServerConstants.StandardScopes.Email,
            IdentityServerConstants.StandardScopes.OfflineAccess,
            "MyApi",
          },
    };
    
          

4. In IdentityServer \ IdentityServerHost \ Configuration \ Resources.cs (or the corresponding ApiResource entry in the database) as apiResource.Scopes.

 var apiResource = new ApiResource
        {
            Name = "MyApi",
            ApiSecrets =
            { 
                new Secret("MyApiSecret".Sha256())
            },
            UserClaims =
            {
                JwtClaimTypes.Name,
                JwtClaimTypes.Profile,

            },
        };

      

+5


source







All Articles