Enable bearer token in Swashbuckle (Swagger docume

2020-05-15 15:05发布

问题:

I created an asp.net webapi application which is using Individual Account Security so that the Bearer token is enabled by default. It's working fine so that I am able to test them in Postman without problem.

Here comes the question when I'm trying to integrate the Swagger UI by Swashbuckle. I installed the Swashbuckle by:

Install-Package Swashbuckle

Then change the SwaggerConfig.cs:

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

Start my application and fill in the Bearer token:

But it doesn't work when I run the api request which need authorization. Here is the screenshot:

The bearer token is added to Authorization in header. But I still got error 401. I'm wondering if it's because the token is encoded (the SPACE is replaced by %20)? Any idea? Thanks.

By the way, I'm wondering how to add the /token in my Swagger document too so that I can get the token in Swagger UI.

回答1:

Update

The issue detailed below is now resolved in Swashbuckle v5.5.0.

Issue

Just ran into the exact same issue. I think the root cause is this line in Swashbuckle's source code:

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

This is where the value from the HTML input field goes through URL encoding turning the space into %20. I'm planning to open an issue in the Swashbuckle repo on GitHub.

Workaround

Until that issue is resolved, here is a workaround based on replacing the above line using a Javascript file injected into the Swagger UI:

  1. In the project where you have Swashbuckle installed, create a new folder and call it "Swagger".

  2. In the new folder create a new Javascript file called "SwaggerUiCustomization.js" and put this script in it:

    (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. In the Solution Explorer, choose the file and hit Alt+Enter to edit its Properties. In the Properties window change the file's Build Action to Embedded Resource.

  4. In your SwaggerConfig.cs file add the following line inside the EnableSwaggerUi() code block: c.InjectJavaScript(thisAssembly, "<Project_Default_Namespace>.Swagger.SwaggerUiCustomization.js");
    Be sure, of course, to replace <Project_Default_Namespace> with your project's default namespace.

  5. Run your project and enter "Bearer " into the text box. When you invoke a controller action, you should get this exact same value - with a whitespace instead of %20% - on the server side.



回答2:

Note: this example uses Json Web Tokens.

Your code can be set up so "Bearer" isn't required in the authorization string.

Code in WebApi project to retrieve token (see token = ... in the code segment below):

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 Enable ApiKey Support:

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

Pasting token into Api_Key form element in Swagger UI:

How it looks in the request header in Swagger: