Pokud máme API, které je s authentizací pomocí JWT (JwtBearer) a chceme pomocí Swashbuckle/Swaggeru naše API testovat, je možné se pomocí Swashbuckle/Swaggeru přihlásit a získaný token (id_token/JWT) předávat do API automaticky.
Swashbuckle/Swagger má podporu pro OAuth2, nikoliv však pro OpenID Connect. Avšak implementace OAuth Googlu umožní získat id_token (JWT) pro OpenID Connect. Chce to však jeden trik v javascriptu, který vymění hodnotu response_type „token“ za „token id_token“.
public IServiceProvider ConfigureServices(IServiceCollection services) { ... services .AddAuthentication(options => options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => ... ); ... services.AddSwaggerGen(c => { ... c.AddSecurityDefinition("oauth2", new OAuth2Scheme { Type = "oauth2", Flow = "implicit", AuthorizationUrl = "https://accounts.google.com/o/oauth2/v2/auth", TokenUrl = "https://www.googleapis.com/oauth2/v4/token", Scopes = new Dictionary<string, string> { { "openid profile email", "Default scopes" } } }); c.OperationFilter<AuthorizeCheckOperationFilter>(); }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { app.UseSwaggerUI(c => { // Swashbuckle/Swagger podporují jen OAuth. Pro OpenID Connect je potřeba namísto "response_type=token" posílat "response_type=token id_token". To zajistíme hackem v javascriptu. // Google OAuth navíc vyžaduje parametr nonce, který je v hacku rovněž přidán. c.InjectOnCompleteJavaScript("/swagger-ui-customization.js"); c.ConfigureOAuth2("client-id", "client-secret", "http://localhost:PORT/swagger/ui/o2c-html", "application-name"); c.SwaggerEndpoint("/swagger/current/swagger.json", "Current"); });
Třída AuthorizeCheckOperationFilter zajišťuje doplnění informací o security pro Swashbuckle/Swagger:
internal class AuthorizeCheckOperationFilter : IOperationFilter { public void Apply(Operation operation, OperationFilterContext context) { // Alternativní implementace: https://github.com/domaindrivendev/Swashbuckle/blob/master/Swashbuckle.Dummy.Core/SwaggerExtensions/AssignOAuth2SecurityRequirements.cs // Check for authorize attribute var hasAuthorize = context.ApiDescription.ControllerAttributes().OfType<AuthorizeAttribute>().Any() || context.ApiDescription.ActionAttributes().OfType<AuthorizeAttribute>().Any(); if (hasAuthorize) { // přidá do dokumentace možnou odpověd - 401 operation.Responses.Add("401", new Response { Description = "Unauthorized" }); // přidá informaci o tom, že se má použít pro volání metody authentizační token (zobrazí se červený vykřičník) operation.Security = new List<IDictionary<string, IEnumerable<string>>> { new Dictionary<string, IEnumerable<string>> { { "oauth2", new string[] { "openid profile email" } } } }; } } }
Dále je potřeba do rootu webu umístit soubor swagger-ui-customization.js, který provádí ukrutný hack nad window.open:
// Swagger UI does not support custom response_type parameters. Azure Active Directory requires an 'id_token' value to // be passed instead of 'token' (See https://github.com/swagger-api/swagger-ui/issues/1974). window.swaggerUiAuth = window.swaggerUiAuth || {}; window.swaggerUiAuth.tokenName = 'id_token'; if (!window.isOpenReplaced) { window.open = function (open) { return function (url) { url = url.replace('response_type=token', 'response_type=token%20id_token&nonce=456'); console.log(url); return open.call(window, url); }; }(window.open); window.isOpenReplaced = true; }