50 votes

Activer le jeton porteur dans Swashbuckle (document Swagger)

J'ai créé une application asp.net webapi qui utilise Sécurité des comptes individuels afin que le jeton Bearer soit activé par défaut. Cela fonctionne bien et je suis en mesure de les tester dans Postman sans problème.

Voici la question qui se pose lorsque j'essaie d'intégrer l'interface utilisateur Swagger par Swashbuckle. J'ai installé le Swashbuckle par :

Installer-Package Swashbuckle

Ensuite, changez le SwaggerConfig.cs :

GlobalConfiguration.Configuration
    .EnableSwagger(c =>
    {
        c.ApiKey("Token")
            .Description("Filling bearer token here")
            .Name("Authorization")
            .In("header");
    }
    .EnableSwaggerUi(c =>
    {
        c.EnableApiKeySupport("Authorization", "header");
    };

Je lance mon application et je remplis le jeton de porteur :

enter image description here

Mais cela ne fonctionne pas lorsque je lance la demande d'api qui nécessite une autorisation. Voici la capture d'écran :

enter image description here

Le jeton du porteur est ajouté à Autorisation dans l'en-tête. Mais j'ai toujours l'erreur 401. Je me demande si c'est parce que le jeton est encodé (l'espace est remplacé par %20) ? Une idée ? Merci.

Au fait, je me demande comment ajouter l'option /token dans mon document Swagger également afin que je puisse obtenir le jeton dans l'interface utilisateur Swagger.

0 votes

J'ai confirmé que l'ESPACE codé (%20) en est la cause. Mais comment puis-je remplacer le %20 par un ESPACE ?

1 votes

Curieux : Où est la méthode EnableApiKeySupport() défini ? J'utilise la dernière version de Swashbuckle (v5.4.0) et je ne la vois pas... ?

0 votes

Je l'ai trouvé. C'est une méthode de SwaggeruiConfig et doit être défini dans c.EnableSwaggerUi() .

21voto

urig Points 2707

Mise à jour

Le problème détaillé ci-dessous est maintenant résolu dans Swashbuckle v5.5.0 .

Numéro

Je viens de rencontrer exactement le même problème. Je pense que la cause principale est cette ligne dans le fichier Le code source de Swashbuckle :

var key = encodeURIComponent($('#input_apiKey')[0].value);

C'est là que la valeur du champ de saisie HTML passe par l'encodage URL, transformant l'espace en %20 . J'ai l'intention d'ouvrir un dossier dans la base de données de la Commission européenne. Repo de Swashbuckle sur GitHub .

Solution de rechange

En attendant que ce problème soit résolu, voici une solution de contournement basée sur le remplacement de la ligne ci-dessus par un fichier Javascript injecté dans l'interface utilisateur Swagger :

  1. Dans le projet où vous avez installé Swashbuckle, créez un nouveau dossier et appelez-le "Swagger" .

  2. Dans ce nouveau dossier, créez un nouveau fichier Javascript appelé "SwaggerUiCustomization.js" et mettez ce script dedans :

    (function () {
        function addApiKeyAuthorization() {
            var key = $('#input_apiKey')[0].value;
            if (key && key.trim() != "") {
                var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization(swashbuckleConfig.apiKeyName, key, swashbuckleConfig.apiKeyIn);
                window.swaggerUi.api.clientAuthorizations.add("api_key", apiKeyAuth);
                log("added key " + key);
            }
        }
        $('#input_apiKey').change(addApiKeyAuthorization);
    })();
  3. Dans l'explorateur de solutions, choisissez le fichier et appuyez sur Alt+Enter pour modifier son nom. Propriétés . Dans le Propriétés change le nom du fichier Action de construction à Ressource intégrée .

  4. Dans votre fichier SwaggerConfig.cs, ajoutez la ligne suivante à l'intérieur du champ EnableSwaggerUi() bloc de code : c.InjectJavaScript(thisAssembly, "<Project_Default_Namespace>.Swagger.SwaggerUiCustomization.js");
    Assurez-vous, bien sûr, de remplacer <Project_Default_Namespace> avec l'espace de nom par défaut de votre projet.

  5. Exécutez votre projet et entrez "Bearer" dans la zone de texte. Lorsque vous invoquez une action de contrôleur, vous devriez obtenir exactement la même valeur - avec un espace à la place du mot "Bearer". %20% - du côté du serveur.

0 votes

J'ai résolu le problème en remplaçant l'index.html (c'est en fait la même chose que ce que vous avez fait dans le javascript). Merci. Mais quelle est votre suggestion sur la façon d'obtenir le jeton ? Parce que le token API n'est pas dans le document Swagger. Je peux bien sûr obtenir le jeton par Postman, mais ce n'est pas convaincant.

0 votes

Je ne comprends pas ce que vous entendez par "obtenir le jeton" et "API du jeton". Pouvez-vous m'expliquer ?

0 votes

Il existe un ConfigureAuth dans Startup.Auth.cs qui défile le endpoint, par exemple, nous pouvons le définir comme "/token" de sorte que nous pouvons appeler cette méthode pour obtenir le token. Mais cette api n'est pas dans le document swagger. Quoi qu'il en soit, j'ai déjà résolu ce problème. Merci quand même.

16voto

Ehsan Sajjad Points 19405

Dans asp.net framework Web API, j'ai pu ajouter le Bearer token sur l'interface utilisateur et le faire fonctionner correctement de deux manières différentes.

Voie 1 :

Ajout d'une opération fitler. Créez la classe suivante :

public class AuthorizationHeaderParameterOperationFilter : IOperationFilter
{
    public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
    {
        if (operation.parameters == null)
        {
            operation.parameters = new List<Parameter>();

        }
        operation.parameters.Add(new Parameter
        {
            name = "Authorization",
            @in = "header",
            description = "access token",
            required = false,
            type = "string",
            @default = "Bearer "
        });
    }
}

et maintenant dans le SwaggerConfig.cs ajouter le suivant :

GlobalConfiguration.Configuration
            .EnableSwagger(c =>
                {
                     // other settings

                     c.OperationFilter<AuthorizationHeaderParameterOperationFilter>();
             })
            .EnableSwaggerUi(c =>
                {
                    // UI configurations
            });

Voie 2 :

Nous pouvons aussi utiliser le DocumentFilter pour itérer toutes les opérations et ajouter l'en-tête, dans la suivante nous sautons l'opération qui prend le nom d'utilisateur et le mot de passe et donne le jeton pour la première fois :

public class SwaggerPathDescriptionFilter : IDocumentFilter
{
    private string tokenUrlRoute = "Auth";
    // the above is the action which returns token against valid credentials
    private Dictionary<HeaderType, Parameter> headerDictionary;
    private enum HeaderType { TokenAuth };

    public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
    {
        CreateHeadersDict();

        var allOtherPaths = swaggerDoc.paths.Where(entry => !entry.Key.Contains(tokenUrlRoute)) //get the other paths which expose API resources and require token auth
            .Select(entry => entry.Value)
            .ToList();

        foreach (var path in allOtherPaths)
        {
            AddHeadersToPath(path, HeaderType.TokenAuth);
        }
    }

    /// <summary>
    /// Adds the desired header descriptions to the path's parameter list
    /// </summary>
    private void AddHeadersToPath(PathItem path, params HeaderType[] headerTypes)
    {
        if (path.parameters != null)
        {
            path.parameters.Clear();
        }
        else
        {
            path.parameters = new List<Parameter>();
        }

        foreach (var type in headerTypes)
        {
            path.parameters.Add(headerDictionary[type]);
        }

    }

    /// <summary>
    /// Creates a dictionary containin all header descriptions
    /// </summary>
    private void CreateHeadersDict()
    {
        headerDictionary = new Dictionary<HeaderType, Parameter>();

        headerDictionary.Add(HeaderType.TokenAuth, new Parameter() //token auth header
        {
            name = "Authorization",
            @in = "header",
            type = "string",
            description = "Token Auth.",
            required = true,
            @default = "Bearer "
        });
    }
}

et ensuite nous avons besoin de le regiter dans le SwaggerConfig.cs :

GlobalConfiguration.Configuration
            .EnableSwagger(c =>
                {
                     // other settings

                     c.DocumentFilter<SwaggerPathDescriptionFilter>();
             })
            .EnableSwaggerUi(c =>
                {
                    // UI configurations
            });

Maintenant, nous verrons l'entrée Token pour les en-têtes dans l'interface utilisateur swagger comme :

enter image description here

12voto

Remarque : cet exemple utilise des jetons Web Json.

Votre code peut être configuré pour que "Bearer" ne soit pas requis dans la chaîne d'autorisation.

Code dans le projet WebApi pour récupérer le jeton (cf. jeton = ... dans le segment de code ci-dessous) :

private static bool TryRetrieveToken(HttpRequestMessage request, out string token)
    {
        token = null;
        IEnumerable<string> authzHeaders;
        if (!request.Headers.TryGetValues("Authorization", out authzHeaders) || authzHeaders.Count() > 1)
        {
            return false;
        }
        var bearerToken = authzHeaders.ElementAt(0);
        token = bearerToken.StartsWith("Bearer ") ? bearerToken.Substring(7) : bearerToken;
        return true;
    }

Swagger ApiKey :

c.ApiKey("Authorization")
                        .Description("Filling bearer token here")
                        .Name("Bearer")
                        .In("header");

Swagger Activer le support ApiKey :

c.EnableApiKeySupport("Authorization", "header");

Collage du jeton dans l'élément de formulaire Api_Key dans l'interface utilisateur Swagger : enter image description here

Comment cela se présente dans l'en-tête de la demande dans Swagger : enter image description here

0 votes

Existe-t-il un moyen de stocker les jetons après un redémarrage de l'ordinateur ou un rafraîchissement du navigateur ?

0 votes

En général, les jetons sont de courte durée et ne sont demandés que pour autoriser quelques demandes. Pouvez-vous fournir plus de détails sur ce besoin ? Un scénario qui vous inquiète ?

0 votes

Ahh, on n'arrête pas de rafraîchir le navigateur, et de devoir le taper.

9voto

Alexey Sukhanov Points 151

Mise à jour pour OpenAPI 3, Swashbuckle.AspNetCore (6.7.1) adresse complète de l'article : https://codeburst.io/api-security-in-swagger-f2afff82fb8e Le code pour ajouter l'autorisation JWT Bearer à swagger. Ajoutez-le dans votre Startup.cs dans la méthode ConfigureServices :

services.AddSwaggerGen(c =>
{
    // configure SwaggerDoc and others

    // add JWT Authentication
    var securityScheme = new OpenApiSecurityScheme
    {
        Name = "JWT Authentication",
        Description = "Enter JWT Bearer token **_only_**",
        In = ParameterLocation.Header,
        Type = SecuritySchemeType.Http,
        Scheme = "bearer", // must be lower case
        BearerFormat = "JWT",
        Reference = new OpenApiReference
        {
            Id = JwtBearerDefaults.AuthenticationScheme,
            Type = ReferenceType.SecurityScheme
        }
    };
    c.AddSecurityDefinition(securityScheme.Reference.Id, securityScheme);
    c.AddSecurityRequirement(new OpenApiSecurityRequirement
    {
        {securityScheme, new string[] { }}
    });
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X