diff --git a/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs b/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs index 3c27c640cd..0f5698ab08 100644 --- a/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using JetBrains.Annotations; using Microsoft.OpenApi.Models; using Swashbuckle.AspNetCore.SwaggerGen; +using Swashbuckle.AspNetCore.SwaggerUI; using Volo.Abp.Content; namespace Microsoft.Extensions.DependencyInjection; @@ -61,20 +62,70 @@ public static class AbpSwaggerGenServiceCollectionExtensions options.AddSecurityRequirement(new OpenApiSecurityRequirement { + { + new OpenApiSecurityScheme { - new OpenApiSecurityScheme + Reference = new OpenApiReference { - Reference = new OpenApiReference - { - Type = ReferenceType.SecurityScheme, - Id = "oauth2" - } - }, - Array.Empty() - } + Type = ReferenceType.SecurityScheme, + Id = "oauth2" + } + }, + Array.Empty() + } }); setupAction?.Invoke(options); }); } + + public static IServiceCollection AddAbpSwaggerGenWithOidc( + this IServiceCollection services, + [NotNull] string authority, + string[] scopes = null, + string[] flows = null, + string discoveryEndpoint = null, + Action setupAction = null) + { + var discoveryUrl = discoveryEndpoint != null ? + new Uri(discoveryEndpoint) : + new Uri($"{authority.TrimEnd('/')}/.well-known/openid-configuration"); + + flows ??= new [] { "authorization_code" }; + + services.Configure(swaggerUiOptions => + { + swaggerUiOptions.ConfigObject.AdditionalItems["oidcSupportedFlows"] = flows; + swaggerUiOptions.ConfigObject.AdditionalItems["oidcSupportedScopes"] = scopes; + swaggerUiOptions.ConfigObject.AdditionalItems["oidcDiscoveryEndpoint"] = discoveryEndpoint; + }); + + return services + .AddAbpSwaggerGen() + .AddSwaggerGen( + options => + { + options.AddSecurityDefinition("oidc", new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OpenIdConnect, + OpenIdConnectUrl = discoveryUrl + }); + + options.AddSecurityRequirement(new OpenApiSecurityRequirement + { + { + new OpenApiSecurityScheme + { + Reference = new OpenApiReference + { + Type = ReferenceType.SecurityScheme, + Id = "oidc" + } + }, + Array.Empty() + } + }); + setupAction?.Invoke(options); + }); + } } diff --git a/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js b/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js index c143b7e75e..6edbe815be 100644 --- a/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js +++ b/framework/src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js @@ -1,16 +1,20 @@ var abp = abp || {}; -(function() { +(function () { - abp.SwaggerUIBundle = function(configObject) { + abp.SwaggerUIBundle = function (configObject) { var excludeUrl = ["swagger.json", "connect/token"] var firstRequest = true; + var oidcSupportedFlows = configObject.oidcSupportedFlows || []; + var oidcSupportedScopes = configObject.oidcSupportedScopes || []; + var oidcDiscoveryEndpoint = configObject.oidcDiscoveryEndpoint || []; abp.appPath = configObject.baseUrl || abp.appPath; var requestInterceptor = configObject.requestInterceptor; + var responseInterceptor = configObject.responseInterceptor; - configObject.requestInterceptor = async function(request) { + configObject.requestInterceptor = async function (request) { if (request.url.includes(excludeUrl[1])) { firstRequest = true; @@ -22,6 +26,10 @@ var abp = abp || {}; }); firstRequest = false; } + // Intercept .well-known request when the discoveryEndpoint is provided + if (!firstRequest && oidcDiscoveryEndpoint.length !== 0 && request.url.includes(".well-known/openid-configuration")) { + request.url = oidcDiscoveryEndpoint; + } var antiForgeryToken = abp.security.antiForgery.getToken(); if (antiForgeryToken) { @@ -38,6 +46,31 @@ var abp = abp || {}; return request; }; + configObject.responseInterceptor = async function (response) { + if (response.url.endsWith(".well-known/openid-configuration") && response.status === 200) { + var openIdConnectData = JSON.parse(response.text); + + if (oidcDiscoveryEndpoint.length > 0) { + openIdConnectData.grant_types_supported = oidcSupportedFlows; + } + + if (oidcSupportedFlows.length > 0) { + openIdConnectData.grant_types_supported = oidcSupportedFlows; + } + + if (oidcSupportedScopes.length > 0) { + openIdConnectData.scopes_supported = oidcSupportedScopes; + } + + response.text = JSON.stringify(openIdConnectData); + } + + if (responseInterceptor) { + responseInterceptor(response); + } + return response; + }; + return SwaggerUIBundle(configObject); } })();