diff --git a/source/Core/Configuration/Hosting/WebApiConfig.cs b/source/Core/Configuration/Hosting/WebApiConfig.cs index f8304fe26..3254069a7 100644 --- a/source/Core/Configuration/Hosting/WebApiConfig.cs +++ b/source/Core/Configuration/Hosting/WebApiConfig.cs @@ -93,11 +93,11 @@ private static void ConfigureRoutes(IdentityServerOptions options, HttpConfigura config.Routes.MapHttpRoute( Constants.RouteNames.Oidc.Authorize, Constants.RoutePaths.Oidc.Authorize, - new { controller = "AuthorizeEndpoint", action = "Get" }); + new { controller = "AuthorizeEndpoint", action = "Process" }); config.Routes.MapHttpRoute( Constants.RouteNames.Oidc.Consent, Constants.RoutePaths.Oidc.Consent, - new { controller = "AuthorizeEndpoint", action = "PostConsent" }); + new { controller = "AuthorizeEndpoint", action = "SubmitConsent" }); config.Routes.MapHttpRoute( Constants.RouteNames.Oidc.SwitchUser, Constants.RoutePaths.Oidc.SwitchUser, diff --git a/source/Core/Endpoints/Connect/AuthorizeEndpointController.cs b/source/Core/Endpoints/Connect/AuthorizeEndpointController.cs index 2c3a6a2e5..8efd23e20 100644 --- a/source/Core/Endpoints/Connect/AuthorizeEndpointController.cs +++ b/source/Core/Endpoints/Connect/AuthorizeEndpointController.cs @@ -97,11 +97,31 @@ public AuthorizeEndpointController( /// The request. /// [HttpGet] - public async Task Get(HttpRequestMessage request) + [HttpPost] + public async Task Process(HttpRequestMessage request) { Logger.Info("Start authorize request"); - var response = await ProcessRequestAsync(request.RequestUri.ParseQueryString()); + NameValueCollection parameters = null; + if (request.Method == HttpMethod.Get) + { + parameters = request.RequestUri.ParseQueryString(); + } + else if (request.Method == HttpMethod.Post) + { + if (!request.Content.IsFormData()) + { + return StatusCode(System.Net.HttpStatusCode.UnsupportedMediaType); + } + + parameters = await request.Content.ReadAsFormDataAsync(); + } + else + { + return StatusCode(System.Net.HttpStatusCode.MethodNotAllowed); + } + + var response = await ProcessRequestAsync(parameters); Logger.Info("End authorize request"); return response; @@ -174,7 +194,7 @@ private async Task ProcessRequestAsync(NameValueCollection pa [HttpPost] [ValidateAntiForgeryToken] - public Task PostConsent(UserConsent model) + public Task SubmitConsent(UserConsent model) { Logger.Info("Resuming from consent, restarting validation"); return ProcessRequestAsync(Request.RequestUri.ParseQueryString(), model ?? new UserConsent()); diff --git a/source/Core/Resources/T4resx.cs b/source/Core/Resources/T4resx.cs index 63b3dff36..333e4e0fb 100644 --- a/source/Core/Resources/T4resx.cs +++ b/source/Core/Resources/T4resx.cs @@ -19,7 +19,7 @@ public class EventIds public const string PreLoginSuccess = "PreLoginSuccess"; public const string ResourceOwnerFlowLoginFailure = "ResourceOwnerFlowLoginFailure"; public const string ResourceOwnerFlowLoginSuccess = "ResourceOwnerFlowLoginSuccess"; - public const string TokenRevoked = "TokenRevoked"; + public const string TokenRevoked = "TokenRevoked"; } public class MessageIds { diff --git a/source/Tests/UnitTests/Conformance/Basic/RedirectUriTests.cs b/source/Tests/UnitTests/Conformance/Basic/RedirectUriTests.cs index 25108508c..972b7d239 100644 --- a/source/Tests/UnitTests/Conformance/Basic/RedirectUriTests.cs +++ b/source/Tests/UnitTests/Conformance/Basic/RedirectUriTests.cs @@ -117,6 +117,36 @@ public void Preserves_query_parameters_in_redirect_uri() query["baz"].ToString().Should().Be("quux"); } + [Fact] + [Trait("Category", Category)] + public void POST_allowed_to_authorization_endpoint() + { + host.Login(); + + var disco = host.GetDiscoveryDocument(); + var url = disco["authorization_endpoint"].ToString(); + + + var nonce = Guid.NewGuid().ToString(); + var state = Guid.NewGuid().ToString(); + + var data = new Dictionary + { + {"client_id", client_id }, + {"redirect_uri", redirect_uri }, + {"scope", "openid" }, + {"response_type", "code" }, + {"state", state }, + {"nonce", nonce}, + }; + + var result = host.Client.PostAsync(url, new FormUrlEncodedContent(data)).Result; + result.StatusCode.Should().Be(HttpStatusCode.Redirect); + result.Headers.Location.AbsoluteUri.Should().StartWith("https://code_client/callback"); + result.Headers.Location.AbsolutePath.Should().Be("/callback"); + } + + [Fact] [Trait("Category", Category)] public void Rejects_redirect_uri_when_query_parameter_does_not_match() diff --git a/source/Tests/UnitTests/Endpoints/Connect/AuthorizeEndpointControllerTests.cs b/source/Tests/UnitTests/Endpoints/Connect/AuthorizeEndpointControllerTests.cs index 5b1d1ed28..2cd9832b3 100644 --- a/source/Tests/UnitTests/Endpoints/Connect/AuthorizeEndpointControllerTests.cs +++ b/source/Tests/UnitTests/Endpoints/Connect/AuthorizeEndpointControllerTests.cs @@ -72,5 +72,12 @@ public void PostConsent_NoBody_ReturnsErrorPage() var resp = PostForm(Constants.RoutePaths.Oidc.Consent, (object)null); resp.AssertPage("error"); } + + [Fact] + public void PostAuthorize_Json_ReturnsError() + { + var response = client.PostAsJsonAsync(Url(Constants.RoutePaths.Oidc.Authorize), new { foo = "bar" }).Result; + response.StatusCode.Should().Be(HttpStatusCode.UnsupportedMediaType); + } } }