From c20a5b370e7f3d9d944c768d91b908f43ff755db Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 19 Feb 2021 19:18:19 +0800 Subject: [PATCH 1/3] Add AbpStrictRedirectUriValidator to compatible with tenant name in domain. --- ...entityServerServiceCollectionExtensions.cs | 19 +++++ .../AbpRedirectUriValidatorOptions.cs | 7 ++ .../AbpStrictRedirectUriValidator.cs | 83 +++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerServiceCollectionExtensions.cs create mode 100644 modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpRedirectUriValidatorOptions.cs create mode 100644 modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator.cs diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerServiceCollectionExtensions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerServiceCollectionExtensions.cs new file mode 100644 index 0000000000..633719ae9b --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerServiceCollectionExtensions.cs @@ -0,0 +1,19 @@ +using IdentityServer4.Validation; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; + +namespace Volo.Abp.IdentityServer +{ + public static class AbpIdentityServerServiceCollectionExtensions + { + public static void AddAbpStrictRedirectUriValidator(this IServiceCollection services, string domainFormat) + { + services.Configure(options => + { + options.DomainFormat = domainFormat; + }); + + services.Replace(ServiceDescriptor.Transient()); + } + } +} diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpRedirectUriValidatorOptions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpRedirectUriValidatorOptions.cs new file mode 100644 index 0000000000..082aeb4523 --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpRedirectUriValidatorOptions.cs @@ -0,0 +1,7 @@ +namespace Volo.Abp.IdentityServer +{ + public class AbpRedirectUriValidatorOptions + { + public string DomainFormat { get; set; } + } +} diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator.cs new file mode 100644 index 0000000000..50baadaf2b --- /dev/null +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using IdentityServer4.Models; +using IdentityServer4.Validation; +using Microsoft.Extensions.Options; +using Volo.Abp.Text.Formatting; + +namespace Volo.Abp.IdentityServer +{ + /// + /// Default implementation of redirect URI validator. Validates the URIs against + /// the client's configured URIs. + /// + public class AbpStrictRedirectUriValidator : IRedirectUriValidator + { + protected AbpRedirectUriValidatorOptions Options { get; } + + public AbpStrictRedirectUriValidator(IOptions options) + { + Options = options.Value; + } + + /// + /// Checks if a given URI string is in a collection of strings (using ordinal ignore case comparison) + /// + /// The uris. + /// The requested URI. + /// + protected virtual bool StringCollectionContainsString(IEnumerable uris, string requestedUri) + { + if (uris == null) + { + return false; + } + + foreach (var url in uris) + { + if (url.Contains(requestedUri, StringComparison.OrdinalIgnoreCase)) + { + return true; + } + + if (url.Contains(Options.DomainFormat)) + { + var extractResult = FormattedStringValueExtracter.Extract(requestedUri, url, ignoreCase: true); + if (extractResult.IsMatch) + { + return true; + } + } + } + + return false; + } + + /// + /// Determines whether a redirect URI is valid for a client. + /// + /// The requested URI. + /// The client. + /// + /// true is the URI is valid; false otherwise. + /// + public virtual Task IsRedirectUriValidAsync(string requestedUri, Client client) + { + return Task.FromResult(StringCollectionContainsString(client.RedirectUris, requestedUri)); + } + + /// + /// Determines whether a post logout URI is valid for a client. + /// + /// The requested URI. + /// The client. + /// + /// true is the URI is valid; false otherwise. + /// + public virtual Task IsPostLogoutRedirectUriValidAsync(string requestedUri, Client client) + { + return Task.FromResult(StringCollectionContainsString(client.PostLogoutRedirectUris, requestedUri)); + } + } +} From 17a24a2a7ffacb92f3326d9893de6a64c1249260 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 19 Feb 2021 22:00:21 +0800 Subject: [PATCH 2/3] Add AbpStrictRedirectUriValidator_Tests --- ...entityServerServiceCollectionExtensions.cs | 4 +- .../AbpRedirectUriValidatorOptions.cs | 11 ++- .../AbpStrictRedirectUriValidator.cs | 69 ++++++------------- .../AbpStrictRedirectUriValidator_Tests.cs | 69 +++++++++++++++++++ 4 files changed, 100 insertions(+), 53 deletions(-) create mode 100644 modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator_Tests.cs diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerServiceCollectionExtensions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerServiceCollectionExtensions.cs index 633719ae9b..679078adbc 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerServiceCollectionExtensions.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerServiceCollectionExtensions.cs @@ -6,11 +6,11 @@ namespace Volo.Abp.IdentityServer { public static class AbpIdentityServerServiceCollectionExtensions { - public static void AddAbpStrictRedirectUriValidator(this IServiceCollection services, string domainFormat) + public static void AddAbpStrictRedirectUriValidator(this IServiceCollection services, params string[] domainFormats) { services.Configure(options => { - options.DomainFormat = domainFormat; + options.DomainFormats.AddRange(domainFormats); }); services.Replace(ServiceDescriptor.Transient()); diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpRedirectUriValidatorOptions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpRedirectUriValidatorOptions.cs index 082aeb4523..e9bf575bfe 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpRedirectUriValidatorOptions.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpRedirectUriValidatorOptions.cs @@ -1,7 +1,14 @@ -namespace Volo.Abp.IdentityServer +using System.Collections.Generic; + +namespace Volo.Abp.IdentityServer { public class AbpRedirectUriValidatorOptions { - public string DomainFormat { get; set; } + public List DomainFormats { get; } + + public AbpRedirectUriValidatorOptions() + { + DomainFormats = new List(); + } } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator.cs index 50baadaf2b..94f05b962b 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator.cs @@ -1,5 +1,5 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using IdentityServer4.Models; using IdentityServer4.Validation; @@ -8,11 +8,7 @@ using Volo.Abp.Text.Formatting; namespace Volo.Abp.IdentityServer { - /// - /// Default implementation of redirect URI validator. Validates the URIs against - /// the client's configured URIs. - /// - public class AbpStrictRedirectUriValidator : IRedirectUriValidator + public class AbpStrictRedirectUriValidator : StrictRedirectUriValidator { protected AbpRedirectUriValidatorOptions Options { get; } @@ -21,63 +17,38 @@ namespace Volo.Abp.IdentityServer Options = options.Value; } - /// - /// Checks if a given URI string is in a collection of strings (using ordinal ignore case comparison) - /// - /// The uris. - /// The requested URI. - /// - protected virtual bool StringCollectionContainsString(IEnumerable uris, string requestedUri) + public override async Task IsRedirectUriValidAsync(string requestedUri, Client client) + { + var isAllowed = await base.IsRedirectUriValidAsync(requestedUri, client); + return isAllowed || await IsRedirectUriValidWithDomainFormatsAsync(client.RedirectUris, requestedUri); + } + + public override async Task IsPostLogoutRedirectUriValidAsync(string requestedUri, Client client) + { + var isAllowed = await base.IsPostLogoutRedirectUriValidAsync(requestedUri, client); + return isAllowed || await IsRedirectUriValidWithDomainFormatsAsync(client.PostLogoutRedirectUris, requestedUri); + } + + protected virtual Task IsRedirectUriValidWithDomainFormatsAsync(IEnumerable uris, string requestedUri) { if (uris == null) { - return false; + return Task.FromResult(false); } foreach (var url in uris) { - if (url.Contains(requestedUri, StringComparison.OrdinalIgnoreCase)) - { - return true; - } - - if (url.Contains(Options.DomainFormat)) + if (Options.DomainFormats.Any(x => url.Contains(x))) { var extractResult = FormattedStringValueExtracter.Extract(requestedUri, url, ignoreCase: true); if (extractResult.IsMatch) { - return true; + return Task.FromResult(true); } } } - return false; - } - - /// - /// Determines whether a redirect URI is valid for a client. - /// - /// The requested URI. - /// The client. - /// - /// true is the URI is valid; false otherwise. - /// - public virtual Task IsRedirectUriValidAsync(string requestedUri, Client client) - { - return Task.FromResult(StringCollectionContainsString(client.RedirectUris, requestedUri)); - } - - /// - /// Determines whether a post logout URI is valid for a client. - /// - /// The requested URI. - /// The client. - /// - /// true is the URI is valid; false otherwise. - /// - public virtual Task IsPostLogoutRedirectUriValidAsync(string requestedUri, Client client) - { - return Task.FromResult(StringCollectionContainsString(client.PostLogoutRedirectUris, requestedUri)); + return Task.FromResult(false); } } } diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator_Tests.cs new file mode 100644 index 0000000000..50f84e890e --- /dev/null +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator_Tests.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using IdentityServer4.Models; +using IdentityServer4.Validation; +using Microsoft.Extensions.DependencyInjection; +using Shouldly; +using Xunit; + +namespace Volo.Abp.IdentityServer +{ + public class AbpStrictRedirectUriValidator_Tests : AbpIdentityServerTestBase + { + private readonly IRedirectUriValidator _abpStrictRedirectUriValidator; + + private readonly Client _testClient = new Client + { + RedirectUris = new List + { + "https://{0}.api.abp.io:8080/signin-oidc", + "http://{0}.ng.abp.io/index.html" + }, + PostLogoutRedirectUris = new List + { + "https://{0}.api.abp.io:8080/signin-oidc", + "http://{0}.ng.abp.io/index.html" + } + }; + + public AbpStrictRedirectUriValidator_Tests() + { + _abpStrictRedirectUriValidator = GetRequiredService(); + } + + protected override void AfterAddApplication(IServiceCollection services) + { + services.AddAbpStrictRedirectUriValidator("{0}.api.abp.io:8080/signin-oidc", "{0}.ng.abp.io/index.html"); + } + + [Fact] + public void Should_Register_AbpStrictRedirectUriValidator() + { + _abpStrictRedirectUriValidator.GetType().ShouldBe(typeof(AbpStrictRedirectUriValidator)); + } + + [Fact] + public async Task IsRedirectUriValidAsync() + { + (await _abpStrictRedirectUriValidator.IsRedirectUriValidAsync("https://t1.api.abp.io:8080/signin-oidc", _testClient)).ShouldBeTrue(); + (await _abpStrictRedirectUriValidator.IsRedirectUriValidAsync("http://t2.ng.abp.io/index.html", _testClient)).ShouldBeTrue(); + + (await _abpStrictRedirectUriValidator.IsRedirectUriValidAsync("https://api.abp:8080/", _testClient)).ShouldBeFalse(); + (await _abpStrictRedirectUriValidator.IsRedirectUriValidAsync("http://ng.abp.io", _testClient)).ShouldBeFalse(); + (await _abpStrictRedirectUriValidator.IsRedirectUriValidAsync("https://api.t1.abp:8080/", _testClient)).ShouldBeFalse(); + (await _abpStrictRedirectUriValidator.IsRedirectUriValidAsync("http://ng.t1.abp.io", _testClient)).ShouldBeFalse(); + } + + [Fact] + public async Task IsPostLogoutRedirectUriValidAsync() + { + (await _abpStrictRedirectUriValidator.IsPostLogoutRedirectUriValidAsync("https://t1.api.abp.io:8080/signin-oidc", _testClient)).ShouldBeTrue(); + (await _abpStrictRedirectUriValidator.IsPostLogoutRedirectUriValidAsync("http://t2.ng.abp.io/index.html", _testClient)).ShouldBeTrue(); + + (await _abpStrictRedirectUriValidator.IsPostLogoutRedirectUriValidAsync("https://api.abp:8080/", _testClient)).ShouldBeFalse(); + (await _abpStrictRedirectUriValidator.IsPostLogoutRedirectUriValidAsync("http://ng.abp.io", _testClient)).ShouldBeFalse(); + (await _abpStrictRedirectUriValidator.IsPostLogoutRedirectUriValidAsync("https://api.t1.abp:8080/", _testClient)).ShouldBeFalse(); + (await _abpStrictRedirectUriValidator.IsPostLogoutRedirectUriValidAsync("http://ng.t1.abp.io", _testClient)).ShouldBeFalse(); + } + } +} From 0c555475918c9be408fb4201f41810d4e5a21316 Mon Sep 17 00:00:00 2001 From: maliming Date: Fri, 19 Feb 2021 22:43:09 +0800 Subject: [PATCH 3/3] Remove AbpRedirectUriValidatorOptions --- ...pIdentityServerServiceCollectionExtensions.cs | 7 +------ .../AbpRedirectUriValidatorOptions.cs | 14 -------------- .../AbpStrictRedirectUriValidator.cs | 16 +++------------- .../AbpStrictRedirectUriValidator_Tests.cs | 2 +- 4 files changed, 5 insertions(+), 34 deletions(-) delete mode 100644 modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpRedirectUriValidatorOptions.cs diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerServiceCollectionExtensions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerServiceCollectionExtensions.cs index 679078adbc..ec45ee32b6 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerServiceCollectionExtensions.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpIdentityServerServiceCollectionExtensions.cs @@ -6,13 +6,8 @@ namespace Volo.Abp.IdentityServer { public static class AbpIdentityServerServiceCollectionExtensions { - public static void AddAbpStrictRedirectUriValidator(this IServiceCollection services, params string[] domainFormats) + public static void AddAbpStrictRedirectUriValidator(this IServiceCollection services) { - services.Configure(options => - { - options.DomainFormats.AddRange(domainFormats); - }); - services.Replace(ServiceDescriptor.Transient()); } } diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpRedirectUriValidatorOptions.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpRedirectUriValidatorOptions.cs deleted file mode 100644 index e9bf575bfe..0000000000 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpRedirectUriValidatorOptions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; - -namespace Volo.Abp.IdentityServer -{ - public class AbpRedirectUriValidatorOptions - { - public List DomainFormats { get; } - - public AbpRedirectUriValidatorOptions() - { - DomainFormats = new List(); - } - } -} diff --git a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator.cs b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator.cs index 94f05b962b..e67740f7f1 100644 --- a/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator.cs +++ b/modules/identityserver/src/Volo.Abp.IdentityServer.Domain/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator.cs @@ -10,13 +10,6 @@ namespace Volo.Abp.IdentityServer { public class AbpStrictRedirectUriValidator : StrictRedirectUriValidator { - protected AbpRedirectUriValidatorOptions Options { get; } - - public AbpStrictRedirectUriValidator(IOptions options) - { - Options = options.Value; - } - public override async Task IsRedirectUriValidAsync(string requestedUri, Client client) { var isAllowed = await base.IsRedirectUriValidAsync(requestedUri, client); @@ -38,13 +31,10 @@ namespace Volo.Abp.IdentityServer foreach (var url in uris) { - if (Options.DomainFormats.Any(x => url.Contains(x))) + var extractResult = FormattedStringValueExtracter.Extract(requestedUri, url, ignoreCase: true); + if (extractResult.IsMatch) { - var extractResult = FormattedStringValueExtracter.Extract(requestedUri, url, ignoreCase: true); - if (extractResult.IsMatch) - { - return Task.FromResult(true); - } + return Task.FromResult(true); } } diff --git a/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator_Tests.cs b/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator_Tests.cs index 50f84e890e..447b0bd008 100644 --- a/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator_Tests.cs +++ b/modules/identityserver/test/Volo.Abp.IdentityServer.Domain.Tests/Volo/Abp/IdentityServer/AbpStrictRedirectUriValidator_Tests.cs @@ -33,7 +33,7 @@ namespace Volo.Abp.IdentityServer protected override void AfterAddApplication(IServiceCollection services) { - services.AddAbpStrictRedirectUriValidator("{0}.api.abp.io:8080/signin-oidc", "{0}.ng.abp.io/index.html"); + services.AddAbpStrictRedirectUriValidator(); } [Fact]