diff --git a/src/Auth0.AspNetCore.Authentication/PushedAuthorizationRequest/PushedAuthorizationRequestHandler.cs b/src/Auth0.AspNetCore.Authentication/PushedAuthorizationRequest/PushedAuthorizationRequestHandler.cs index a72e66c..69ab1ad 100644 --- a/src/Auth0.AspNetCore.Authentication/PushedAuthorizationRequest/PushedAuthorizationRequestHandler.cs +++ b/src/Auth0.AspNetCore.Authentication/PushedAuthorizationRequest/PushedAuthorizationRequestHandler.cs @@ -1,3 +1,4 @@ +using System; using System.Net.Http; using System.Net.Http.Json; using System.Threading.Tasks; @@ -22,13 +23,17 @@ public static async Task HandleAsync(RedirectContext context, OpenIdConnectOptio // Read the PAR Endpoint from the OIDC configuration. var oidcConfiguration = await oidcOptions.ConfigurationManager?.GetConfigurationAsync(default)!; - var parEndpoint = oidcConfiguration?.AdditionalData["pushed_authorization_request_endpoint"] as string; + + object? rawParEndpoint = string.Empty; + oidcConfiguration?.AdditionalData.TryGetValue("pushed_authorization_request_endpoint", out rawParEndpoint); + string? parEndpoint = rawParEndpoint as string; // If PAR was enabled in the options, but no `pushed_authorization_request_endpoint` value is find - // in the OIDC configuration, we will skip using Pushed Authorization Request. + // in the OIDC configuration, we will throw an error. if (string.IsNullOrEmpty(parEndpoint)) { - return; + throw new InvalidOperationException( + "Trying to use pushed authorization, but no value for 'pushed_authorization_request_endpoint' was found in the open id configuration."); } var message = context.ProtocolMessage; diff --git a/tests/Auth0.AspNetCore.Authentication.IntegrationTests/Auth0.AspNetCore.Authentication.IntegrationTests.csproj b/tests/Auth0.AspNetCore.Authentication.IntegrationTests/Auth0.AspNetCore.Authentication.IntegrationTests.csproj index d20e576..4624fbf 100644 --- a/tests/Auth0.AspNetCore.Authentication.IntegrationTests/Auth0.AspNetCore.Authentication.IntegrationTests.csproj +++ b/tests/Auth0.AspNetCore.Authentication.IntegrationTests/Auth0.AspNetCore.Authentication.IntegrationTests.csproj @@ -7,6 +7,7 @@ + diff --git a/tests/Auth0.AspNetCore.Authentication.IntegrationTests/Auth0MiddlewareTests.cs b/tests/Auth0.AspNetCore.Authentication.IntegrationTests/Auth0MiddlewareTests.cs index 44a2d2f..025542c 100644 --- a/tests/Auth0.AspNetCore.Authentication.IntegrationTests/Auth0MiddlewareTests.cs +++ b/tests/Auth0.AspNetCore.Authentication.IntegrationTests/Auth0MiddlewareTests.cs @@ -93,6 +93,32 @@ public async Task Should_Redirect_To_Authorize_Endpoint() } } + [Fact] + public async Task Should_Throw_When_Using_PAR_But_No_OIDC_Config() + { + var mockHandler = new OidcMockBuilder() + .MockOpenIdConfig("wellknownconfig_without_par.json") + .MockJwks() + .MockPAR("https://my-par-request-uri") + .Build(); + + using (var server = TestServerBuilder.CreateServer(opt => + { + opt.UsePushedAuthorization = true; + opt.Backchannel = new HttpClient(mockHandler.Object); + })) + { + using (var client = server.CreateClient()) + { + Func act = () => client.SendAsync($"{TestServerBuilder.Host}/{TestServerBuilder.Login}"); + + var exception = await act.Should().ThrowAsync(); + + exception.And.Message.Should().Be("Trying to use pushed authorization, but no value for 'pushed_authorization_request_endpoint' was found in the open id configuration."); + } + } + } + [Fact] public async Task Should_Post_To_PAR_Endpoint() { diff --git a/tests/Auth0.AspNetCore.Authentication.IntegrationTests/Builders/OidcMockBuilder.cs b/tests/Auth0.AspNetCore.Authentication.IntegrationTests/Builders/OidcMockBuilder.cs index f71d083..101eec4 100644 --- a/tests/Auth0.AspNetCore.Authentication.IntegrationTests/Builders/OidcMockBuilder.cs +++ b/tests/Auth0.AspNetCore.Authentication.IntegrationTests/Builders/OidcMockBuilder.cs @@ -24,7 +24,7 @@ public class OidcMockBuilder /// Mock the `.well-known/openid-configuration` request. /// /// The contents of `wellknownconfig.json`, containing some dummy information needed for the tests. - public OidcMockBuilder MockOpenIdConfig() + public OidcMockBuilder MockOpenIdConfig(string configFile = "wellknownconfig.json") { _mockHandler .Protected() @@ -33,7 +33,7 @@ public OidcMockBuilder MockOpenIdConfig() ItExpr.Is(me => me.IsOpenIdConfigurationEndPoint()), ItExpr.IsAny() ) - .ReturnsAsync(ReturnResource("wellknownconfig.json").Result); + .ReturnsAsync(ReturnResource(configFile).Result); return this; } diff --git a/tests/Auth0.AspNetCore.Authentication.IntegrationTests/wellknownconfig_without_par.json b/tests/Auth0.AspNetCore.Authentication.IntegrationTests/wellknownconfig_without_par.json new file mode 100644 index 0000000..70e44ec --- /dev/null +++ b/tests/Auth0.AspNetCore.Authentication.IntegrationTests/wellknownconfig_without_par.json @@ -0,0 +1,63 @@ +{ + "issuer": "https://tenant.eu.auth0.com/", + "authorization_endpoint": "https://tenant.eu.auth0.com/authorize", + "token_endpoint": "https://tenant.eu.auth0.com/oauth/token", + "device_authorization_endpoint": "https://tenant.eu.auth0.com/oauth/device/code", + "userinfo_endpoint": "https://tenant.eu.auth0.com/userinfo", + "mfa_challenge_endpoint": "https://tenant.eu.auth0.com/mfa/challenge", + "jwks_uri": "https://tenant.eu.auth0.com/.well-known/jwks.json", + "registration_endpoint": "https://tenant.eu.auth0.com/oidc/register", + "revocation_endpoint": "https://tenant.eu.auth0.com/oauth/revoke", + "scopes_supported": [ + "openid", + "profile", + "offline_access", + "name", + "given_name", + "family_name", + "nickname", + "email", + "email_verified", + "picture", + "created_at", + "identities", + "phone", + "address" + ], + "response_types_supported": [ + "code", + "token", + "id_token", + "code token", + "code id_token", + "token id_token", + "code token id_token" + ], + "code_challenge_methods_supported": [ "S256", "plain" ], + "response_modes_supported": [ "query", "fragment", "form_post" ], + "subject_types_supported": [ "public" ], + "id_token_signing_alg_values_supported": [ "HS256", "RS256" ], + "token_endpoint_auth_methods_supported": [ + "client_secret_basic", + "client_secret_post" + ], + "claims_supported": [ + "aud", + "auth_time", + "created_at", + "email", + "email_verified", + "exp", + "family_name", + "given_name", + "iat", + "identities", + "iss", + "name", + "nickname", + "phone_number", + "picture", + "sub" + ], + "request_uri_parameter_supported": "false" +} \ No newline at end of file