Reputation: 1921
I have a Web API (ASP.NET Core) and I am trying to adjust the swagger to make the calls from it. The calls must contains the Authorization header and I am using Bearer authentication. The calls from third party apps like Postman, etc. go fine. But I am having the issue with setting up the headers for swagger (for some reason I don't receive the headers). This is how it looks like now:
"host": "localhost:50352",
"basePath": "/" ,
"schemes": [
"http",
"https"
],
"securityDefinitions": {
"Bearer": {
"name": "Authorization",
"in": "header",
"type": "apiKey",
"description": "HTTP/HTTPS Bearer"
}
},
"paths": {
"/v1/{subAccountId}/test1": {
"post": {
"tags": [
"auth"
],
"operationId": "op1",
"consumes": ["application/json", "application/html"],
"produces": ["application/json", "application/html"],
"parameters": [
{
"name": "subAccountId",
"in": "path",
"required": true,
"type": "string"
}
],
"security":[{
"Bearer": []
}],
"responses": {
"204": {
"description": "No Content"
},
"400": {
"description": "BadRequest",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"401": {
"description": "Unauthorized",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
},
"500": {
"description": "InternalServerError",
"schema": {
"$ref": "#/definitions/ErrorResponse"
}
}
},
"deprecated": false
}
},
Upvotes: 183
Views: 289962
Reputation: 1641
Below is the code for .NET SDK 8. To be able to provide bearer token in Swagger, below code is to be added to Program.cs. Add package Swashbuckle.AspNetCore.Filters, which is required for using SecurityRequirementsOperationFilter, which is used to add security requirements to your relevant API endpoints.
builder.Services.AddSwaggerGen(options =>
{
options.AddSecurityDefinition("oauth2", new Microsoft.OpenApi.Models.OpenApiSecurityScheme()
{
In = Microsoft.OpenApi.Models.ParameterLocation.Header,
Name = "Authorization",
Type = Microsoft.OpenApi.Models.SecuritySchemeType.ApiKey
});
options.OperationFilter<SecurityRequirementsOperationFilter>();
});
A lock will start showing in Swagger as below
and when you click on it, below popup appears to enter token value.
Upvotes: 0
Reputation: 93
The following code works for me:
using Microsoft.AspNetCore.Authentication.JwtBearer;
builder.Services.AddSwaggerGen(options =>
{
options.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new Microsoft.OpenApi.Models.OpenApiSecurityScheme
{
Name = "Authorization",
Type = Microsoft.OpenApi.Models.SecuritySchemeType.Http,
Scheme = JwtBearerDefaults.AuthenticationScheme,
BearerFormat = "JWT",
In = Microsoft.OpenApi.Models.ParameterLocation.Header,
Description = "JWT Authorization header using the Bearer scheme."
});
options.AddSecurityRequirement(new Microsoft.OpenApi.Models.OpenApiSecurityRequirement {
{
new Microsoft.OpenApi.Models.OpenApiSecurityScheme {
Reference = new Microsoft.OpenApi.Models.OpenApiReference {
Type = Microsoft.OpenApi.Models.ReferenceType.SecurityScheme,
Id = JwtBearerDefaults.AuthenticationScheme
}
},
new string[] {}
}
});
});
Upvotes: 1
Reputation: 11
The following code works for me:
services.AddSwaggerGen(config =>
{
config.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Type = SecuritySchemeType.Http,
In = ParameterLocation.Header,
Scheme = "Bearer",
BearerFormat = "JWT",
Description = "JWT Authorization header using the Bearer scheme."
});
config.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
In = ParameterLocation.Header,
},
new List<string>()
}
});
});
Upvotes: 1
Reputation: 360
Tested on .Net 8, Dec 2023. with [Authorize] attribute
I have tried other answers and had to come up with my own solution because other answers were making all my api endpoints looking like they were all needed authentication with padlocks around no matter some does not require authentication actually. So above solutions were dealing with it globally, applying to every endpoint which is not correct and the produced swagger.json/yaml file was also faulty for the same reason which could affect service client generations in other platforms. That's why I felt the need to post this here.
I only wanted where I specifically put [Authorize] attribute to be authorized basically so, during service registration in a typical web application, you can add this:
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
options.SwaggerDoc("v1", new OpenApiInfo { Title = "JadeWebAPI", Version = "v1" });
options.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Name = "Authorization",
Description = "JWT token must be provided",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = JwtBearerDefaults.AuthenticationScheme
});
//options.AddSecurityRequirement(new OpenApiSecurityRequirement
//{
// {
// new OpenApiSecurityScheme
// {
// Name = "Bearer",
// In = ParameterLocation.Header,
// Reference = new OpenApiReference
// {
// Id="Bearer",
// Type=ReferenceType.SecurityScheme,
// }
// },
// new string[]{ }
// }
//});
options.OperationFilter<AuthorizeCheckOperationFilter>();
});
So you will notice that I added and commented AddSecurityRequirement section to not globally affect all endpoints but added instead an OperationFilter to configuration options in the end. This is the implementation of IOperationFilter for this:
public class AuthorizeCheckOperationFilter : IOperationFilter
{
public void Apply(OpenApiOperation operation, OperationFilterContext context)
{
if (context.MethodInfo.DeclaringType is null)
return;
var hasAuthorize = context.MethodInfo.DeclaringType.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any()
|| context.MethodInfo.GetCustomAttributes(true).OfType<AuthorizeAttribute>().Any();
if (hasAuthorize)
{
operation.Responses.Add("401", new OpenApiResponse { Description = "Unauthorized" });
// operation.Responses.Add("403", new OpenApiResponse { Description = "Forbidden" });
var jwtBearerScheme = new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
};
operation.Security = new List<OpenApiSecurityRequirement>
{
new OpenApiSecurityRequirement
{
[jwtBearerScheme] = Array.Empty<string>()
}
};
}
}
}
I think the code is self explanatory. I have also attached screenshots when using global/filter options. This gave a more refined solution to me and correct swagger.json/yaml output.
Upvotes: 8
Reputation: 1275
Update 17.12.2022
in case someone has problems adding JWT to .Net 7,8 the next code worked for me, should work in .Net 6 as well
builder.Services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "Test01", Version = "v1" });
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme()
{
Name = "Authorization",
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer",
BearerFormat = "JWT",
In = ParameterLocation.Header,
Description = "JWT Authorization header using the Bearer scheme."
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
new string[] {}
}
});
});
Upvotes: 21
Reputation: 4003
TIP!
To avoid always write the keyword Bearer
on the Swagger(a.k.a Swashbuckle) auth dialog, like: "bearer xT1..."
, you can use the code/config below on ConfigureServices(...)
method at your Startup
class:
using Microsoft.OpenApi.Models;
...
services.AddSwaggerGen(setup =>
{
// Include 'SecurityScheme' to use JWT Authentication
var jwtSecurityScheme = new OpenApiSecurityScheme
{
BearerFormat = "JWT",
Name = "JWT Authentication",
In = ParameterLocation.Header,
Type = SecuritySchemeType.Http,
Scheme = JwtBearerDefaults.AuthenticationScheme,
Description = "Put **_ONLY_** your JWT Bearer token on textbox below!",
Reference = new OpenApiReference
{
Id = JwtBearerDefaults.AuthenticationScheme,
Type = ReferenceType.SecurityScheme
}
};
setup.AddSecurityDefinition(jwtSecurityScheme.Reference.Id, jwtSecurityScheme);
setup.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{ jwtSecurityScheme, Array.Empty<string>() }
});
});
We can make this, only by changing the Type
property of the OpenApiSecurityScheme
class to:
Type = SecuritySchemeType.Http
instead
Type = SecuritySchemeType.ApiKey
.
Packages:
Swashbuckle.AspNetCore(5.6.3)
Swashbuckle.AspNetCore.SwaggerUI(5.6.3)
I'am using .NET Core 3.1.
Upvotes: 157
Reputation: 5361
There is no need to generate token separate and key in swagger. Swagger support generation part too. Below work for me with asp.net core 3.1 and keycloack auth.
swagger.AddSecurityDefinition(JwtBearerDefaults.AuthenticationScheme, new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
Implicit = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri("https://youauthsrv.com/auth/realms/your-realm/protocol/openid-connect/auth"),
}
},
In = ParameterLocation.Header,
Scheme = JwtBearerDefaults.AuthenticationScheme,
});
swagger.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = JwtBearerDefaults.AuthenticationScheme
}
},
new string[] {}
}
});
in Configure
app.UseSwaggerUI(c =>
{
c.OAuthClientId("clientname");
c.OAuthRealm("your-realm");
});
Upvotes: 7
Reputation: 704
Using ASP.Net Core 3.1, here's what worked for me:
services.AddSwaggerGen(s =>
{
s.SwaggerDoc("v1", new OpenApiInfo
{
Version = "v1",
Title = "Chat API",
Description = "Chat API Swagger Surface",
Contact = new OpenApiContact
{
Name = "João Victor Ignacio",
Email = "[email protected]",
Url = new Uri("https://www.linkedin.com/in/ignaciojv/")
},
License = new OpenApiLicense
{
Name = "MIT",
Url = new Uri("https://github.com/ignaciojvig/ChatAPI/blob/master/LICENSE")
}
});
s.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = "JWT Authorization header using the Bearer scheme (Example: 'Bearer 12345abcdef')",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
s.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
}
},
Array.Empty<string>()
}
});
});
Upvotes: 46
Reputation: 9720
ApiKeyScheme was deprecated, in version 5 you can use like this:
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new Info { Title = "You api title", Version = "v1" });
c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
{
Description = @"JWT Authorization header using the Bearer scheme. \r\n\r\n
Enter 'Bearer' [space] and then your token in the text input below.
\r\n\r\nExample: 'Bearer 12345abcdef'",
Name = "Authorization",
In = ParameterLocation.Header,
Type = SecuritySchemeType.ApiKey,
Scheme = "Bearer"
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement()
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Type = ReferenceType.SecurityScheme,
Id = "Bearer"
},
Scheme = "oauth2",
Name = "Bearer",
In = ParameterLocation.Header,
},
new List<string>()
}
});
var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
c.IncludeXmlComments(xmlPath);
});
Upvotes: 277
Reputation: 1665
First of all, you can use Swashbuckle.AspNetCore
nuget package for auto generating your swagger definition. (tested on 2.3.0)
After you've installed package, setup it in Startup.cs in method ConfigureServices
services.AddSwaggerGen(c => {
c.SwaggerDoc("v1", new Info { Title = "You api title", Version = "v1" });
c.AddSecurityDefinition("Bearer",
new ApiKeyScheme { In = "header",
Description = "Please enter into field the word 'Bearer' following by space and JWT",
Name = "Authorization", Type = "apiKey" });
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>> {
{ "Bearer", Enumerable.Empty<string>() },
});
});
Then you can use Authorize button at the top right of the page.
At least you can try to use this package to generate valid swagger definition
Upvotes: 149