web-dev-qa-db-fra.com

L'audience est une erreur non valide

J'ai 3 projets 1- Javascript SPA 2- Projet API Web, 3- IdentityServer avec EF Core

J'ai commencé le débogage de l'API et d'Identity Server et j'ai réussi à obtenir le jeton jwt mais, lorsque j'essaie d'obtenir de la valeur à partir de la méthode API qui a l'attribut d'autorisation, j'obtiens une erreur:

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

Je n'ai trouvé aucune propriété sur l'audience dans les options d'authentification. Ceci est ma configuration dans le projet API

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

Et mon fichier Config.cs dans 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"
                }
            }
        };
    }
}
11
Okan Aslankan

Voir ici pour en quoi consiste cette affirmation:

La revendication aud (audience) identifie les destinataires auxquels le JWT est destiné. Chaque mandant destiné à traiter le JWT DOIT s'identifier avec une valeur dans la revendication d'audience. Si le principal traitant la réclamation ne s'identifie pas avec une valeur dans la réclamation aud lorsque cette réclamation est présente, alors le JWT DOIT être rejeté ....

Le nom de votre API doit donc exister dans la revendication aud pour que le JWT soit valide lorsqu'il est validé par le middleware de votre API. Vous pouvez utiliser jwt.io pour regarder votre jeton en passant, cela peut être utile pour aider à le comprendre.

Pour qu'IdentityServer ajoute le nom de votre API à l'aud réclamation, votre code client (qui tente d'obtenir une ressource de l'API et a donc besoin d'un jeton d'accès) doit demander une étendue à votre API. Par exemple, comme ceci (à partir d'un client MVC):

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

    //other properties removed...
});
10
Matt

Pour éviter l'erreur, l'audience doit être systématiquement ajoutée à 4 endroits

Dans mon client (par exemple MVC) en tant que portée personnalisée.
2. Dans l'application API comme ApiName
3.Dans la configuration des clients IdentityServer en tant que AllowScope
4.Dans la configuration des ressources API comme ApiResource

Voir les détails (précédemment disponibles sur le wiki IdentityServer4):

Lors de la configuration d'une nouvelle connexion API dans identityServer4, vous pouvez obtenir une erreur:

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

Pour éviter l'erreur, l'audience doit être systématiquement ajoutée à 4 endroits

Dans mon client (par exemple MVC) en tant que portée personnalisée:

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

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

Dans l'application API comme ApiName

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

            EnableCaching = false,

            ApiName = "MyApi",
            ApiSecret = "MyApiSecret"
        };
  1. Dans IdentityServer\IdentityServerHost\Configuration\Clients.cs (ou entrée Clients correspondante dans la base de données)

    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",
          },
    };
    

Dans IdentityServer\IdentityServerHost\Configuration\Resources.cs (ou entrée ApiResource correspondante dans la base de données) en tant qu'apiResource.Scopes

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

            },
        };
9