/* * Licensed under the Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0) * See https://github.com/openiddict/openiddict-core for more information concerning * the license and the contributors participating to this project. */ using System.Security.Cryptography; using System.Threading; using System.Threading.Tasks; using AspNet.Security.OpenIdConnect.Client; using AspNet.Security.OpenIdConnect.Primitives; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.DependencyInjection; using Moq; using OpenIddict.Core; using Xunit; namespace OpenIddict.Tests { public partial class OpenIddictProviderTests { [Fact] public async Task ExtractLogoutRequest_RequestIdParameterIsRejectedWhenRequestCachingIsDisabled() { // Arrange var server = CreateAuthorizationServer(); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(LogoutEndpoint, new OpenIdConnectRequest { RequestId = "EFAF3596-F868-497F-96BB-AA2AD1F8B7E7" }); // Assert Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, response.Error); Assert.Equal("The 'request_id' parameter is not supported.", response.ErrorDescription); } [Fact] public async Task ExtractLogoutRequest_InvalidRequestIdParameterIsRejected() { // Arrange var server = CreateAuthorizationServer(builder => { builder.Services.AddDistributedMemoryCache(); builder.EnableRequestCaching(); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(LogoutEndpoint, new OpenIdConnectRequest { RequestId = "EFAF3596-F868-497F-96BB-AA2AD1F8B7E7" }); // Assert Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, response.Error); Assert.Equal("The specified 'request_id' parameter is invalid.", response.ErrorDescription); } [Theory] [InlineData("/path", "The 'post_logout_redirect_uri' parameter must be a valid absolute URL.")] [InlineData("/tmp/file.xml", "The 'post_logout_redirect_uri' parameter must be a valid absolute URL.")] [InlineData("C:\\tmp\\file.xml", "The 'post_logout_redirect_uri' parameter must be a valid absolute URL.")] [InlineData("http://www.fabrikam.com/path#param=value", "The 'post_logout_redirect_uri' parameter must not include a fragment.")] public async Task ValidateLogoutRequest_RequestIsRejectedWhenRedirectUriIsInvalid(string address, string message) { // Arrange var server = CreateAuthorizationServer(); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(LogoutEndpoint, new OpenIdConnectRequest { PostLogoutRedirectUri = address }); // Assert Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, response.Error); Assert.Equal(message, response.ErrorDescription); } [Fact] public async Task ValidateLogoutRequest_RequestIsRejectedWhenRedirectUriIsUnknown() { // Arrange var manager = CreateApplicationManager(instance => { instance.Setup(mock => mock.ValidatePostLogoutRedirectUriAsync("http://www.fabrikam.com/path", It.IsAny())) .ReturnsAsync(false); }); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(manager); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(LogoutEndpoint, new OpenIdConnectRequest { PostLogoutRedirectUri = "http://www.fabrikam.com/path" }); // Assert Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, response.Error); Assert.Equal("The specified 'post_logout_redirect_uri' parameter is not valid.", response.ErrorDescription); Mock.Get(manager).Verify(mock => mock.ValidatePostLogoutRedirectUriAsync("http://www.fabrikam.com/path", It.IsAny()), Times.Once()); } [Fact] public async Task HandleLogoutRequest_RequestIsPersistedInDistributedCache() { // Arrange var cache = new Mock(); var generator = new Mock(); var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { instance.Setup(mock => mock.ValidatePostLogoutRedirectUriAsync("http://www.fabrikam.com/path", It.IsAny())) .ReturnsAsync(true); })); builder.Services.AddSingleton(cache.Object); builder.EnableRequestCaching(); builder.Configure(options => options.RandomNumberGenerator = generator.Object); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(LogoutEndpoint, new OpenIdConnectRequest { PostLogoutRedirectUri = "http://www.fabrikam.com/path" }); var identifier = (string) response[OpenIdConnectConstants.Parameters.RequestId]; // Assert Assert.Single(response.GetParameters()); Assert.NotNull(identifier); cache.Verify(mock => mock.SetAsync( OpenIddictConstants.Environment.LogoutRequest + identifier, It.IsAny(), It.IsAny()), Times.Once()); generator.Verify(mock => mock.GetBytes(It.Is(bytes => bytes.Length == 256 / 8)), Times.Once()); } [Fact] public async Task HandleLogoutRequest_RequestsAreNotHandledLocally() { // Arrange var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { instance.Setup(mock => mock.ValidatePostLogoutRedirectUriAsync("http://www.fabrikam.com/path", It.IsAny())) .ReturnsAsync(true); })); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync(LogoutEndpoint, new OpenIdConnectRequest { PostLogoutRedirectUri = "http://www.fabrikam.com/path", State = "af0ifjsldkj" }); // Assert Assert.Equal("af0ifjsldkj", response.State); } [Fact] public async Task ApplyLogoutResponse_ErroredRequestIsNotHandledLocallyWhenStatusCodeMiddlewareIsEnabled() { // Arrange var server = CreateAuthorizationServer(builder => { builder.Services.AddSingleton(CreateApplicationManager(instance => { instance.Setup(mock => mock.ValidatePostLogoutRedirectUriAsync("http://www.fabrikam.com/path", It.IsAny())) .ReturnsAsync(false); })); builder.EnableAuthorizationEndpoint("/logout-status-code-middleware"); }); var client = new OpenIdConnectClient(server.CreateClient()); // Act var response = await client.PostAsync("/logout-status-code-middleware", new OpenIdConnectRequest { PostLogoutRedirectUri = "http://www.fabrikam.com/path" }); // Assert Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, (string) response["error_custom"]); } } }