How to use Swagger in ASP.Net WebAPI 2.0 with token based authentication

11,995

Solution 1

I found the solution myself. I would like to share it in case anybody is facing the same problem. The solution is of 2 steps, first one is to request a token and the next step, is to add the token into the header request.

So the first step:

Customize the frontend to enable post request for requesting a token:

enter image description here

Add a AuthTokenOperation class to enable which inherits the IDcoumentFilter interface and implements the Apply method:

public class AuthTokenOperation : IDocumentFilter
    {
        /// <summary>
        /// Apply custom operation.
        /// </summary>
        /// <param name="swaggerDoc">The swagger document.</param>
        /// <param name="schemaRegistry">The schema registry.</param>
        /// <param name="apiExplorer">The api explorer.</param>
        public void Apply(SwaggerDocument swaggerDoc, SchemaRegistry schemaRegistry, IApiExplorer apiExplorer)
        {
            swaggerDoc.paths.Add("/token", new PathItem
            {
                post = new Operation
                {
                    tags = new List<string> { "Auth"},
                    consumes = new List<string>
                    {
                        "application/x-www-form-urlencoded"
                    },
                    parameters = new List<Parameter>
                    {
                        new Parameter
                        {
                            type = "string",
                            name = "grant_type",
                            required = true,
                            @in = "formData"
                        },
                        new Parameter
                        {
                            type = "string",
                            name = "username",
                            required = false,
                            @in = "formData"
                        },
                        new Parameter
                        {
                            type = "string",
                            name = "password",
                            required = false,
                            @in = "formData"
                        },
                    }
                }
            });
        }
    }

And in the SwaggerConfig class in the register method, add this action

c.DocumentFilter<AuthTokenOperation>();

to the extension method:

GlobalConfiguration.Configuration.EnableSwagger

To add the authorization token in the request header:

enter image description here

Add this operation class:

/// <summary>
    /// The class to add the authorization header.
    /// </summary>
    public class AddAuthorizationHeaderParameterOperationFilter : IOperationFilter
    {
        /// <summary>
        /// Applies the operation filter.
        /// </summary>
        /// <param name="operation"></param>
        /// <param name="schemaRegistry"></param>
        /// <param name="apiDescription"></param>
        public void Apply(Operation operation, SchemaRegistry schemaRegistry, ApiDescription apiDescription)
        {
            if (operation.parameters != null)
            {
                operation.parameters.Add(new Parameter
                {
                    name = "Authorization",
                    @in = "header",
                    description = "access token",
                    required = false,
                    type = "string"
                });
            }
        }
    }

And in the SwaggerConfig class in the register method, add this action

c.OperationFilter<AddAuthorizationHeaderParameterOperationFilter>();

to the extension method:

GlobalConfiguration.Configuration.EnableSwagger

Of course in the Authoization field, you need to add: Bearer token_string

Solution 2

I just want to add something to the accepted answer that when autorest is used for client generation, the accepted answer is not complete for it misses the some properties.

[Fatal]OperationId is required for all operations. Please add it for 'post' operation of '/authenticate' path. Exception: There was an error during code generation when trying to add a client for the REST API Generating client code and adding to project failed Adding REST API client for failed

post = new Operation
            {
                operationId = "Auth_AccessToken",
                tags = new List<string> { "Auth" },
                produces = new List<string>
                {
                    "application/json",
                    "text/json",
                    "application/xml",
                    "text/xml"
                },
                consumes = new List<string>
                {
                    "application/x-www-form-urlencoded"
                },
                parameters = new List<Parameter>
                {
                    new Parameter
                    {
                        type = "string",
                        name = "grant_type",
                        required = true,
                        @in = "formData"
                    },
                    new Parameter
                    {
                        type = "string",
                        name = "username",
                        required = true,
                        @in = "formData"
                    },
                    new Parameter
                    {
                        type = "string",
                        name = "password",
                        required = true,
                        @in = "formData"
                    },
                    new Parameter
                    {
                        type = "string",
                        name = "client_id",
                        required = true,
                        @in = "formData"
                    },
                    new Parameter
                    {
                        type = "string",
                        name = "client_secret",
                        required = true,
                        @in = "formData"
                    }
                },
                responses = new Dictionary<string, Response>
                {
                    {"200", new Response{ description = "OK", schema = new Schema{ type = "object"} } }
                }
            }

you need to add the operationId and responses for autorest to work properly.

Share:
11,995

Related videos on Youtube

alaa_sayegh
Author by

alaa_sayegh

My name is Alaa, staying in Germany. I'm a senior software developer as working as freelancer. I'm very attracted to new technologies and writing code is my passion.

Updated on August 17, 2021

Comments

  • alaa_sayegh
    alaa_sayegh over 2 years

    I have a ASP.Net WebApi with token based authentication and I want to use swagger to create documentation for this RestApi.

    The Api has for now only 2 methods, one for requesting a token i.e. http://localhost:4040/token and the other one is for creating a notification. The returned bearer token is sent like follows:

    using (var client = new HttpClient())
    {
        // setup client
        client.BaseAddress = new Uri("http://localhost:4040");
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
        client.DefaultRequestHeaders.Add("Authorization", "Bearer " + token);
    
        var serializedNotification = new JavaScriptSerializer().Serialize(notification);
        var stringContent = new StringContent(serializedNotification, Encoding.UTF8, "application/json");
    
        var response = await client.PostAsync("api/Notification", stringContent);
        response.EnsureSuccessStatusCode();
    
        // return URI of the created resource.
        return response.Headers.Location;
     }
    

    With swagger I can see the post Notification method, however I can't do a request because I don't have a token and I don't know how to do it in swagger.

  • Imbajoe
    Imbajoe over 4 years
    I used this method, and all the information shows up in swagger. However, when I try to get an auth token, I get an "error": "unsupported_grant_type" response back. Any idea what I might have done wrong? I'm using 'password' as the grant_type
  • Jeff Hartman
    Jeff Hartman about 4 years
    I had the same problem with "unsupported_grant_type". The issue with mine was the @in string is case sensitive, and I had it all lowercase. Changing it to formData like the example fixed my issue.
  • Sam White
    Sam White over 3 years
    This method (attributed to this answer) has been presented in full detail by Tim Corey in one of his YouTube video tutorials. Link: youtube.com/watch?v=zQRgB6nasUc
  • Hamza Khanzada
    Hamza Khanzada about 2 years
    Reminding once again: Make sure you add Bearer <token> in the Authorization textbox when accessing a protected resource