Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authorization Header not being sent from Swagger UI 5.0.0-rc5 #1425

Closed
VictorioBerra opened this issue Dec 18, 2019 · 18 comments
Closed

Authorization Header not being sent from Swagger UI 5.0.0-rc5 #1425

VictorioBerra opened this issue Dec 18, 2019 · 18 comments

Comments

@VictorioBerra
Copy link
Contributor

VictorioBerra commented Dec 18, 2019

Tried both the following solutions:

#1022

                    options.AddSecurityDefinition("basicAuth", new OpenApiSecurityScheme
                    {
                        Type = SecuritySchemeType.Http,
                        Scheme = "Basic", // tried lowercase "basic" too.
                        Description = "Input your username and password to access this API",
                        In = ParameterLocation.Header,
                    });

                    options.AddSecurityRequirement(new OpenApiSecurityRequirement
                    {
                        {
                            new OpenApiSecurityScheme
                            {
                                Reference = new OpenApiReference {
                                    Type = ReferenceType.SecurityScheme,
                                    Id = "basicAuth" }
                            }, new List<string>() }
                    });

#1171

                    options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                    {
                        Description = "JWT Authorization header using the Bearer scheme.",
                        Name = "Authorization",
                        In = ParameterLocation.Header,
                        Scheme = "bearer",
                        Type = SecuritySchemeType.Http,
                        BearerFormat = "JWT"
                    });

                    options.AddSecurityRequirement(new OpenApiSecurityRequirement
                    {
                        {
                            new OpenApiSecurityScheme
                            {
                                Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
                            },
                            new List<string>()
                        }
                    });

I need basic auth, and I am willing to settle for making the user put the encoded final header in. Ideally, they would be prompted for a username and password and that could automatically be encoded.

@handsome-b-wonderful
Copy link

I'm also experiencing the same issue where the UI is not adding the authorization header.

I'm using token authentication that is applied conditionally based on attrbiutes of my controller, but with very similar code in an IOperationFilter:

               operation.Parameters.Add(new OpenApiParameter
                {
                    Name = "Authorization",
                    In = ParameterLocation.Header,
                    Description = "[Your Token]",
                    Required = true,
                    Schema = new OpenApiSchema { Type = "string" },
                });

                operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
                operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });

                operation.Security = new List<OpenApiSecurityRequirement>
                {
                    new OpenApiSecurityRequirement()
                        {
                             {
                                new OpenApiSecurityScheme
                                {
                                    Description = "Adds token to header",
                                    Name = "Authorization",
                                    Type = SecuritySchemeType.Http,
                                    In = ParameterLocation.Header,
                                    Scheme = "bearer",
                                    Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "Bearer" }
                                },
                                new List<string>()
                            }
                    }
                };

The UI is generated correctly but the header is not added to the request.

using 5.0.0-rc5

@gorkemyontem
Copy link

Really need a working example for bearer token.

@VictorioBerra
Copy link
Contributor Author

@gorkemyontem at this point I'm thinking that's not going to happen without a PR.

@domaindrivendev
Copy link
Owner

domaindrivendev commented Jan 3, 2020

The following example works for me (including automatic encoding of credentials). It's worth noting that this type of question is related to understanding the Swagger specification, and how to express certain API behaviors with it, as opposed to Swashbuckle itself. When this is the case, I would encourage people to look at the Swagger documents (e.g. authentication examples) instead as they contain many examples which can be easily ported over to Swashbuckle configuration.

Anyway, here's a working example for basic Auth (derived from the Swagger docs):

c.AddSecurityDefinition("basicAuth", new OpenApiSecurityScheme
{
    Type = SecuritySchemeType.Http
    Scheme = "basic"
});

c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
    {
        new OpenApiSecurityScheme
        {
            Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "basicAuth" }
        },
        new string[]{}
    }
});

@VictorioBerra
Copy link
Contributor Author

@domaindrivendev That did not work.

Click authorize

image

Fill out info and click the authorize button

image

Expand an operation

image

Click "Try it out"

image

Click "Execute"

image

401! And there is no "Authorize" header in the request payload.

image

It's worth noting that this type of question is related to understanding the Swagger specification, and how to express certain API behaviors with it, as opposed to Swashbuckle itself

But Swashbuckle needs to understand the Swagger body to make use of it in the UI does it not? How else does the UI know to create Auth headers, and encode parameters?

@pnavk
Copy link

pnavk commented Jan 8, 2020

Don't use parameters to accomplish this as it is no longer supported by Swagger UI. To get the Authorization header included in the curl request you must define it entirely using security schemes. For reference see this comment

Want to share my configuration that works on 5.0.0-rc5:

In Startup.cs, add a global Security Definition and operation filter:

services.AddSwaggerGen(opt =>
{
	opt.SwaggerDoc("v1", new OpenApiInfo { Title = "My Api", Version = "v1" });
	opt.AddSecurityDefinition("bearer", new OpenApiSecurityScheme
	{
		Type = SecuritySchemeType.Http,
		BearerFormat = "JWT",
		In = ParameterLocation.Header,
		Scheme = "bearer"
	});
	opt.OperationFilter<AuthenticationRequirementsOperationFilter>();
});

In the AuthenticationRequirementsOperationFilter add a Security Requirement to the operation by referencing the Security Definition that was added globally:

public class AuthenticationRequirementsOperationFilter : IOperationFilter
{
	public void Apply(OpenApiOperation operation, OperationFilterContext context)
	{
		if (operation.Security == null)
			operation.Security = new List<OpenApiSecurityRequirement>();


		var scheme = new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearer" } };
		operation.Security.Add(new OpenApiSecurityRequirement
		{
			[scheme] = new List<string>()
		});
	}
}

Note:

  • The Id value "bearer" matches what was passed as the first parameter to AddSecurityDefinition in Startup.cs
  • This example adds the security requirement to ALL endpoints. Typically, filtering logic will be included to only add the security requirement to endpoints that need it.

The generated UI won't have Authorization fields in each endpoint. There should be open locks on the endpoints that had a security requirement added to them in the OperationFilter and an Authorize button should show up on the top right. Add the token to the header using the Authorize button and the endpoints will show with closed locks. Note: "Bearer" will be added automatically, so only provide the token when authorizing.

Screen Shot 2020-01-07 at 11 23 07 PM

Requests should now include the Authorization header with the provided token. You can verify in the curl:

Screen Shot 2020-01-07 at 11 24 51 PM

Hope it helps!

@VictorioBerra
Copy link
Contributor Author

@pnavk Thank's you led me to the solution which was that I had options.OperationFilter<SecurityRequirementsOperationFilter>() in my startup.cs! This was overriding anything I did thanks to this https://github.com/mattfrear/Swashbuckle.AspNetCore.Filters/blob/master/src/Swashbuckle.AspNetCore.Filters/SecurityRequirementsOperationFilter/SecurityRequirementsOperationFilter.cs#L20

Similar one here: https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/test/WebSites/OAuth2Integration/ResourceServer/Swagger/SecurityRequirementsOperationFilter.cs#L27

All I had to do was add the following to my AddSwaggerGen and the problem was solved.

options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
{
    Type = SecuritySchemeType.Http,
    Scheme = "basic"
});

The key here being "oauth2" since that references the hardcoded OpenApiScheme.OpenApiReference.

@handsome-b-wonderful
Copy link

Really need a working example for bearer token.

This is working for me under 5.0.0-rc5:

In Startup.cs in ConfigureServices:

services.AddSwaggerGen(options =>
            {
                options.AddSecurityDefinition("bearer", new OpenApiSecurityScheme
                {
                    Type = SecuritySchemeType.Http,
                    BearerFormat = "JWT",
                    In = ParameterLocation.Header,
                    Scheme = "bearer"
                });


                // add auth header for [Authorize] endpoints
                options.OperationFilter<AddAuthHeaderOperationFilter>();
public class AddAuthHeaderOperationFilter : IOperationFilter
    {

        public void Apply(OpenApiOperation operation, OperationFilterContext context)
        {
               if (operation.Security == null)
                    operation.Security = new List<OpenApiSecurityRequirement>();


                var scheme = new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearer" } };
                operation.Security.Add(new OpenApiSecurityRequirement
                {
                    [scheme] = new List<string>()
                });
        }
    }

NOTE: I filter on

  • controllers that have an [Authorize] attribute
  • do not have [AllowAnonymous] method attributes.

in AddAuthHeaderOperationFilter - code removed for clarity.

@11kodykay11
Copy link

For those who are still having trouble with this, here is the code that worked for me after few hours of trial and error.

services.AddSwaggerGen(c =>
            {                
                c.AddSecurityDefinition("Basic", new OpenApiSecurityScheme
                {
                    Name = "Basic",
                    Description = "Please enter your username and password",
                    Type = SecuritySchemeType.Http,
                    Scheme = "basic", //This is were it was not working for me. I was using uppercase B
                    In = ParameterLocation.Header
                });

`               c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Basic" }
                        }, new List<string>() 
                    }
                });
        }

@zscao
Copy link

zscao commented Mar 31, 2020

The options below working with Bearer scheme for me:

            c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
            {
                Description = "JWT Authorization header using the Bearer scheme.",
                Name = "Authorization",
                In = ParameterLocation.Header,
                Type = SecuritySchemeType.ApiKey,
                Scheme = "bearer"
            });

            c.AddSecurityRequirement(new OpenApiSecurityRequirement
            {
                {
                    new OpenApiSecurityScheme
                    {
                        Reference = new OpenApiReference
                        {
                            Type = ReferenceType.SecurityScheme,
                            Id = "Bearer"
                        }
                    }, new List<string>()
                }
            });

@davidbuckleyni
Copy link

I am having the same issue for me but for me its addding the token but getting 401 unauthorised from the controller if i remove the dataannotation it works fine.

services.AddSwaggerGen(c =>
{

            c.SwaggerDoc("v1", new OpenApiInfo { Title = "App Manager - Running Buddies", Version = "v1" });

            c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme {
                Description = "JWT Authorization header using the Bearer scheme.",
                Name = "Authorization",
                In = ParameterLocation.Header,
                Type = SecuritySchemeType.ApiKey,
                Scheme = "bearer"
            });

            c.AddSecurityRequirement(new OpenApiSecurityRequirement
            {
            {
                new OpenApiSecurityScheme
                {
                    Reference = new OpenApiReference
                    {
                        Type = ReferenceType.SecurityScheme,
                        Id = "Bearer"
                    }
                }, new List<string>()
            }
        });
   });
        [AllowAnonymous]
        [HttpPost]
        public IActionResult CreateToken([FromBody] LoginModel login) {

            IActionResult response = Unauthorized();
            var user = Authenticate(login);

            if (user != null) {
                var tokenString = BuildToken(login);
                response = Ok(new { token = tokenString });
            }

            return response;

        }


        private string BuildToken(LoginModel login) {
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["JwtToken:SecretKey"]));
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
            JwtSecurityToken token;
            
                token = new JwtSecurityToken(_config["JwtToken:Issuer"],
              _config["JwtToken:Issuer"], expires: DateTime.Now.AddMinutes(30),
              signingCredentials: creds); 
            return new JwtSecurityTokenHandler().WriteToken(token);

        }


        private UserModel Authenticate(LoginModel login) {
            UserModel user = null;
            //var result = await _signInManager.PasswordSignInAsync(, lockoutOnFailure: false);
            if (login.Username == "mario" && login.Password == "secret") {
                user = new UserModel { UserName = "Mario Rossi", Email = "mario.rossi@domain.com" };
            }
            return user;
        }

My Bmi Controler

namespace AppManagerApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
   [Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
    public class BmiInformationsController : ControllerBase
    {
        private readonly AppManagerDBContext _context;

        public BmiInformationsController(AppManagerDBContext context)
        {
            _context = context;
        }

        // GET: api/BmiInformations
        [HttpGet]
        public async Task<ActionResult<IEnumerable<BmiInformation>>> GetBmiInformation()
        {
            return await _context.BmiInformation.ToListAsync();
        }
}```

Please help this is driving me nuts



@ceemafour
Copy link

I think the issue here (from the documentation ):

NOTE: In addition to defining a scheme, you also need to indicate which operations that scheme is applicable to. You can apply schemes globally (i.e. to ALL operations) through the AddSecurityRequirement method. The example below indicates that the scheme called "oauth2" should be applied to all operations, and that the "readAccess" and "writeAccess" scopes are required. When applying schemes of type other than "oauth2", the array of scopes MUST be empty.

I am using implicit flow for swagger and this solved the issue for me:

c.AddSecurityRequirement(new OpenApiSecurityRequirement { { new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "oauth2" } }, new[] { "scope1", "scope2" } } });

@capcom923
Copy link

capcom923 commented Jul 2, 2020

I met the same issue before and resolved it.

Now the available Authorization header works fine.

Please check my latest sample using SwashBuckle v5.5.1 and netcore 3.1
https://github.com/capcom923/MySwashBuckleSwaggerWithJwtToken

send-authorization-header

@glorious73
Copy link

I met the same issue before and resolved it.

Now the available Authorization header works fine.

Please check my latest sample using SwashBuckle v5.5.1 and netcore 3.1
https://github.com/capcom923/MySwashBuckleSwaggerWithJwtToken

send-authorization-header

Solved my problem thanks.

@FidelisChimombe
Copy link

FidelisChimombe commented Oct 26, 2021

I had the same issue. The securityDefinitions in the swagger config, should match the security definition in the operation.
image

In my case I had configured it as,
image

Therefore my endpoint operation definition should include the security, bearerAuth: []
image

@iashwini
Copy link

iashwini commented Jan 17, 2022

If someone migrating to .net core version 3.1, following are the changes require.

  1. Use 'Type = SecuritySchemeType.Http'. Because we need to use bearer authentication, set the scheme type to http.
  2. HTTP Authorization scheme to be used in the Authorization header. Scheme = "bearer". This has to be a lower case.
  3. Add AddSecurityRequirement(). This enables security globally.

Below is the code how it should look.

              `options.AddSecurityDefinition(definition, new OpenApiSecurityScheme
               {
                   Description = $"desc",
                   Name = "Authorization",
                   In = ParameterLocation.Header,
                   Type = SecuritySchemeType.ApiKey,
                   Scheme = "bearer"
               });

               options.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            }
                        }, new List<string>()
                    }
                });`

@RahulBavaliya
Copy link

Don't use parameters to accomplish this as it is no longer supported by Swagger UI. To get the Authorization header included in the curl request you must define it entirely using security schemes. For reference see this comment

Want to share my configuration that works on 5.0.0-rc5:

In Startup.cs, add a global Security Definition and operation filter:

services.AddSwaggerGen(opt =>
{
	opt.SwaggerDoc("v1", new OpenApiInfo { Title = "My Api", Version = "v1" });
	opt.AddSecurityDefinition("bearer", new OpenApiSecurityScheme
	{
		Type = SecuritySchemeType.Http,
		BearerFormat = "JWT",
		In = ParameterLocation.Header,
		Scheme = "bearer"
	});
	opt.OperationFilter<AuthenticationRequirementsOperationFilter>();
});

In the AuthenticationRequirementsOperationFilter add a Security Requirement to the operation by referencing the Security Definition that was added globally:

public class AuthenticationRequirementsOperationFilter : IOperationFilter
{
	public void Apply(OpenApiOperation operation, OperationFilterContext context)
	{
		if (operation.Security == null)
			operation.Security = new List<OpenApiSecurityRequirement>();


		var scheme = new OpenApiSecurityScheme { Reference = new OpenApiReference { Type = ReferenceType.SecurityScheme, Id = "bearer" } };
		operation.Security.Add(new OpenApiSecurityRequirement
		{
			[scheme] = new List<string>()
		});
	}
}

Note:

  • The Id value "bearer" matches what was passed as the first parameter to AddSecurityDefinition in Startup.cs
  • This example adds the security requirement to ALL endpoints. Typically, filtering logic will be included to only add the security requirement to endpoints that need it.

The generated UI won't have Authorization fields in each endpoint. There should be open locks on the endpoints that had a security requirement added to them in the OperationFilter and an Authorize button should show up on the top right. Add the token to the header using the Authorize button and the endpoints will show with closed locks. Note: "Bearer" will be added automatically, so only provide the token when authorizing.

Screen Shot 2020-01-07 at 11 23 07 PM

Requests should now include the Authorization header with the provided token. You can verify in the curl:

Screen Shot 2020-01-07 at 11 24 51 PM

Hope it helps!

Thanks for the solution, it worked for me....!!!

@douglasg14b
Copy link

douglasg14b commented Dec 8, 2023

Unfortunately this doesn't appear to work, endpoints are not marked as requiring auth and no authorization header is included in nay request.

Does this behavior not come out of the box....?

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests