In the new version, the Authorization token is not being passed in the request header.
Setup...


I can uninstall Swashbuckle, and install 1.1.0 or 1.2.0 and it works. 2.0.0 does not work.
Thanks!
And I think can add one more issue comment. Maybe they are related.
I have similar setup and Document Filter which hides endpoints with authorization required.
When I open Swagger UI I see only one method SignIn and use it to get token.
I set this token in Authorize window and it should reload the documentation and show me all available endpoints for authorized user.
In 1.1.0 and 1.2.0 it works fine. It does new request and load new filtered documentation, but in 2.0.0 it doesn't make any additional request.
Sounds similar. I don't hide based on authorization. But, I do have the "Authorize" attribute set on all methods other than my Login method (which is AllowAnonymous) . As such, all methods other than Login return a 401, even after adding the Bearer {token} to the Authorization section of the Swagger doc.
I like the new Swagger layout a lot better. In particular I like that it renders the models at the bottom of the document. However, it's a nonstarter if the Authorization doesn't work.
Thanks all!
Can confirm that the authorization header is not set. I can take a look at it and hopefully soon have a PR for a fix + tests.
Also have the same issue. It is setting a WWW-Authenticate: Bearer HTTP header though.
I鈥檒l look into this. The OAuth example in this repo works without a hitch so I鈥檓 surprised that other auth methods aren鈥檛 working.
I'm using both OAuth and Basic in the same API. Just confirmed that Basic is not working for me either.
As per the Swagger spec, defining the scheme alone is not sufficient. You also need to provide a Security Requirement Object at the document level or on individual operations to indicate which operations that scheme is applicable to.
If this was working in the previous version of the UI without the security requirement, then that's really a bug because it shouldn't have been according to the spec. The security semantics in Swagger 2.0 are fairly clunky IMO, but still, you should be able to get things working by wiring up the following DocumentFilter (see readme). I just verified locally and it works exactly as expected for Bearer and Basic.
public class SecurityRequirementsDocumentFilter : IDocumentFilter
{
public void Apply(SwaggerDocument document, DocumentFilterContext context)
{
document.Security = new List<IDictionary<string, IEnumerable<string>>>()
{
new Dictionary<string, IEnumerable<string>>()
{
{ "Bearer", new string[]{ } },
{ "Basic", new string[]{ } },
}
};
}
}
Yep, that worked. Thanks @domaindrivendev
I got Basic auth working but OAuth2 is not. I can get as far as logging in as shown here:

When hitting Execute on an operation, it's not adding an Authorization HTTP header to the request:

Here is the code I'm using for OAuth2:
var scheme = new OAuth2Scheme()
{
AuthorizationUrl = "https://login.microsoftonline.com/{Company Name}.onmicrosoft.com/oauth2/authorize",
Description = "OAuth2 Authentication using Azure Active Directory.",
Flow = "implicit",
Type = "oauth2"
};
options.AddSecurityDefinition("oauth2", scheme);
options.OperationFilter<ClaimsOperationFilter>();
public class ClaimsOperationFilter : IOperationFilter
{
public void Apply(Operation operation, OperationFilterContext context)
{
var filterDescriptors = context.ApiDescription.ActionDescriptor.FilterDescriptors;
var authorizationRequirements = filterDescriptors.GetPolicyRequirements();
var claimTypes = authorizationRequirements
.OfType<ClaimsAuthorizationRequirement>()
.Select(x => x.ClaimType)
.ToList();
if (claimTypes.Any())
{
operation.Security = new List<IDictionary<string, IEnumerable<string>>>
{
new Dictionary<string, IEnumerable<string>>()
{
{ "basic", claimTypes },
{ "oauth2", claimTypes }
}
};
}
}
}
options.OAuthAppName("My Application");
options.OAuthClientId("{Client ID GUID}");
options.OAuthAdditionalQueryStringParams(new { nonce = Guid.NewGuid().ToString() });
{
"swagger": "2.0",
"info": {
"version": "1.0",
"title": "...Omitted",
"description": "...Omitted"
},
"paths": {
"/foo": {
"get": {
"tags": [
"...Omitted"
],
"summary": "...Omitted",
"operationId": "...Omitted",
"consumes": [],
"produces": [
"application/json",
"text/json"
],
"parameters": [],
"responses": {
"200": {
"description": "...Omitted",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/...Omitted"
}
}
},
"401": {
"description": "Unauthorized - The user has not supplied the necessary credentials to access the resource."
},
"403": {
"description": "Forbidden - The user does not have the necessary permissions to access the resource."
}
},
"security": [
{
"basic": [
"roles"
],
"oauth2": [
"roles"
]
}
]
}
}
},
"definitions": {
"...Omitted": {
},
},
"securityDefinitions": {
"basic": {
"type": "basic",
"description": "Basic HTTP Authentication using a username and password."
},
"oauth2": {
"flow": "implicit",
"authorizationUrl": "https://login.microsoftonline.com/{Company Name}.onmicrosoft.com/oauth2/authorize",
"type": "oauth2",
"description": "OAuth2 Authentication using Azure Active Directory."
}
}
}
I also thought oauth2 is not working. It started to work when I changed the example above to this:
public class SecurityRequirementsDocumentFilter : IDocumentFilter
{
public void Apply(SwaggerDocument document, DocumentFilterContext context)
{
document.Security = new List<IDictionary<string, IEnumerable<string>>>()
{
new Dictionary<string, IEnumerable<string>>()
{
{ "oauth2", new string[]{ "openid", "profile", "email" } },
}
};
}
}
oauth2 is the name of my security definition
options.AddSecurityDefinition("oauth2", new OAuth2Scheme
{
Description = "Client credentials needed.",
Type = "oauth2",
Flow = "implicit",
AuthorizationUrl = "http://localhostandstuff/auth/realms/master/protocol/openid-connect/auth",
Scopes = new Dictionary<string, string>
{
{ "openid", "Standard openid scope" },
{ "profile", "Standard openid scope" },
{ "email", "Standard openid scope" },
}
});
@Razzeee That didn't seem to work for me. I still don't see the Authorization HTTP header getting added to the request. I'm going to try and debug the JavaScript to see why that is the case.
I've worked it out, sadly Swagger UI has hard coded the name of the token to access_token and I'm using Azure Active Directory which uses an id_token. I had a workaround in Swagger v2 as described here https://github.com/swagger-api/swagger-ui/issues/1974 that no longer works with v3 because they've hard coded the token name in a few more places :-(
Looks like there is an open issue here https://github.com/swagger-api/swagger-ui/issues/4084?
any 2.1.1 nuget package?
It鈥檚 published but unlisted because there seems to be other issues with it. Working on it
I'm having this bug with Bearer tokens. Here is my C#
c.AddSecurityDefinition("Bearer", new ApiKeyScheme
{
Name = "Authorization",
In = "header",
Description = "JWT Authorization header using the Bearer scheme. Example: \"Bearer {token}\"",
Type = "apiKey"
});

But when i try HttpDelete with [Authorise] Attribute added, this is the response -

The same API tested in Postman works completely fine -

Is your SecurityRequirementsDocumentFilter matching the one from this topic and referenced correctly?
I'm having too, and I add SecurityRequirementsDocumentFilter :
c.AddSecurityDefinition("oauth2", new OAuth2Scheme
{
Type = "oauth2",
Flow = "password",
TokenUrl = "/api/Token/Authenticate"
});
c.DocumentFilter<SecurityRequirementsDocumentFilter>();
I loggin in, but Authorization Token still not being sent in Headers.
Then, I upgrade version to 2.2.0, add AddSecurityRequirement:
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
{
{ "oauth2", new string[] { } }
});
That worked.
This worked for me if you're using a bearer token.
c.AddSecurityDefinition("Bearer", new ApiKeyScheme
{
In = "header",
Description = "Please insert JWT with Bearer into field",
Name = "Authorization",
Type = "apiKey"
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", new string[] { } }
});
@tariknz Thank you for setting authorize in swagger v.2.2 It's work
Just wanted to say that add that the info @tariknz and @RainingNight provided also worked for me. I am using JWT token but I was able to use the oath2 configuration. That way i can use the Authorization Form provided by Swagger UI
c.AddSecurityDefinition("oauth2", new OAuth2Scheme
{
Type = "oauth2",
Flow = "password",
TokenUrl = "/api/token",
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
{
{ "oauth2", new string[] { } }
});
Swagger UI Login

Successfull Call

For JWT
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
{
{ "Bearer", new string[] { } }
});
sovles the problem.
For Oauth2 using Azure AD integration.
c.AddSecurityDefinition("oauth2", new OAuth2Scheme()
{
AuthorizationUrl = $"https://login.microsoftonline.com/{Configuration["AzureAd:TenantId"]}/oauth2/authorize",
Flow = "implicit",
TokenUrl = $"https://login.microsoftonline.com/{Configuration["AzureAd:TenantId"]}/oauth2/token",
Scopes = new Dictionary<string, string> { { "Arch.NetCoreAPI", "Dotnet Core API" } }
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>>
{
{ "oauth2", new string[] { } }
});
Hello. I have problem with getting token by client credentials grant type.
Swashbuckle.AspNetCore V 2.4.0
I've added config for services:
services.AddSwaggerGen(c =>
{
var oauthScheme = new OAuth2Scheme
{
Description =
"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
TokenUrl = "/token",
Flow = "application"
};
c.SwaggerDoc("v1", new Info { Title = "Map Service API", Version = "v1" });
c.AddSecurityDefinition("oauth2", oauthScheme);
IncludeComments(c);
c.DescribeAllEnumsAsStrings();
});
Then added config for app:
app.UseSwaggerUI(c =>
{
c.SwaggerEndpoint("/swagger/v1/swagger.json", "Map Service API V1");
c.OAuthClientId("someclientid");
c.OAuthClientSecret("somepass2app");
c.OAuthRealm(string.Empty);
c.OAuthAppName("SomeService");
});
On trying to send post request for getting token, i see that in form data i have only grant_type property. My clientCredentials converted to Base64 and putted into Authorization header.

Is exist solution for getting my client_id and client_secret from Form Data. Or should I get the values from encoding Authorization header?
P.S. For example with flow flow: password in form data I'm getting username and password.
P.S.S. I have some doubts that this question should be asked in swagger-ui proj. :)
@Cular
In section where you do services.AddSwagger(c => ...)
you must add:
c.AddSecurityRequirement(new Dictionary
{
{ "Bearer", new string[] { } }
});
this tells Swagger to attach the header to requests
@alaniemieckota , yeah, thanks i found it later.
But for me it works by another way:
services.AddSwaggerGen(c =>
{
var oauthScheme = new OAuth2Scheme
{
Description =
"JWT Authorization header using the Bearer scheme. Example: \"Authorization: Bearer {token}\"",
TokenUrl = "/token",
Flow = "application",
Type = "oauth2"
};
c.SwaggerDoc("v1", new Info { Title = "My Service API", Version = "v1" });
c.AddSecurityDefinition("oauth2", oauthScheme);
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>> { { "oauth2", new string[] { } } });
c.DocumentFilter<SecurityRequirementsDocumentFilter>();
IncludeComments(c);
c.DescribeAllEnumsAsStrings();
});
And i did it by encoding Header with basic auth:
if (!context.Request.Headers.TryGetValue("Authorization", out var authorizationHeader) || authorizationHeader.Count < 1 || !authorizationHeader.First().StartsWith("Basic", StringComparison.OrdinalIgnoreCase))
{
context.Response.StatusCode = 400;
await context.Response.WriteAsync(JsonConvert.SerializeObject(new ValidationResult((int)AuthenticationFalied, "Authorization header must contains: Basic {clientCredentials}")));
}
var convertedCredetials = authorizationHeader.First().Replace("Basic ", string.Empty);
var clientCredentials = Encoding.UTF8.GetString(Convert.FromBase64String(convertedCredetials));
var credentials = clientCredentials.Split(':');
var clientid = credentials[0];
var clientsecret = credentials[1];
Result:
Swagger sends (flow = application) basic auth header with Basic clientId:clientSecret, credentials will be in a Base64String for getting JWT.
Next requests will send with Bearer JWT
This issue solved my problem,thanks.
Awesome @Cular, this work for me !!! but I have an issue, how to put the response into the "Available authorizations" when it comes back from azure? How to create a response page to retrieve this info and put it on the needed place?
Than you.
@arlan85, sorry for late response. I have no trouble with case, that you describe. My previous post was implemented with nuget version: 2.5.0. And I don't update my dependency on new version, maybe it helps to you. :)
I had to fiddle around a bit to get this to work for ApiKey auth. Here's what works for me (no need to include the filter mentioned above):
c.AddSecurityDefinition("ApiKeyAuth", new ApiKeyScheme {
Description = "Authorization by pre-shared API key.",
In = "header",
Type = "apiKey",
Name = "X-API-KEY"
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>> {
{ "ApiKeyAuth", new string[0] }
});
`c.AddSecurityDefinition("Bearer", new ApiKeyScheme
{
In = "header",
Description = "Please insert JWT with Bearer into field",
Name = "Authorization",
Type = "apiKey"
});
c.AddSecurityRequirement(new Dictionary
{
{ "Bearer", new string[] { } }
});`
Should add Bearer before token string

It worked with me :)
.FilterDescriptors
.GetPolicyRequirements() Not works for me???
Severity Code Description Project File Line Suppression State
Error CS1061 'IList
Most helpful comment
This worked for me if you're using a bearer token.