Swashbuckle.aspnetcore: OAuth2 Implicit not working with AzureAD id_token

Created on 28 Aug 2019  路  11Comments  路  Source: domaindrivendev/Swashbuckle.AspNetCore

Looks like the authentication request is hard-coding the response_type of 'token'. We need the ability to send 'id_token token' as the response type in order to get an id_token back from AzureAD and have that id_token passed in the auth header instead of the access_token.

I am using OIDC with Azure v2.0 endpoints for OAuth2. Running on dotnet core 2.2 and Swashbuckle.AspNetCore 4.0.1.

Url showing response_type of token:
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?response_type=token&client_id=.......

upstream-swagger-ui

Most helpful comment

Thanks for your reply. Unfortunately, adding the response_type in this manner results in an AzureAD error stating the following: "AADSTS9000411: The request is not properly formatted. The parameter 'response_type' is duplicated."

I was, however, able to use an older method to replace the response_type query param to what I want. This works, but then I can't seem to tell Swagger UI to use the id_token for my authorization, instead of the access_token.

I attempted using Swashbuckle 5.0.0-rc2, which allowed me to configure OIDC. After clicking the Authorize button, the modal that pops up was blank. Maybe I just need to play with that some more. Do you have an example by chance?

All 11 comments

// inside AddSwaggerGen
c.AddSecurityDefinition("oauth2", new OAuth2Scheme 
{
    Type = "oauth2",
    Flow = "implicit",
    AuthorizationUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize",
    Scopes = new Dictionary<string, string> 
    {
        {"openid", "oidc standard"}
    }
});
c.AddSecurityRequirement(new Dictionary<string, IEnumerable<string>> 
{
    {"oauth2", new[] {"openid"}}
});

// inside UseSwaggerUI
c.OAuthClientId(ClientId);

// implementation of IOperationFilter (pretty much copied from docs)
public void Apply(Operation operation, OperationFilterContext context) 
{
    var requiredScopes = context.MethodInfo
        .GetCustomAttributes(true)
        .OfType<AuthorizeAttribute>()
        .Select(attr => attr.Policy)
        .Distinct()
        .ToList();
    if (!requiredScopes.Any()) return;

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

    operation.Security = new List<IDictionary<string, IEnumerable<string>>> 
    {
        new Dictionary<string, IEnumerable<string>> {{"oauth2", requiredScopes}}
    };
}

I ran into the same problem and found two solutions:

  1. Update to Swashbuckle 5 which uses a Swagger UI version that supports OIDC
  2. A little hack in the current version: You can add the response type ?response_type=token id_token directly to the authorization url:
c.AddSecurityDefinition("oauth2", new OAuth2Scheme 
{
    Type = "oauth2",
    Flow = "implicit",
    AuthorizationUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?response_type=token id_token",
    Scopes = new Dictionary<string, string> 
    {
        {"openid", "oidc standard"}
    }
});

Thanks for your reply. Unfortunately, adding the response_type in this manner results in an AzureAD error stating the following: "AADSTS9000411: The request is not properly formatted. The parameter 'response_type' is duplicated."

I was, however, able to use an older method to replace the response_type query param to what I want. This works, but then I can't seem to tell Swagger UI to use the id_token for my authorization, instead of the access_token.

I attempted using Swashbuckle 5.0.0-rc2, which allowed me to configure OIDC. After clicking the Authorize button, the modal that pops up was blank. Maybe I just need to play with that some more. Do you have an example by chance?

With 5.0.0-rc2, i've tried this:

c.AddSecurityDefinition("oidc", new OpenApiSecurityScheme
{
    Type = SecuritySchemeType.OpenIdConnect,
    OpenIdConnectUrl = new Uri("https://login.microsoftonline.com/common/v2.0/.well-known/openid-configuration")
});
c.AddSecurityRequirement(new OpenApiSecurityRequirement
{
    {
        new OpenApiSecurityScheme
        {
            Reference = new OpenApiReference {Type = ReferenceType.SecurityScheme, Id = "oidc"}
        }, new string[] { }
    }
});

From what I understand, scope definitions are not needed here since those are available in the discovery url. I have tried specifying an implicit flow with and without scopes anyway, just in case, same result. Available authorizations modal is empty, so I cannot continue to authorize in Swagger UI.

Oh, it worked with the oidc implementation I tested https://demo.identityserver.io/

I actually had the same problem with the v5 version. Did you see that there is a dedicated documentation for v5? https://github.com/domaindrivendev/Swashbuckle.AspNetCore/blob/master/README-v5.md

You could open a new issue to either fix it if it is a bug or improve the documentation.

I reviewed the v5 docs, yes. Nothing specific about the OpenIdConnect security scheme. With your identityserver demo, did you just create your own identity server implementation? Or is that hitting an instance of Azure AD?

I have opened a new issue specific to the blank modal in v5 rc2 #1241

I reviewed the v5 docs, yes. Nothing specific about the OpenIdConnect security scheme. With your identityserver demo, did you just create your own identity server implementation? Or is that hitting an instance of Azure AD?

I used the demo server directly but it should not matter if you use another provider behind your instance since the request is processed by the identity server 4 logic.

Looks like using swagger-ui 3.25 may fix this ?https://github.com/domaindrivendev/Swashbuckle.AspNetCore/pull/1525

Interesting, that a combination of these closed tickets should solve the problem:

Though, after adding Extensions = new Dictionary<string, IOpenApiExtension> { {"x-tokenName", new OpenApiString("id_token") } }, _Swashbuckle_ still sends a request with response_type=token instead of response_type=id_token. Not sure if it's an expected behaviour

Interesting, that a combination of these closed tickets should solve the problem:

Though, after adding Extensions = new Dictionary<string, IOpenApiExtension> { {"x-tokenName", new OpenApiString("id_token") } }, _Swashbuckle_ still sends a request with response_type=token instead of response_type=id_token. Not sure if it's an expected behaviour

The issue where response_type=token is sent instead of response_type=id_token seems to be a Swagger UI limitation/bug. Open an issue in the Swagger UI repo (if not already):
https://github.com/swagger-api/swagger-ui/issues

upd: This one seems related: https://github.com/swagger-api/swagger-ui/issues/3906

Was this page helpful?
0 / 5 - 0 ratings

Related issues

jluqueba picture jluqueba  路  4Comments

NinoFloris picture NinoFloris  路  3Comments

govin picture govin  路  3Comments

brucewilkins picture brucewilkins  路  3Comments

rgelb picture rgelb  路  3Comments