web-dev-qa-db-fra.com

Utiliser plusieurs authentifications de porteur JWT

Est-il possible de prendre en charge plusieurs émetteurs de jetons JWT dans ASP.NET Core 2? Je souhaite fournir une API pour un service externe et je dois utiliser deux sources de jetons JWT: les émetteurs de jetons Firebase et personnalisés JWT. Dans ASP.NET Core, je peux définir l'authentification JWT pour le schéma d'authentification du porteur, mais uniquement pour une autorité:

  services
        .AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.Authority = "https://securetoken.google.com/my-firebase-project"
            options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidIssuer = "my-firebase-project"
                    ValidateAudience = true,
                    ValidAudience = "my-firebase-project"
                    ValidateLifetime = true
                };
        }

Je peux avoir plusieurs émetteurs et publics, mais je ne peux pas définir plusieurs autorités.

35
Sane

Vous pouvez totalement réaliser ce que vous voulez:

services
    .AddAuthentication()
    .AddJwtBearer("Firebase", options =>
    {
        options.Authority = "https://securetoken.google.com/my-firebase-project"
        options.TokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuer = true,
            ValidIssuer = "my-firebase-project"
            ValidateAudience = true,
            ValidAudience = "my-firebase-project"
            ValidateLifetime = true
        };
    })
    .AddJwtBearer("Custom", options =>
    {
        // Configuration for your custom
        // JWT tokens here
    });

services
    .AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase", "Custom")
            .Build();
    });

Passons en revue les différences entre votre code et celui-là.

AddAuthentication n'a pas de paramètre

Si vous définissez un schéma d'authentification par défaut, le middleware d'authentification essaiera d'exécuter à chaque requête le gestionnaire d'authentification associé au schéma d'authentification par défaut. Puisque nous avons maintenant deux schémas d’authentification utilisables, il n’est pas utile d’en exécuter un.

Utilisez une autre surcharge de AddJwtBearer

Chaque méthode AddXXX pour ajouter une authentification comporte plusieurs surcharges:

Maintenant, comme vous utilisez deux fois la même méthode d'authentification mais que les schémas d'authentification doivent être uniques, vous devez utiliser la deuxième surcharge.

Mettre à jour la politique par défaut

Puisque les requêtes ne seront plus authentifiées automatiquement, ajouter les attributs [Authorize] À certaines actions entraînera le rejet des requêtes et un HTTP 401 Sera émis.

Puisque ce n'est pas ce que nous voulons, car nous voulons donner aux gestionnaires d'authentification l'occasion d'authentifier la demande, nous modifions la stratégie par défaut du système d'autorisation en indiquant les schémas d'authentification Firebase et Custom. être essayé d’authentifier la demande.

Cela ne vous empêche pas d'être plus restrictif pour certaines actions; l'attribut [Authorize] a une propriété AuthenticationSchemes qui vous permet de remplacer les schémas d'authentification valides.

Si vous avez des scénarios plus complexes, vous pouvez utiliser autorisation basée sur une stratégie . Je trouve la documentation officielle géniale.

Imaginons que certaines actions ne soient disponibles que pour les jetons JWT émis par Firebase et doivent avoir une revendication avec une valeur spécifique; vous pouvez le faire de cette façon:

// Authentication code omitted for brevity

services
    .AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase", "Custom")
            .Build();

        options.AddPolicy("FirebaseAdministrators", new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("Firebase")
            .RequireClaim("role", "admin")
            .Build());
    });

Vous pouvez ensuite utiliser [Authorize(Policy = "FirebaseAdministrators")] sur certaines actions.

72
Mickaël Derriey