Microsoft Entra ID Swagger authentication

658 views Asked by At

I have an API with Swagger and the authorization happens via Microsoft Entra Id. This is working but only on Firefox. When I click Authorization button in Swagger the Edge and Chrome browsers are keep waiting for something but nothing happens. CORS is enabled: policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod(); Swagger registration redirectURL is https://localhost:7215/swagger/oauth2-redirect.html

UPDATE

appsettings.json

{
  "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "domain.onmicrosoft.com",
    "TenantId": "tenentid",
    "ClientId": "clientid",
    "CallbackPath": "/signin-oidc",
    "Scopes": "access_as_user",
  },
  "SwaggerAzureAD": {
    "AuthorizationUrl":       
 "https://login.microsoftonline.com/tenentid/oauth2/v2.0/authorize",
    "TokenUrl": 
 "https://login.microsoftonline.com/tenentid/oauth2/v2.0/token",
    "Scope": "api://clientid/access_as_user",
    "ClientId": "swaggerclientid"
  },
  "MicrosoftGraph": {
    "BaseUrl": "https://graph.microsoft.com/v1.0",
    "Scopes": "user.read"
  }
}

Program.cs

builder.Services.AddAuthentication(
  JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph"))
.AddInMemoryTokenCaches();

builder.Services.AddSwaggerGen(c =>
{
  c.SwaggerDoc("v1",
    new OpenApiInfo
    {
        Title = "Swagger API",
        Version = "v1",
        Description = "Oauth2.0 which uses AuthorizationCode flow",
        Contact = new OpenApiContact
        {
            Name = "name",
            Email = "email",
        }
    });

  c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
  {
    Description = "Oauth2.0 which uses AuthorizationCode flow",
    Name = "oauth2.0",
    Type = SecuritySchemeType.OAuth2,
    Flows = new OpenApiOAuthFlows
    {
        Implicit = new OpenApiOAuthFlow()
        {
            AuthorizationUrl = new Uri(config.SwaggerAzureAD.AuthorizationUrl),
            TokenUrl = new Uri(config.SwaggerAzureAD.TokenUrl),
            Scopes = new Dictionary<string, string>
            {
                {config.SwaggerAzureAD.Scope, "Access API as User"}
            }
        }
    }
  });

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

app.UseSwagger();
app.UseSwaggerUI(options =>
{
  options.OAuthAppName("Swagger Client");
  options.OAuthClientId(config.SwaggerAzureAD.ClientId);
  options.OAuthUsePkce();
  options.OAuthScopeSeparator(" ");
});

UPDATE 2 AADSTS7000215 error is solved when in the appsetings.json I modified client secret declaration in AzureAD section from

"ClientSecret": "xxxxx"

to

"ClientCredentials": [
  {
    "SourceType": "ClientSecret",
    "ClientSecret": "xxxxx"
  }
]

Unfortunately Chrome and Edge stop me after authorization.

UPDATE 3 The problem with the Chrome and Firefox only occurs on my machine. I think it can be problem with Group Policy.

1

There are 1 answers

5
Tiny Wang On

I followed this blog to test in my side and it worked in chrome or firefox.

enter image description here enter image description here

Here's what I did in my side.

builder.Services.AddSwaggerGen(c => {
    c.SwaggerDoc("v1", new OpenApiInfo { Title = "WebApplication1", Version = "v1" });
    c.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme
    {
        Type = SecuritySchemeType.OAuth2,
        Flows = new OpenApiOAuthFlows()
        {
            Implicit = new OpenApiOAuthFlow()
            {
                AuthorizationUrl = new Uri("https://login.microsoftonline.com/tenant_id/oauth2/v2.0/authorize"),
                TokenUrl = new Uri("https://login.microsoftonline.com/tenant_id/oauth2/v2.0/token"),
                Scopes = new Dictionary<string, string> {
                    {
                        "api://aad_app_id/Tiny.Read", "API permission description"
                    }
                }
            }
        }
    });
    c.AddSecurityRequirement(new OpenApiSecurityRequirement() {
        {
            new OpenApiSecurityScheme {
                Reference = new OpenApiReference {
                    Type = ReferenceType.SecurityScheme,
                    Id = "oauth2"
                },
                Scheme = "oauth2",
                Name = "oauth2",
                In = ParameterLocation.Header
            },
            new List < string > ()
        }
    });
});


var app = builder.Build();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    //app.UseSwaggerUI();
    app.UseSwaggerUI(options =>
    {
        options.OAuthAppName("Swagger Client");
        options.OAuthClientId("client_id");
        options.OAuthClientSecret("client_secret");
        options.OAuthUseBasicAuthenticationWithAccessCodeGrant();
    });
}

And my appsettings.json

"AzureAd": {
  "Instance": "https://login.microsoftonline.com/",
  "Domain": "tenant_id",
  "TenantId": "tenant_id",
  "ClientId": "client_id",
  "ClientSecret": "client_secret",
  "CallbackPath": "/signin-oidc"
},

I just add Authorize attribute into my controller, so that without authentication, I would get 401 error.

enter image description here