public async Task ValidateAuthorizationRequest_AnAccessTokenCannotBeReturnedWhenClientIsConfidential(string type)
        {
            // Arrange
            var application = new OpenIddictApplication();

            var manager = CreateApplicationManager(instance =>
            {
                instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny <CancellationToken>()))
                .ReturnsAsync(application);

                instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny <CancellationToken>()))
                .Returns(new ValueTask <string>(OpenIddictConstants.ClientTypes.Confidential));
            });

            var server = CreateAuthorizationServer(builder =>
            {
                builder.Services.AddSingleton(manager);
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(AuthorizationEndpoint, new OpenIdConnectRequest
            {
                ClientId     = "Fabrikam",
                Nonce        = "n-0S6_WzA2Mj",
                RedirectUri  = "http://www.fabrikam.com/path",
                ResponseType = type,
                Scope        = OpenIdConnectConstants.Scopes.OpenId
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.UnauthorizedClient, response.Error);
            Assert.Equal("The specified 'response_type' parameter is not valid for this client application.", response.ErrorDescription);

            Mock.Get(manager).Verify(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny <CancellationToken>()), Times.Once());
            Mock.Get(manager).Verify(mock => mock.GetClientTypeAsync(application, It.IsAny <CancellationToken>()), Times.Once());
        }
        public async Task InvokeTokenEndpointAsync_ValidateTokenRequest_MissingClientIdCausesAnErrorForClientCredentialsRequests()
        {
            // Arrange
            var server = CreateAuthorizationServer(options => {
                options.Provider.OnValidateTokenRequest = context => {
                    context.Skip();

                    return(Task.FromResult(0));
                };
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest {
                Code      = "SplxlOBeZQQYbYS6WxSbIA",
                GrantType = OpenIdConnectConstants.GrantTypes.ClientCredentials
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.InvalidGrant, response.Error);
            Assert.Equal("Client authentication is required when using client_credentials.", response.ErrorDescription);
        }
        public async Task InvokeTokenEndpointAsync_ValidateTokenRequest_AllowsSkippingToNextMiddleware()
        {
            // Arrange
            var server = CreateAuthorizationServer(options => {
                options.Provider.OnValidateTokenRequest = context => {
                    context.SkipToNextMiddleware();

                    return(Task.FromResult(0));
                };
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest {
                GrantType = OpenIdConnectConstants.GrantTypes.Password,
                Username  = "******",
                Password  = "******"
            });

            // Assert
            Assert.Equal("Bob le Magnifique", (string)response["name"]);
        }
Exemplo n.º 4
0
        public async Task PostConfigure_MissingSigningCredentialsThrowAnException()
        {
            // Arrange
            var server = CreateAuthorizationServer(options =>
            {
                options.AccessTokenHandler = new JwtSecurityTokenHandler();
                options.SigningCredentials.Clear();
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act and assert
            var exception = await Assert.ThrowsAsync <InvalidOperationException>(delegate
            {
                return(client.GetAsync("/"));
            });

            Assert.Equal(
                "At least one signing key must be registered when using JWT as the access token format. " +
                "Consider registering a X.509 certificate using 'options.SigningCredentials.AddCertificate()' " +
                "or 'options.SigningCredentials.AddDevelopmentCertificate()' or call " +
                "'options.SigningCredentials.AddEphemeralKey()' to use an ephemeral key.", exception.Message);
        }
        public async Task InvokeIntrospectionEndpointAsync_MissingClientIdCausesAnErrorForValidatedRequests()
        {
            // Arrange
            var server = CreateAuthorizationServer(options => {
                options.Provider.OnValidateIntrospectionRequest = context => {
                    context.Validate();

                    return(Task.FromResult(0));
                };
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(IntrospectionEndpoint, new OpenIdConnectRequest {
                ClientId = null,
                Token    = "2YotnFZFEjr1zCsicMWpAA"
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.ServerError, response.Error);
            Assert.Equal("An internal server error occurred.", response.ErrorDescription);
        }
        public async Task InvokeLogoutEndpointAsync_ValidateLogoutRequest_AllowsRejectingRequest(string error, string description, string uri)
        {
            // Arrange
            var server = CreateAuthorizationServer(options =>
            {
                options.Provider.OnValidateLogoutRequest = context =>
                {
                    context.Reject(error, description, uri);

                    return(Task.CompletedTask);
                };
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(LogoutEndpoint, new OpenIdConnectRequest());

            // Assert
            Assert.Equal(error ?? OpenIdConnectConstants.Errors.InvalidRequest, response.Error);
            Assert.Equal(description, response.ErrorDescription);
            Assert.Equal(uri, response.ErrorUri);
        }
Exemplo n.º 7
0
        public async Task InvokeAuthorizationEndpointAsync_MissingCodeResponseTypeCausesAnErrorWhenCodeChallengeIsUsed(string type)
        {
            // Arrange
            var server = CreateAuthorizationServer();

            var client = new OpenIdConnectClient(server.HttpClient);

            // Act
            var response = await client.PostAsync(AuthorizationEndpoint, new OpenIdConnectRequest {
                ClientId            = "Fabrikam",
                CodeChallenge       = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
                CodeChallengeMethod = OpenIdConnectConstants.CodeChallengeMethods.Sha256,
                Nonce        = "n-0S6_WzA2Mj",
                RedirectUri  = "http://www.fabrikam.com/path",
                ResponseType = type,
                Scope        = OpenIdConnectConstants.Scopes.OpenId
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, response.Error);
            Assert.Equal("The 'code_challenge' and 'code_challenge_method' parameters " +
                         "can only be used with a response type containing 'code'.", response.ErrorDescription);
        }
        public async Task HandleLogoutRequest_RequestsAreNotHandledLocally()
        {
            // Arrange
            var server = CreateAuthorizationServer(builder => {
                builder.Services.AddSingleton(CreateApplicationManager(instance => {
                    var application = new OpenIddictApplication();

                    instance.Setup(mock => mock.FindByLogoutRedirectUri("http://www.fabrikam.com/path", It.IsAny <CancellationToken>()))
                    .ReturnsAsync(application);
                }));
            });

            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);
        }
        public async Task InvokeTokenEndpointAsync_InvalidRefreshTokenCausesAnError()
        {
            // Arrange
            var server = CreateAuthorizationServer(options => {
                options.Provider.OnValidateTokenRequest = context => {
                    context.Skip();

                    return(Task.FromResult(0));
                };
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest {
                GrantType    = OpenIdConnectConstants.GrantTypes.RefreshToken,
                RefreshToken = "8xLOxBtZp8"
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.InvalidGrant, response.Error);
            Assert.Equal("Invalid ticket", response.ErrorDescription);
        }
        public async Task InvokeRevocationEndpointAsync_ExtractRevocationRequest_AllowsRejectingRequest(string error, string description, string uri)
        {
            // Arrange
            var server = CreateAuthorizationServer(options =>
            {
                options.Provider.OnExtractRevocationRequest = context =>
                {
                    context.Reject(error, description, uri);

                    return(Task.FromResult(0));
                };
            });

            var client = new OpenIdConnectClient(server.HttpClient);

            // Act
            var response = await client.PostAsync(RevocationEndpoint, new OpenIdConnectRequest());

            // Assert
            Assert.Equal(error ?? OpenIdConnectConstants.Errors.InvalidRequest, response.Error);
            Assert.Equal(description, response.ErrorDescription);
            Assert.Equal(uri, response.ErrorUri);
        }
        public async Task ValidateAuthorizationRequest_RequestWithOfflineAccessScopeIsRejectedWhenRefreshTokenFlowIsDisabled()
        {
            // Arrange
            var server = CreateAuthorizationServer(builder =>
            {
                builder.Configure(options => options.GrantTypes.Remove(OpenIdConnectConstants.GrantTypes.RefreshToken));
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(AuthorizationEndpoint, new OpenIdConnectRequest
            {
                ClientId     = "Fabrikam",
                RedirectUri  = "http://www.fabrikam.com/path",
                ResponseType = OpenIdConnectConstants.ResponseTypes.Code,
                Scope        = OpenIdConnectConstants.Scopes.OfflineAccess
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, response.Error);
            Assert.Equal("The 'offline_access' scope is not allowed.", response.ErrorDescription);
        }
Exemplo n.º 12
0
        public async Task HandleConfigurationRequest_EnabledFlowsAreReturned(string flow)
        {
            // Arrange
            var server = CreateAuthorizationServer(builder =>
            {
                builder.Configure(options =>
                {
                    options.GrantTypes.Clear();
                    options.GrantTypes.Add(flow);
                });
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.GetAsync(ConfigurationEndpoint);

            var types = ((JArray)response[OpenIdConnectConstants.Metadata.GrantTypesSupported]).Values <string>();

            // Assert
            Assert.Single(types);
            Assert.Contains(flow, types);
        }
Exemplo n.º 13
0
        public async Task PostConfigure_ThrowsAnExceptionWhenNoSigningKeyIsRegisteredIfTheImplicitFlowIsEnabled()
        {
            // Arrange
            var server = CreateAuthorizationServer(builder =>
            {
                builder.EnableAuthorizationEndpoint("/connect/authorize")
                .AllowImplicitFlow();
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act and assert
            var exception = await Assert.ThrowsAsync <InvalidOperationException>(delegate
            {
                return(client.GetAsync("/"));
            });

            Assert.Equal(
                "At least one asymmetric signing key must be registered when enabling the implicit flow. " +
                "Consider registering a X.509 certificate using 'services.AddOpenIddict().AddSigningCertificate()' " +
                "or 'services.AddOpenIddict().AddDevelopmentSigningCertificate()' or call " +
                "'services.AddOpenIddict().AddEphemeralSigningKey()' to use an ephemeral key.", exception.Message);
        }
Exemplo n.º 14
0
        public async Task ValidateTokenRequest_RequestWithOfflineAccessScopeIsRejectedWhenRefreshTokenFlowIsDisabled()
        {
            // Arrange
            var server = CreateAuthorizationServer(builder =>
            {
                builder.Configure(options => options.GrantTypes.Remove(OpenIdConnectConstants.GrantTypes.RefreshToken));
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest
            {
                GrantType = OpenIdConnectConstants.GrantTypes.Password,
                Username  = "******",
                Password  = "******",
                Scope     = OpenIdConnectConstants.Scopes.OfflineAccess
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, response.Error);
            Assert.Equal("The 'offline_access' scope is not allowed.", response.ErrorDescription);
        }
Exemplo n.º 15
0
        public async Task InvokeCryptographyEndpointAsync_ValidateCryptographyRequest_AllowsHandlingResponse()
        {
            // Arrange
            var server = CreateAuthorizationServer(options => {
                options.Provider.OnValidateCryptographyRequest = context => {
                    context.HandleResponse();

                    context.OwinContext.Response.Headers["Content-Type"] = "application/json";

                    return(context.OwinContext.Response.WriteAsync(JsonConvert.SerializeObject(new {
                        name = "Bob le Magnifique"
                    })));
                };
            });

            var client = new OpenIdConnectClient(server.HttpClient);

            // Act
            var response = await client.GetAsync(CryptographyEndpoint);

            // Assert
            Assert.Equal("Bob le Magnifique", (string)response["name"]);
        }
        public async Task PostConfigure_ThrowsAnExceptionWhenApplicationProviderTypeAndInstanceAreProvided()
        {
            // Arrange
            var server = CreateAuthorizationServer(builder =>
            {
                builder.Configure(options =>
                {
                    options.ApplicationProvider     = new OpenIdConnectServerProvider();
                    options.ApplicationProviderType = typeof(OpenIdConnectServerProvider);
                });
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act and assert
            var exception = await Assert.ThrowsAsync <InvalidOperationException>(delegate
            {
                return(client.GetAsync("/"));
            });

            // Assert
            Assert.Equal("An application provider cannot be registered when a type is specified.", exception.Message);
        }
        public async Task InvokeUserinfoEndpointAsync_ExtractUserinfoRequest_AllowsHandlingResponse()
        {
            // Arrange
            var server = CreateAuthorizationServer(options => {
                options.Provider.OnExtractUserinfoRequest = context => {
                    context.HandleResponse();

                    context.HttpContext.Response.Headers[HeaderNames.ContentType] = "application/json";

                    return(context.HttpContext.Response.WriteAsync(JsonConvert.SerializeObject(new {
                        name = "Bob le Bricoleur"
                    })));
                };
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.GetAsync(UserinfoEndpoint);

            // Assert
            Assert.Equal("Bob le Bricoleur", (string)response["name"]);
        }
        public async Task ValidateAuthorizationRequest_RequestIsRejectedWhenUnregisteredScopeIsSpecified()
        {
            // Arrange
            var server = CreateAuthorizationServer(builder =>
            {
                builder.EnableScopeValidation();
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(AuthorizationEndpoint, new OpenIdConnectRequest
            {
                ClientId     = "Fabrikam",
                RedirectUri  = "http://www.fabrikam.com/path",
                ResponseType = OpenIdConnectConstants.ResponseTypes.Code,
                Scope        = "unregistered_scope"
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, response.Error);
            Assert.Equal("The specified 'scope' parameter is not valid.", response.ErrorDescription);
        }
        public async Task ExtractAuthorizationRequest_UnsupportedRequestParameterIsRejected()
        {
            // Arrange
            var server = CreateAuthorizationServer();

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(AuthorizationEndpoint, new OpenIdConnectRequest
            {
                ClientId    = "Fabrikam",
                RedirectUri = "http://www.fabrikam.com/path",
                Request     = "eyJhbGciOiJub25lIn0.eyJpc3MiOiJodHRwOi8vd3d3LmZhYnJpa2FtLmNvbSIsImF1ZCI6Imh0" +
                              "dHA6Ly93d3cuY29udG9zby5jb20iLCJyZXNwb25zZV90eXBlIjoiY29kZSIsImNsaWVudF9pZCI6" +
                              "IkZhYnJpa2FtIiwicmVkaXJlY3RfdXJpIjoiaHR0cDovL3d3dy5mYWJyaWthbS5jb20vcGF0aCJ9.",
                ResponseType = OpenIdConnectConstants.ResponseTypes.Code,
                Scope        = OpenIdConnectConstants.Scopes.OpenId
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.RequestNotSupported, response.Error);
            Assert.Equal("The request parameter is not supported.", response.ErrorDescription);
        }
        public async Task ValidateAuthorizationRequest_CodeChallengeRequestWithForbiddenResponseTypeIsRejected(string type)
        {
            // Arrange
            var server = CreateAuthorizationServer();

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(AuthorizationEndpoint, new OpenIdConnectRequest
            {
                ClientId            = "Fabrikam",
                CodeChallenge       = "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
                CodeChallengeMethod = OpenIdConnectConstants.CodeChallengeMethods.Sha256,
                Nonce        = "n-0S6_WzA2Mj",
                RedirectUri  = "http://www.fabrikam.com/path",
                ResponseType = type,
                Scope        = OpenIdConnectConstants.Scopes.OpenId
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, response.Error);
            Assert.Equal("The specified response_type parameter is not allowed when using PKCE.", response.ErrorDescription);
        }
Exemplo n.º 21
0
        public async Task ValidateRevocationRequest_ClientSecretIsRequiredForHybridClients()
        {
            // Arrange
            var application = new OpenIddictApplication();

            var manager = CreateApplicationManager(instance =>
            {
                instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny <CancellationToken>()))
                .ReturnsAsync(application);

                instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny <CancellationToken>()))
                .ReturnsAsync(OpenIddictConstants.ClientTypes.Hybrid);
            });

            var server = CreateAuthorizationServer(builder =>
            {
                builder.Services.AddSingleton(manager);
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(RevocationEndpoint, new OpenIdConnectRequest
            {
                ClientId      = "Fabrikam",
                ClientSecret  = null,
                Token         = "SlAV32hkKG",
                TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.RefreshToken
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.InvalidClient, response.Error);
            Assert.Equal("The 'client_secret' parameter required for this client application is missing.", response.ErrorDescription);

            Mock.Get(manager).Verify(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny <CancellationToken>()), Times.Once());
            Mock.Get(manager).Verify(mock => mock.GetClientTypeAsync(application, It.IsAny <CancellationToken>()), Times.Once());
        }
        public async Task InvokeTokenEndpointAsync_AuthorizationCodeCausesAnErrorWhenPresentersAreMissing()
        {
            // Arrange
            var server = CreateAuthorizationServer(options => {
                options.Provider.OnDeserializeAuthorizationCode = context => {
                    Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.AuthorizationCode);

                    context.Ticket = new AuthenticationTicket(
                        new ClaimsPrincipal(),
                        new AuthenticationProperties(),
                        context.Options.AuthenticationScheme);

                    context.Ticket.SetPresenters(Enumerable.Empty <string>());

                    return(Task.FromResult(0));
                };

                options.Provider.OnValidateTokenRequest = context => {
                    context.Skip();

                    return(Task.FromResult(0));
                };
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest {
                ClientId  = "Fabrikam",
                Code      = "SplxlOBeZQQYbYS6WxSbIA",
                GrantType = OpenIdConnectConstants.GrantTypes.AuthorizationCode
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.ServerError, response.Error);
            Assert.Equal("An internal server error occurred.", response.ErrorDescription);
        }
        public async Task InvokeUserinfoEndpointAsync_BasicClaimsAreCorrectlyReturned()
        {
            // Arrange
            var server = CreateAuthorizationServer(options =>
            {
                options.Provider.OnDeserializeAccessToken = context =>
                {
                    Assert.Equal("SlAV32hkKG", context.AccessToken);

                    var identity = new ClaimsIdentity(OpenIdConnectServerDefaults.AuthenticationScheme);
                    identity.AddClaim(OpenIdConnectConstants.Claims.Subject, "Bob le Magnifique");

                    context.Ticket = new AuthenticationTicket(
                        new ClaimsPrincipal(identity),
                        new AuthenticationProperties(),
                        OpenIdConnectServerDefaults.AuthenticationScheme);

                    context.Ticket.SetPresenters("Fabrikam", "Contoso");

                    return(Task.CompletedTask);
                };
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(UserinfoEndpoint, new OpenIdConnectRequest
            {
                AccessToken = "SlAV32hkKG"
            });

            // Assert
            Assert.Equal(3, response.GetParameters().Count());
            Assert.Equal(server.BaseAddress.AbsoluteUri, (string)response[OpenIdConnectConstants.Claims.Issuer]);
            Assert.Equal("Bob le Magnifique", (string)response[OpenIdConnectConstants.Claims.Subject]);
            Assert.Equal(new[] { "Fabrikam", "Contoso" }, (string[])response[OpenIdConnectConstants.Claims.Audience]);
        }
Exemplo n.º 24
0
        public async Task InvokeUserinfoEndpointAsync_HandleUserinfoRequest_AllowsRejectingRequest(string error, string description, string uri)
        {
            // Arrange
            var server = CreateAuthorizationServer(options =>
            {
                options.Provider.OnDeserializeAccessToken = context =>
                {
                    Assert.Equal("SlAV32hkKG", context.AccessToken);

                    context.Ticket = new AuthenticationTicket(
                        new ClaimsIdentity(context.Options.AuthenticationType),
                        new AuthenticationProperties());

                    return(Task.CompletedTask);
                };

                options.Provider.OnHandleUserinfoRequest = context =>
                {
                    context.Reject(error, description, uri);

                    return(Task.CompletedTask);
                };
            });

            var client = new OpenIdConnectClient(server.HttpClient);

            // Act
            var response = await client.PostAsync(UserinfoEndpoint, new OpenIdConnectRequest
            {
                AccessToken = "SlAV32hkKG"
            });

            // Assert
            Assert.Equal(error ?? OpenIdConnectConstants.Errors.InvalidRequest, response.Error);
            Assert.Equal(description, response.ErrorDescription);
            Assert.Equal(uri, response.ErrorUri);
        }
        public async Task InvokeTokenEndpointAsync_RefreshTokenCausesAnErrorWhenResourceIsInvalid()
        {
            // Arrange
            var server = CreateAuthorizationServer(options => {
                options.Provider.OnDeserializeRefreshToken = context => {
                    Assert.Equal("8xLOxBtZp8", context.RefreshToken);

                    context.Ticket = new AuthenticationTicket(
                        new ClaimsPrincipal(),
                        new AuthenticationProperties(),
                        context.Options.AuthenticationScheme);

                    context.Ticket.SetResources("phone_api", "mail_api");

                    return(Task.FromResult(0));
                };

                options.Provider.OnValidateTokenRequest = context => {
                    context.Skip();

                    return(Task.FromResult(0));
                };
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest {
                GrantType    = OpenIdConnectConstants.GrantTypes.RefreshToken,
                RefreshToken = "8xLOxBtZp8",
                Resource     = "phone_api contact_api"
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.InvalidGrant, response.Error);
            Assert.Equal("Token request doesn't contain a valid resource parameter", response.ErrorDescription);
        }
        public async Task InvokeTokenEndpointAsync_AuthorizationCodeCausesAnErrorWhenCallerIsNotAPresenter()
        {
            // Arrange
            var server = CreateAuthorizationServer(options => {
                options.Provider.OnDeserializeAuthorizationCode = context => {
                    Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.AuthorizationCode);

                    context.Ticket = new AuthenticationTicket(
                        new ClaimsPrincipal(),
                        new AuthenticationProperties(),
                        context.Options.AuthenticationScheme);

                    context.Ticket.SetPresenters("Contoso");

                    return(Task.FromResult(0));
                };

                options.Provider.OnValidateTokenRequest = context => {
                    context.Skip();

                    return(Task.FromResult(0));
                };
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest {
                ClientId  = "Fabrikam",
                Code      = "SplxlOBeZQQYbYS6WxSbIA",
                GrantType = OpenIdConnectConstants.GrantTypes.AuthorizationCode
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.InvalidGrant, response.Error);
            Assert.Equal("Ticket does not contain matching client_id", response.ErrorDescription);
        }
        public async Task ValidateLogoutRequest_RequestIsRejectedWhenApplicationHasNoLogoutPermission()
        {
            // Arrange
            var application = new OpenIddictApplication();

            var manager = CreateApplicationManager(instance =>
            {
                instance.Setup(mock => mock.FindByPostLogoutRedirectUriAsync("http://www.fabrikam.com/path", It.IsAny <CancellationToken>()))
                .ReturnsAsync(ImmutableArray.Create(application));

                instance.Setup(mock => mock.HasPermissionAsync(application,
                                                               OpenIddictConstants.Permissions.Endpoints.Logout, It.IsAny <CancellationToken>()))
                .ReturnsAsync(false);
            });

            var server = CreateAuthorizationServer(builder =>
            {
                builder.Services.AddSingleton(manager);

                builder.Configure(options => options.IgnoreEndpointPermissions = false);
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(LogoutEndpoint, new OpenIdConnectRequest
            {
                PostLogoutRedirectUri = "http://www.fabrikam.com/path"
            });

            // Assert
            Assert.Equal(OpenIddictConstants.Errors.InvalidRequest, response.Error);
            Assert.Equal("The specified 'post_logout_redirect_uri' parameter is not valid.", response.ErrorDescription);

            Mock.Get(manager).Verify(mock => mock.HasPermissionAsync(application,
                                                                     OpenIddictConstants.Permissions.Endpoints.Logout, It.IsAny <CancellationToken>()), Times.Once());
        }
        public async Task ValidateRevocationRequest_ClientSecretCannotBeUsedByPublicClients()
        {
            // Arrange
            var application = new OpenIddictApplication();

            var manager = CreateApplicationManager(instance =>
            {
                instance.Setup(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny <CancellationToken>()))
                .ReturnsAsync(application);

                instance.Setup(mock => mock.GetClientTypeAsync(application, It.IsAny <CancellationToken>()))
                .ReturnsAsync(OpenIddictConstants.ClientTypes.Public);
            });

            var server = CreateAuthorizationServer(builder =>
            {
                builder.Services.AddSingleton(manager);
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(RevocationEndpoint, new OpenIdConnectRequest
            {
                ClientId      = "Fabrikam",
                ClientSecret  = "7Fjfp0ZBr1KtDRbnfVdmIw",
                Token         = "SlAV32hkKG",
                TokenTypeHint = OpenIdConnectConstants.TokenTypeHints.RefreshToken
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.InvalidRequest, response.Error);
            Assert.Equal("Public clients are not allowed to send a client_secret.", response.ErrorDescription);

            Mock.Get(manager).Verify(mock => mock.FindByClientIdAsync("Fabrikam", It.IsAny <CancellationToken>()), Times.Once());
            Mock.Get(manager).Verify(mock => mock.GetClientTypeAsync(application, It.IsAny <CancellationToken>()), Times.Once());
        }
        public async Task InvokeUserinfoEndpointAsync_ProfileClaimsAreCorrectlyReturned()
        {
            // Arrange
            var server = CreateAuthorizationServer(options => {
                options.Provider.OnDeserializeAccessToken = context => {
                    Assert.Equal("SlAV32hkKG", context.AccessToken);

                    var identity = new ClaimsIdentity(context.Options.AuthenticationScheme);
                    identity.AddClaim(ClaimTypes.NameIdentifier, "Bob le Magnifique");
                    identity.AddClaim(ClaimTypes.GivenName, "Bob");
                    identity.AddClaim(ClaimTypes.Surname, "Saint-Clar");
                    identity.AddClaim(ClaimTypes.DateOfBirth, "04/09/1933");

                    context.Ticket = new AuthenticationTicket(
                        new ClaimsPrincipal(identity),
                        new AuthenticationProperties(),
                        context.Options.AuthenticationScheme);

                    context.Ticket.SetPresenters("Fabrikam");
                    context.Ticket.SetScopes(OpenIdConnectConstants.Scopes.Profile);

                    return(Task.FromResult(0));
                };
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(UserinfoEndpoint, new OpenIdConnectRequest {
                AccessToken = "SlAV32hkKG"
            });

            // Assert
            Assert.Equal("Bob", (string)response[OpenIdConnectConstants.Claims.GivenName]);
            Assert.Equal("Saint-Clar", (string)response[OpenIdConnectConstants.Claims.FamilyName]);
            Assert.Equal("04/09/1933", (string)response[OpenIdConnectConstants.Claims.Birthdate]);
        }
        public async Task InvokeTokenEndpointAsync_ExpiredAuthorizationCodeCausesAnError()
        {
            // Arrange
            var server = CreateAuthorizationServer(options => {
                options.Provider.OnDeserializeAuthorizationCode = context => {
                    Assert.Equal("SplxlOBeZQQYbYS6WxSbIA", context.AuthorizationCode);

                    context.Ticket = new AuthenticationTicket(
                        new ClaimsPrincipal(),
                        new AuthenticationProperties(),
                        context.Options.AuthenticationScheme);

                    context.Ticket.Properties.ExpiresUtc = context.Options.SystemClock.UtcNow - TimeSpan.FromDays(1);

                    return(Task.FromResult(0));
                };

                options.Provider.OnValidateTokenRequest = context => {
                    context.Skip();

                    return(Task.FromResult(0));
                };
            });

            var client = new OpenIdConnectClient(server.CreateClient());

            // Act
            var response = await client.PostAsync(TokenEndpoint, new OpenIdConnectRequest {
                ClientId  = "Fabrikam",
                Code      = "SplxlOBeZQQYbYS6WxSbIA",
                GrantType = OpenIdConnectConstants.GrantTypes.AuthorizationCode
            });

            // Assert
            Assert.Equal(OpenIdConnectConstants.Errors.InvalidGrant, response.Error);
            Assert.Equal("Expired ticket", response.ErrorDescription);
        }