diff --git a/e2e/config/clients-configuration.json b/e2e/config/clients-configuration.json index 8af1c0a..9a322e4 100644 --- a/e2e/config/clients-configuration.json +++ b/e2e/config/clients-configuration.json @@ -4,7 +4,7 @@ "Description": "Client for implicit flow", "AllowedGrantTypes": ["implicit"], "AllowAccessTokensViaBrowser": true, - "RedirectUris": ["https://www.google.com"], + "RedirectUris": ["https://*.google.com"], "AllowedScopes": ["openid", "profile", "email", "some-custom-identity"], "IdentityTokenLifetime": 3600, "AccessTokenLifetime": 3600 diff --git a/e2e/tests/authorization-endpoint.e2e-spec.ts b/e2e/tests/authorization-endpoint.e2e-spec.ts index 3fead42..2a0685d 100644 --- a/e2e/tests/authorization-endpoint.e2e-spec.ts +++ b/e2e/tests/authorization-endpoint.e2e-spec.ts @@ -41,7 +41,7 @@ describe('Authorization Endpoint', () => { client_id: implicitFlowClient.ClientId, scope: 'openid some-custom-identity', response_type: 'id_token token', - redirect_uri: implicitFlowClient.RedirectUris?.[0], + redirect_uri: implicitFlowClient.RedirectUris?.[0].replace('*', 'www'), state: 'abc', nonce: 'xyz', }; @@ -55,7 +55,7 @@ describe('Authorization Endpoint', () => { await page.keyboard.press('Enter'); await page.waitForNavigation(); const redirectedUrl = new URL(page.url()); - expect(redirectedUrl.origin).toEqual(implicitFlowClient.RedirectUris?.[0]); + expect(redirectedUrl.origin).toEqual(parameters.redirect_uri); const hash = redirectedUrl.hash.slice(1); const query = querystring.parse(hash); diff --git a/e2e/tests/userinfo-endpoint.e2e-spec.ts b/e2e/tests/userinfo-endpoint.e2e-spec.ts index 96a6194..7acca9f 100644 --- a/e2e/tests/userinfo-endpoint.e2e-spec.ts +++ b/e2e/tests/userinfo-endpoint.e2e-spec.ts @@ -41,7 +41,7 @@ describe('UserInfo Endpoint', () => { client_id: implicitFlowClient.ClientId, scope: 'openid profile some-custom-identity', response_type: 'id_token token', - redirect_uri: implicitFlowClient.RedirectUris?.[0], + redirect_uri: implicitFlowClient.RedirectUris?.[0].replace('*', 'www'), state: 'abc', nonce: 'xyz', }; @@ -55,7 +55,7 @@ describe('UserInfo Endpoint', () => { await page.keyboard.press('Enter'); await page.waitForNavigation(); const redirectedUrl = new URL(page.url()); - expect(redirectedUrl.origin).toEqual(implicitFlowClient.RedirectUris?.[0]); + expect(redirectedUrl.origin).toEqual(parameters.redirect_uri); const hash = redirectedUrl.hash.slice(1); const query = querystring.parse(hash); diff --git a/src/Startup.cs b/src/Startup.cs index cb420bd..52ad2a9 100644 --- a/src/Startup.cs +++ b/src/Startup.cs @@ -24,7 +24,8 @@ public void ConfigureServices(IServiceCollection services) .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryApiScopes(Config.GetApiScopes()) .AddInMemoryClients(Config.GetClients()) - .AddTestUsers(Config.GetUsers()); + .AddTestUsers(Config.GetUsers()) + .AddRedirectUriValidator(); services.AddRouting(); services.AddCors(); diff --git a/src/UriValidator.cs b/src/UriValidator.cs new file mode 100644 index 0000000..73a8c8a --- /dev/null +++ b/src/UriValidator.cs @@ -0,0 +1,28 @@ +using System.Threading.Tasks; +using IdentityServer4.Models; +using IdentityServer4.Validation; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System; +using System.Text.RegularExpressions; + +namespace OpenIdConnectServer +{ + internal class UriValidator : IRedirectUriValidator + { + + public Task IsPostLogoutRedirectUriValidAsync(string requestedUri, Client client) + { + return Task.FromResult(client.RedirectUris.Any(allowedUri => + Regex.Match(requestedUri, Regex.Escape(allowedUri).Replace("\\*", "[a-zA-Z0-9.]+?")).Success + )); + } + + public Task IsRedirectUriValidAsync(string requestedUri, Client client) + { + return Task.FromResult(client.RedirectUris.Any(allowedUri => + Regex.Match(requestedUri, Regex.Escape(allowedUri).Replace("\\*", "[a-zA-Z0-9.]+?")).Success + )); } + } +} \ No newline at end of file