I am trying to get OAuth code flow with PCKE to work with Swashbuckle (6.2.3) and swagger ui in .NET 6. There are a few things that happen successfully:
- In swagger UI I can click on "Authorize" button and get redirected to Azure for login.
- The redirect successfully returns to swagger ui and I can see in the network tab that the token is retrieved from Azure by swagger ui.
The problem is when I try to call the sample weather forecast API using swagger UI, no token is attached to the authorization header and it looks like this in the request:
authorization: Bearer undefined
And here is my code:
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.Identity.Web;
using Microsoft.OpenApi.Models;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAdB2C"));
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen(options =>
{
const string oAuth2 = "oauth2";
options.AddSecurityDefinition(oAuth2, new OpenApiSecurityScheme
{
Type = SecuritySchemeType.OAuth2,
Flows = new OpenApiOAuthFlows
{
AuthorizationCode = new OpenApiOAuthFlow
{
AuthorizationUrl = new Uri(builder.Configuration["AzureAdB2C:AuthorizationUrl"]),
TokenUrl = new Uri(builder.Configuration["AzureAdB2C:TokenUrl"]),
Scopes = {{"openid", "Sign users in"}, {"offline_access", "Maintain access to data you have given it access to"}}
}
},
In = ParameterLocation.Header,
BearerFormat = "JWT",
Scheme = "bearer",
Name = "authorization"
});
options.AddSecurityRequirement(new OpenApiSecurityRequirement
{
{
new OpenApiSecurityScheme
{
Reference = new OpenApiReference
{
Id = oAuth2,
Type = ReferenceType.SecurityScheme
},
}, new List<string> {"openid", "offline_access"}
}
});
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI(options =>
{
options.OAuthClientId(builder.Configuration["AzureAdB2C:ClientId"]);
options.OAuthScopes("openid", "offline_access");
options.OAuthUsePkce();
});
}
app.UseHttpsRedirection();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllers();
app.Run();
I'm not sure what I'm missing. Any ideas?
UPDATE: I have been able to get it to work with something like this:
options.UseRequestInterceptor("(req) => { req.headers['Authorization'] = 'Bearer ' + window?.swaggerUIRedirectOauth2?.auth?.token?.id_token; return req; }");
But it doesn't look like a proper solution.