From b4d5b771d145fd850c3449ba3975f99bbcb7e7e6 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 16 May 2023 10:35:23 +0800 Subject: [PATCH 1/5] Enhance Swagger to support OpenIdConnect --- .../AbpSwaggerGenServiceCollectionExtensions.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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..38e104fab5 100644 --- a/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs @@ -35,10 +35,12 @@ public static class AbpSwaggerGenServiceCollectionExtensions [NotNull] Dictionary scopes, Action setupAction = null, string authorizationEndpoint = "/connect/authorize", - string tokenEndpoint = "/connect/token") + string tokenEndpoint = "/connect/token", + string openIdConnectDiscoveryEndpoint = "/.well-known/openid-configuration") { var authorizationUrl = new Uri($"{authority.TrimEnd('/')}{authorizationEndpoint.EnsureStartsWith('/')}"); var tokenUrl = new Uri($"{authority.TrimEnd('/')}{tokenEndpoint.EnsureStartsWith('/')}"); + var openIdConnectDiscoveryUrl = new Uri($"{authority.TrimEnd('/')}{openIdConnectDiscoveryEndpoint.EnsureStartsWith('/')}"); return services .AddAbpSwaggerGen() @@ -47,7 +49,8 @@ public static class AbpSwaggerGenServiceCollectionExtensions { options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { - Type = SecuritySchemeType.OAuth2, + Type = SecuritySchemeType.OpenIdConnect, + OpenIdConnectUrl = openIdConnectDiscoveryUrl, Flows = new OpenApiOAuthFlows { AuthorizationCode = new OpenApiOAuthFlow From 8fb15b378ce025f869b8ebf878dd88d06c4c7961 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Tue, 16 May 2023 15:46:19 +0800 Subject: [PATCH 2/5] Add AddAbpSwaggerGenWithOidc --- ...bpSwaggerGenServiceCollectionExtensions.cs | 71 +++++++++++++++---- .../wwwroot/swagger/ui/abp.swagger.js | 15 ++++ 2 files changed, 72 insertions(+), 14 deletions(-) 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 38e104fab5..b012300c6f 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; @@ -35,12 +36,10 @@ public static class AbpSwaggerGenServiceCollectionExtensions [NotNull] Dictionary scopes, Action setupAction = null, string authorizationEndpoint = "/connect/authorize", - string tokenEndpoint = "/connect/token", - string openIdConnectDiscoveryEndpoint = "/.well-known/openid-configuration") + string tokenEndpoint = "/connect/token") { var authorizationUrl = new Uri($"{authority.TrimEnd('/')}{authorizationEndpoint.EnsureStartsWith('/')}"); var tokenUrl = new Uri($"{authority.TrimEnd('/')}{tokenEndpoint.EnsureStartsWith('/')}"); - var openIdConnectDiscoveryUrl = new Uri($"{authority.TrimEnd('/')}{openIdConnectDiscoveryEndpoint.EnsureStartsWith('/')}"); return services .AddAbpSwaggerGen() @@ -49,8 +48,7 @@ public static class AbpSwaggerGenServiceCollectionExtensions { options.AddSecurityDefinition("oauth2", new OpenApiSecurityScheme { - Type = SecuritySchemeType.OpenIdConnect, - OpenIdConnectUrl = openIdConnectDiscoveryUrl, + Type = SecuritySchemeType.OAuth2, Flows = new OpenApiOAuthFlows { AuthorizationCode = new OpenApiOAuthFlow @@ -64,19 +62,64 @@ 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, + Action setupAction = null, + List flows = null, + string openIdConnectDiscoveryEndpoint = "/.well-known/openid-configuration") + { + var openIdConnectDiscoveryUrl = new Uri($"{authority.TrimEnd('/')}{openIdConnectDiscoveryEndpoint.EnsureStartsWith('/')}"); + flows ??= new List { "authorization_code"}; + + services.Configure(swaggerUiOptions => + { + swaggerUiOptions.ConfigObject.AdditionalItems["oidcSupportedFlows"] = flows; + }); + + return services + .AddAbpSwaggerGen() + .AddSwaggerGen( + options => + { + options.AddSecurityDefinition("oidc", new OpenApiSecurityScheme + { + Type = SecuritySchemeType.OpenIdConnect, + OpenIdConnectUrl = openIdConnectDiscoveryUrl, + }); + 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..fa0e27dd0c 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 @@ -6,9 +6,11 @@ var abp = abp || {}; var excludeUrl = ["swagger.json", "connect/token"] var firstRequest = true; + var oidcSupportedFlows = configObject.oidcSupportedFlows || []; abp.appPath = configObject.baseUrl || abp.appPath; var requestInterceptor = configObject.requestInterceptor; + var responseInterceptor = configObject.responseInterceptor; configObject.requestInterceptor = async function(request) { @@ -38,6 +40,19 @@ var abp = abp || {}; return request; }; + configObject.responseInterceptor = async function(response) { + if(response.url.endsWith(".well-known/openid-configuration") && response.status === 200 && oidcSupportedFlows.length > 0) { + var openIdConnectData = JSON.parse(response.text); + openIdConnectData.grant_types_supported = oidcSupportedFlows; + response.text = JSON.stringify(openIdConnectData); + } + + if (responseInterceptor) { + responseInterceptor(response); + } + return response; + }; + return SwaggerUIBundle(configObject); } })(); From 5a7764fc074125369d30d4979e83a85e9d9f1745 Mon Sep 17 00:00:00 2001 From: liangshiwei Date: Fri, 19 May 2023 10:07:39 +0800 Subject: [PATCH 3/5] Add scopes --- ...AbpSwaggerGenServiceCollectionExtensions.cs | 18 +++++++++++------- .../wwwroot/swagger/ui/abp.swagger.js | 13 +++++++++++-- 2 files changed, 22 insertions(+), 9 deletions(-) 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 b012300c6f..b9fc9fb7bb 100644 --- a/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs @@ -82,16 +82,21 @@ public static class AbpSwaggerGenServiceCollectionExtensions public static IServiceCollection AddAbpSwaggerGenWithOidc( this IServiceCollection services, [NotNull] string authority, - Action setupAction = null, - List flows = null, - string openIdConnectDiscoveryEndpoint = "/.well-known/openid-configuration") + string[] scopes = null, + string[] flows = null, + string discoveryEndpoint = null, + Action setupAction = null) { - var openIdConnectDiscoveryUrl = new Uri($"{authority.TrimEnd('/')}{openIdConnectDiscoveryEndpoint.EnsureStartsWith('/')}"); - flows ??= new List { "authorization_code"}; + 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; }); return services @@ -102,8 +107,7 @@ public static class AbpSwaggerGenServiceCollectionExtensions options.AddSecurityDefinition("oidc", new OpenApiSecurityScheme { Type = SecuritySchemeType.OpenIdConnect, - OpenIdConnectUrl = openIdConnectDiscoveryUrl, - + OpenIdConnectUrl = discoveryUrl }); options.AddSecurityRequirement(new OpenApiSecurityRequirement 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 fa0e27dd0c..8c1ef922d6 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 @@ -7,6 +7,7 @@ var abp = abp || {}; var excludeUrl = ["swagger.json", "connect/token"] var firstRequest = true; var oidcSupportedFlows = configObject.oidcSupportedFlows || []; + var oidcSupportedScopes = configObject.oidcSupportedScopes || []; abp.appPath = configObject.baseUrl || abp.appPath; var requestInterceptor = configObject.requestInterceptor; @@ -41,9 +42,17 @@ var abp = abp || {}; }; configObject.responseInterceptor = async function(response) { - if(response.url.endsWith(".well-known/openid-configuration") && response.status === 200 && oidcSupportedFlows.length > 0) { + if(response.url.endsWith(".well-known/openid-configuration") && response.status === 200) { var openIdConnectData = JSON.parse(response.text); - 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); } From b186d330e9bc6dbb939dccdc0eb5b2b706f9920a Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Tue, 20 Jun 2023 14:32:48 -0400 Subject: [PATCH 4/5] Oidc support for different issuer and metadata address --- ...bpSwaggerGenServiceCollectionExtensions.cs | 2 ++ .../wwwroot/swagger/ui/abp.swagger.js | 30 ++++++++++++------- 2 files changed, 22 insertions(+), 10 deletions(-) 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 b9fc9fb7bb..b895e86598 100644 --- a/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs @@ -97,6 +97,8 @@ public static class AbpSwaggerGenServiceCollectionExtensions { swaggerUiOptions.ConfigObject.AdditionalItems["oidcSupportedFlows"] = flows; swaggerUiOptions.ConfigObject.AdditionalItems["oidcSupportedScopes"] = scopes; + swaggerUiOptions.ConfigObject.AdditionalItems["oidcAuthority"] = authority; + swaggerUiOptions.ConfigObject.AdditionalItems["oidcDiscoveryEndpoint"] = discoveryEndpoint; }); return services 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 8c1ef922d6..c44937e961 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,19 +1,21 @@ 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 oidcAuthority = configObject.oidcAuthority || []; + 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; @@ -25,6 +27,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 = new URL(oidcAuthority) + ".well-known/openid-configuration"; + } var antiForgeryToken = abp.security.antiForgery.getToken(); if (antiForgeryToken) { @@ -41,18 +47,22 @@ var abp = abp || {}; return request; }; - configObject.responseInterceptor = async function(response) { - if(response.url.endsWith(".well-known/openid-configuration") && response.status === 200) { + configObject.responseInterceptor = async function (response) { + if (response.url.endsWith(".well-known/openid-configuration") && response.status === 200) { var openIdConnectData = JSON.parse(response.text); - - if(oidcSupportedFlows.length > 0){ + + if (oidcDiscoveryEndpoint.length > 0) { openIdConnectData.grant_types_supported = oidcSupportedFlows; } - - if(oidcSupportedScopes.length > 0) { + + if (oidcSupportedFlows.length > 0) { + openIdConnectData.grant_types_supported = oidcSupportedFlows; + } + + if (oidcSupportedScopes.length > 0) { openIdConnectData.scopes_supported = oidcSupportedScopes; } - + response.text = JSON.stringify(openIdConnectData); } From 773f08959e4c87d0d26dad9cd04500837a48e59b Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Tue, 20 Jun 2023 15:10:50 -0400 Subject: [PATCH 5/5] using real dns for authority instead of service-name --- .../AbpSwaggerGenServiceCollectionExtensions.cs | 1 - .../src/Volo.Abp.Swashbuckle/wwwroot/swagger/ui/abp.swagger.js | 3 +-- 2 files changed, 1 insertion(+), 3 deletions(-) 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 b895e86598..0f5698ab08 100644 --- a/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs +++ b/framework/src/Volo.Abp.Swashbuckle/Microsoft/Extensions/DependencyInjection/AbpSwaggerGenServiceCollectionExtensions.cs @@ -97,7 +97,6 @@ public static class AbpSwaggerGenServiceCollectionExtensions { swaggerUiOptions.ConfigObject.AdditionalItems["oidcSupportedFlows"] = flows; swaggerUiOptions.ConfigObject.AdditionalItems["oidcSupportedScopes"] = scopes; - swaggerUiOptions.ConfigObject.AdditionalItems["oidcAuthority"] = authority; swaggerUiOptions.ConfigObject.AdditionalItems["oidcDiscoveryEndpoint"] = discoveryEndpoint; }); 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 c44937e961..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 @@ -8,7 +8,6 @@ var abp = abp || {}; var firstRequest = true; var oidcSupportedFlows = configObject.oidcSupportedFlows || []; var oidcSupportedScopes = configObject.oidcSupportedScopes || []; - var oidcAuthority = configObject.oidcAuthority || []; var oidcDiscoveryEndpoint = configObject.oidcDiscoveryEndpoint || []; abp.appPath = configObject.baseUrl || abp.appPath; @@ -29,7 +28,7 @@ var abp = abp || {}; } // Intercept .well-known request when the discoveryEndpoint is provided if (!firstRequest && oidcDiscoveryEndpoint.length !== 0 && request.url.includes(".well-known/openid-configuration")) { - request.url = new URL(oidcAuthority) + ".well-known/openid-configuration"; + request.url = oidcDiscoveryEndpoint; } var antiForgeryToken = abp.security.antiForgery.getToken();