public async Task When_Requesting_Token_Via_AuthorizationCode_Grant_Type_Then_Events_Are_Logged() { // ARRANGE InitializeFakeObjects(); const string clientId = "clientId"; const string code = "code"; const string accessToken = "accessToken"; const string identityToken = "identityToken"; var parameter = new AuthorizationCodeGrantTypeParameter { ClientId = clientId, Code = code }; var grantedToken = new GrantedToken { AccessToken = accessToken, IdToken = identityToken }; _getTokenByAuthorizationCodeGrantTypeActionFake.Setup( g => g.Execute(It.IsAny <AuthorizationCodeGrantTypeParameter>(), It.IsAny <AuthenticationHeaderValue>())) .Returns(Task.FromResult(grantedToken)); // ACT await _tokenActions.GetTokenByAuthorizationCodeGrantType(parameter, null); // ASSERTS _simpleIdentityServerEventSourceFake.Verify(s => s.StartGetTokenByAuthorizationCode(clientId, code)); _simpleIdentityServerEventSourceFake.Verify(s => s.EndGetTokenByAuthorizationCode(accessToken, identityToken)); }
/// <summary> /// Check the parameters based on the RFC : http://openid.net/specs/openid-connect-core-1_0.html#TokenRequestValidation /// </summary> /// <param name="authorizationCodeGrantTypeParameter"></param> /// <param name="authenticationHeaderValue"></param> /// <param name="certificate"></param> /// <param name="issuerName"></param> /// <param name="cancellationToken">The <see cref="CancellationToken"/> for the async operation.</param> /// <returns></returns> private async Task <Option <ValidationResult> > ValidateParameter( AuthorizationCodeGrantTypeParameter authorizationCodeGrantTypeParameter, AuthenticationHeaderValue?authenticationHeaderValue, X509Certificate2?certificate, string issuerName, CancellationToken cancellationToken) { if (authorizationCodeGrantTypeParameter.Code == null) { return(new ErrorDetails { Status = HttpStatusCode.BadRequest, Title = ErrorCodes.InvalidGrant, Detail = Strings.TheAuthorizationCodeIsNotCorrect }); } // 1. Authenticate the client var instruction = authenticationHeaderValue.GetAuthenticateInstruction( authorizationCodeGrantTypeParameter, certificate); var authResult = await _authenticateClient.Authenticate(instruction, issuerName, cancellationToken) .ConfigureAwait(false); var client = authResult.Client; if (client == null) { return(new ErrorDetails { Status = HttpStatusCode.BadRequest, Title = ErrorCodes.InvalidClient, Detail = authResult.ErrorMessage ! });
public async Task <GrantedToken> GetTokenByAuthorizationCodeGrantType(AuthorizationCodeGrantTypeParameter authorizationCodeGrantTypeParameter, AuthenticationHeaderValue authenticationHeaderValue, X509Certificate2 certificate = null) { if (authorizationCodeGrantTypeParameter == null) { throw new ArgumentNullException(nameof(authorizationCodeGrantTypeParameter)); } var processId = Guid.NewGuid().ToString(); try { _eventPublisher.Publish(new GrantTokenViaAuthorizationCodeReceived(Guid.NewGuid().ToString(), processId, _payloadSerializer.GetPayload(authorizationCodeGrantTypeParameter, authenticationHeaderValue), authenticationHeaderValue, 0)); _simpleIdentityServerEventSource.StartGetTokenByAuthorizationCode( authorizationCodeGrantTypeParameter.ClientId, authorizationCodeGrantTypeParameter.Code); _authorizationCodeGrantTypeParameterTokenEdpValidator.Validate(authorizationCodeGrantTypeParameter); var result = await _getTokenByAuthorizationCodeGrantTypeAction.Execute(authorizationCodeGrantTypeParameter, authenticationHeaderValue); _simpleIdentityServerEventSource.EndGetTokenByAuthorizationCode( result.AccessToken, result.IdToken); _eventPublisher.Publish(new TokenGranted(Guid.NewGuid().ToString(), processId, _payloadSerializer.GetPayload(result), 1)); return(result); } catch (IdentityServerException ex) { _eventPublisher.Publish(new OpenIdErrorReceived(Guid.NewGuid().ToString(), processId, ex.Code, ex.Message, 1)); throw; } }
public async Task When_Requesting_An_Existed_Granted_Token_Then_Check_Id_Token_Is_Signed_And_Encrypted() { // ARRANGE InitializeFakeObjects(); const string accessToken = "accessToken"; const string identityToken = "identityToken"; const string clientId = "clientId"; var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientSecret = "clientSecret", RedirectUri = "redirectUri", ClientId = clientId }; var result = new AuthenticationResult(new Models.Client { ClientId = "clientId", IdTokenSignedResponseAlg = Jwt.Constants.JwsAlgNames.RS256, IdTokenEncryptedResponseAlg = Jwt.Constants.JweAlgNames.RSA1_5, IdTokenEncryptedResponseEnc = Jwt.Constants.JweEncNames.A128CBC_HS256 }, null); var authorizationCode = new AuthorizationCode { ClientId = clientId, RedirectUri = "redirectUri", CreateDateTime = DateTime.UtcNow }; var grantedToken = new GrantedToken { ClientId = clientId, AccessToken = accessToken, IdToken = identityToken, IdTokenPayLoad = new JwsPayload() }; _clientValidatorFake.Setup(c => c.CheckPkce(It.IsAny <Client>(), It.IsAny <string>(), It.IsAny <AuthorizationCode>())) .Returns(true); _authenticateInstructionGeneratorStub.Setup(a => a.GetAuthenticateInstruction(It.IsAny <AuthenticationHeaderValue>())) .Returns(new AuthenticateInstruction()); _authenticateClientFake.Setup(a => a.AuthenticateAsync(It.IsAny <AuthenticateInstruction>())) .Returns(Task.FromResult(result)); _authorizationCodeRepositoryFake.Setup(a => a.GetAsync(It.IsAny <string>())) .Returns(Task.FromResult(authorizationCode)); _simpleIdentityServerConfiguratorFake.Setup(s => s.GetAuthorizationCodeValidityPeriodInSecondsAsync()) .Returns(Task.FromResult((double)3000)); _clientValidatorFake.Setup(c => c.GetRedirectionUrls(It.IsAny <Models.Client>(), It.IsAny <string>())) .Returns(new[] { "redirectUri" }); _grantedTokenHelperStub.Setup(g => g.GetValidGrantedTokenAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <JwsPayload>(), It.IsAny <JwsPayload>())) .Returns(Task.FromResult(grantedToken)); // ACT await _getTokenByAuthorizationCodeGrantTypeAction.Execute(authorizationCodeGrantTypeParameter, null); // ASSERTS _clientHelper.Verify(j => j.GenerateIdTokenAsync(It.IsAny <Client>(), It.IsAny <JwsPayload>())); }
public async Task When_Client_Doesnt_Support_Grant_Type_Code_Then_Exception_Is_Thrown() { // ARRANGE InitializeFakeObjects(); var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientId = "clientId", ClientSecret = "clientSecret" }; _authenticateInstructionGeneratorStub.Setup(a => a.GetAuthenticateInstruction(It.IsAny <AuthenticationHeaderValue>())) .Returns(new AuthenticateInstruction()); _authenticateClientFake.Setup(a => a.AuthenticateAsync(It.IsAny <AuthenticateInstruction>(), null, It.IsAny <bool>())) .Returns(() => Task.FromResult(new AuthenticationResult(new Client { ClientId = "id" }, null))); // ACT & ASSERTS var exception = await Assert.ThrowsAsync <IdentityServerException>(() => _getTokenByAuthorizationCodeGrantTypeAction.Execute(authorizationCodeGrantTypeParameter, null, null, null)); Assert.True(exception.Code == ErrorCodes.InvalidClient); Assert.True(exception.Message == string.Format(ErrorDescriptions.TheClientDoesntSupportTheGrantType, "id", GrantType.authorization_code)); }
public async Task When_Redirect_Uri_Is_Not_The_Same_Then_Exception_Is_Thrown() { // ARRANGE InitializeFakeObjects(); var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientId = "clientId", ClientSecret = "clientSecret", RedirectUri = "notCorrectRedirectUri" }; var result = new AuthenticationResult(new Core.Common.Models.Client { ClientId = "clientId" }, null); var authorizationCode = new AuthorizationCode { ClientId = "clientId", RedirectUri = "redirectUri" }; _clientValidatorFake.Setup(c => c.CheckPkce(It.IsAny<Client>(), It.IsAny<string>(), It.IsAny<AuthorizationCode>())) .Returns(true); _authenticateInstructionGeneratorStub.Setup(a => a.GetAuthenticateInstruction(It.IsAny<AuthenticationHeaderValue>())) .Returns(new AuthenticateInstruction()); _authenticateClientFake.Setup(a => a.AuthenticateAsync(It.IsAny<AuthenticateInstruction>())) .Returns(Task.FromResult(result)); _authorizationCodeStoreFake.Setup(a => a.GetAuthorizationCode(It.IsAny<string>())) .Returns(Task.FromResult(authorizationCode)); // ACT & ASSERTS var exception = await Assert.ThrowsAsync<IdentityServerException>(() => _getTokenByAuthorizationCodeGrantTypeAction.Execute(authorizationCodeGrantTypeParameter, null)); Assert.True(exception.Code == ErrorCodes.InvalidGrant); Assert.True(exception.Message == ErrorDescriptions.TheRedirectionUrlIsNotTheSame); }
public async Task When_Client_Cannot_Be_Authenticated_Then_Error_Is_Returned() { InitializeFakeObjects(); var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { Code = "abc", ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientId = "clientId", ClientSecret = "clientSecret" }; _clientStore.Setup(x => x.GetById(It.IsAny <string>(), It.IsAny <CancellationToken>())) .ReturnsAsync((Client)null); var result = await _getTokenByAuthorizationCodeGrantTypeAction.Execute( authorizationCodeGrantTypeParameter, null, null, null, CancellationToken.None) .ConfigureAwait(false) as Option <GrantedToken> .Error; Assert.Equal(ErrorCodes.InvalidClient, result !.Details.Title); }
public async Task When_Authorization_Code_Is_Not_Valid_Then_Exception_Is_Thrown() { // ARRANGE InitializeFakeObjects(); var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientId = "clientId", ClientSecret = "clientSecret" }; var client = new AuthenticationResult(new Client(), null); _authenticateInstructionGeneratorStub.Setup(a => a.GetAuthenticateInstruction(It.IsAny <AuthenticationHeaderValue>())) .Returns(new AuthenticateInstruction()); _authenticateClientFake.Setup(a => a.AuthenticateAsync(It.IsAny <AuthenticateInstruction>())) .Returns(() => Task.FromResult(client)); _authorizationCodeRepositoryFake.Setup(a => a.GetAsync(It.IsAny <string>())) .Returns(() => Task.FromResult((AuthorizationCode)null)); // ACT & ASSERTS var exception = await Assert.ThrowsAsync <IdentityServerException>(() => _getTokenByAuthorizationCodeGrantTypeAction.Execute(authorizationCodeGrantTypeParameter, null)); Assert.True(exception.Code == ErrorCodes.InvalidGrant); Assert.True(exception.Message == ErrorDescriptions.TheAuthorizationCodeIsNotCorrect); }
public GrantTokenViaAuthorizationCodeReceived(string id, string processId, AuthorizationCodeGrantTypeParameter parameter, AuthenticationHeaderValue authHeader, int order) { Id = id; ProcessId = processId; Parameter = parameter; Order = order; AuthHeader = authHeader; }
private AuthenticateInstruction CreateAuthenticateInstruction( AuthorizationCodeGrantTypeParameter authorizationCodeGrantTypeParameter, AuthenticationHeaderValue authenticationHeaderValue) { var result = _authenticateInstructionGenerator.GetAuthenticateInstruction(authenticationHeaderValue); result.ClientAssertion = authorizationCodeGrantTypeParameter.ClientAssertion; result.ClientAssertionType = authorizationCodeGrantTypeParameter.ClientAssertionType; result.ClientIdFromHttpRequestBody = authorizationCodeGrantTypeParameter.ClientId; result.ClientSecretFromHttpRequestBody = authorizationCodeGrantTypeParameter.ClientSecret; return(result); }
public void When_Passing_EmptyCode_Then_Exception_Is_Thrown() { // ARRANGE InitializeFakeObject(); var parameter = new AuthorizationCodeGrantTypeParameter(); // ACT & ASSERTS var exception = Assert.Throws <IdentityServerException>(() => _authorizationCodeGrantTypeParameterTokenEdpValidator.Validate(parameter)); Assert.True(exception.Code == ErrorCodes.InvalidRequestCode); Assert.True(exception.Message == string.Format(ErrorDescriptions.MissingParameter, Constants.StandardTokenRequestParameterNames.AuthorizationCodeName)); }
public async Task When_RedirectUri_Is_Different_From_The_One_Hold_By_The_Client_Then_Exception_Is_Thrown() { // ARRANGE InitializeFakeObjects(); var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientSecret = "clientSecret", RedirectUri = "redirectUri", ClientId = "clientId", }; var result = new AuthenticationResult(new Client { ClientId = "clientId", GrantTypes = new System.Collections.Generic.List <GrantType> { GrantType.authorization_code }, ResponseTypes = new System.Collections.Generic.List <ResponseType> { ResponseType.code } }, null); var authorizationCode = new AuthorizationCode { ClientId = "clientId", RedirectUri = "redirectUri", CreateDateTime = DateTime.UtcNow }; _clientValidatorFake.Setup(c => c.CheckPkce(It.IsAny <Client>(), It.IsAny <string>(), It.IsAny <AuthorizationCode>())) .Returns(true); _authorizationCodeStoreFake.Setup(a => a.RemoveAuthorizationCode(It.IsAny <string>())).Returns(Task.FromResult(true)); _authenticateInstructionGeneratorStub.Setup(a => a.GetAuthenticateInstruction(It.IsAny <AuthenticationHeaderValue>())) .Returns(new AuthenticateInstruction()); _authenticateClientFake.Setup(a => a.AuthenticateAsync(It.IsAny <AuthenticateInstruction>(), null, It.IsAny <bool>())) .Returns(Task.FromResult(result)); _authorizationCodeStoreFake.Setup(a => a.GetAuthorizationCode(It.IsAny <string>())) .Returns(Task.FromResult(authorizationCode)); _simpleIdentityServerConfiguratorFake.Setup(s => s.GetAuthorizationCodeValidityPeriodInSecondsAsync()) .Returns(Task.FromResult((double)3000)); _clientValidatorFake.Setup(c => c.GetRedirectionUrls(It.IsAny <Client>(), It.IsAny <string[]>())) .Returns(new string[0]); // ACT & ASSERTS var exception = await Assert.ThrowsAsync <IdentityServerException>(() => _getTokenByAuthorizationCodeGrantTypeAction.Execute(authorizationCodeGrantTypeParameter, null, null, null)); Assert.True(exception.Code == ErrorCodes.InvalidGrant); Assert.True(exception.Message == string.Format(ErrorDescriptions.RedirectUrlIsNotValid, "redirectUri")); }
public async Task When_RedirectUri_Is_Different_From_The_One_Hold_By_The_Client_Then_Error_Is_Returned() { InitializeFakeObjects(TimeSpan.FromSeconds(3000)); var clientId = "clientId"; var clientSecret = "clientSecret"; var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { Code = "abc", ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientSecret = clientSecret, RedirectUri = new Uri("https://redirectUri"), ClientId = clientId, }; var client = new Client { RequirePkce = false, ClientId = clientId, Secrets = new[] { new ClientSecret { Type = ClientSecretTypes.SharedSecret, Value = clientSecret } }, GrantTypes = new[] { GrantTypes.AuthorizationCode }, ResponseTypes = new[] { ResponseTypeNames.Code } }; var authorizationCode = new AuthorizationCode { ClientId = clientId, RedirectUri = new Uri("https://redirectUri"), CreateDateTime = DateTimeOffset.UtcNow }; _clientStore.Setup(x => x.GetById(It.IsAny <string>(), It.IsAny <CancellationToken>())).ReturnsAsync(client); _authorizationCodeStoreFake.Setup(a => a.Remove(It.IsAny <string>(), It.IsAny <CancellationToken>())).ReturnsAsync(true); _authorizationCodeStoreFake.Setup(a => a.Get(It.IsAny <string>(), It.IsAny <CancellationToken>())) .ReturnsAsync(authorizationCode); var authenticationHeader = new AuthenticationHeaderValue( "Basic", $"{clientId}:{clientSecret}".Base64Encode()); var result = await _getTokenByAuthorizationCodeGrantTypeAction.Execute( authorizationCodeGrantTypeParameter, authenticationHeader, null, null, CancellationToken.None) .ConfigureAwait(false) as Option <GrantedToken> .Error; Assert.Equal(ErrorCodes.InvalidRedirectUri, result.Details.Title); Assert.Equal( string.Format(Strings.RedirectUrlIsNotValid, "https://redirecturi/"), result.Details.Detail); }
public async Task When_Granted_Client_Is_Not_The_Same_Then_Error_Is_Returned() { InitializeFakeObjects(); var clientSecret = "clientSecret"; var clientId = "notCorrectClientId"; var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { Code = "abc", ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientId = clientId, ClientSecret = clientSecret }; var client = new Client { RequirePkce = false, ClientId = clientId, Secrets = new[] { new ClientSecret { Type = ClientSecretTypes.SharedSecret, Value = clientSecret } }, GrantTypes = new[] { GrantTypes.AuthorizationCode }, ResponseTypes = new[] { ResponseTypeNames.Code } }; var authorizationCode = new AuthorizationCode { ClientId = "clientId" }; _clientStore.Setup(x => x.GetById(It.IsAny <string>(), It.IsAny <CancellationToken>())).ReturnsAsync(client); _authorizationCodeStoreFake.Setup(a => a.Get(It.IsAny <string>(), It.IsAny <CancellationToken>())) .Returns(() => Task.FromResult(authorizationCode)); var authenticationHeader = new AuthenticationHeaderValue( "Basic", $"{clientId}:{clientSecret}".Base64Encode()); var result = await _getTokenByAuthorizationCodeGrantTypeAction.Execute( authorizationCodeGrantTypeParameter, authenticationHeader, null, null, CancellationToken.None) .ConfigureAwait(false) as Option <GrantedToken> .Error; Assert.Equal(ErrorCodes.InvalidRequest, result.Details.Title); Assert.Equal( string.Format( Strings.TheAuthorizationCodeHasNotBeenIssuedForTheGivenClientId, "clientId"), result.Details.Detail); }
public async Task When_The_Authorization_Code_Has_Expired_Then_Exception_Is_Thrown() { // ARRANGE InitializeFakeObjects(); var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientSecret = "clientSecret", RedirectUri = "redirectUri", ClientId = "clientId", }; var result = new AuthenticationResult(new Core.Common.Models.Client { ClientId = "clientId", GrantTypes = new System.Collections.Generic.List <GrantType> { GrantType.authorization_code }, ResponseTypes = new System.Collections.Generic.List <ResponseType> { ResponseType.code } }, null); var authorizationCode = new AuthorizationCode { ClientId = "clientId", RedirectUri = "redirectUri", CreateDateTime = DateTime.UtcNow.AddSeconds(-30) }; _clientValidatorFake.Setup(c => c.CheckPkce(It.IsAny <Core.Common.Models.Client>(), It.IsAny <string>(), It.IsAny <AuthorizationCode>())) .Returns(true); _authenticateInstructionGeneratorStub.Setup(a => a.GetAuthenticateInstruction(It.IsAny <AuthenticationHeaderValue>())) .Returns(new AuthenticateInstruction()); _authenticateClientFake.Setup(a => a.AuthenticateAsync(It.IsAny <AuthenticateInstruction>(), null)) .Returns(Task.FromResult(result)); _authorizationCodeStoreFake.Setup(a => a.GetAuthorizationCode(It.IsAny <string>())) .Returns(Task.FromResult(authorizationCode)); _simpleIdentityServerConfiguratorFake.Setup(s => s.GetAuthorizationCodeValidityPeriodInSecondsAsync()) .Returns(Task.FromResult((double)2)); // ACT & ASSERTS var exception = await Assert.ThrowsAsync <IdentityServerException>(() => _getTokenByAuthorizationCodeGrantTypeAction.Execute(authorizationCodeGrantTypeParameter, null, null, null)); Assert.True(exception.Code == ErrorCodes.InvalidGrant); Assert.True(exception.Message == ErrorDescriptions.TheAuthorizationCodeIsObsolete); }
public async Task When_The_Authorization_Code_Has_Expired_Then_Exception_Is_Thrown() { InitializeFakeObjects(TimeSpan.FromSeconds(2)); var clientId = "clientId"; var clientSecret = "clientSecret"; var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { Code = "abc", ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientSecret = clientSecret, RedirectUri = new Uri("https://redirectUri"), ClientId = clientId, }; var client = new Client { RequirePkce = false, ClientId = clientId, Secrets = new[] { new ClientSecret { Type = ClientSecretTypes.SharedSecret, Value = clientSecret } }, GrantTypes = new[] { GrantTypes.AuthorizationCode }, ResponseTypes = new[] { ResponseTypeNames.Code } }; var authorizationCode = new AuthorizationCode { ClientId = clientId, RedirectUri = new Uri("https://redirectUri"), CreateDateTime = DateTimeOffset.UtcNow.AddSeconds(-30) }; _clientStore.Setup(x => x.GetById(It.IsAny <string>(), It.IsAny <CancellationToken>())).ReturnsAsync(client); _authorizationCodeStoreFake.Setup(a => a.Get(It.IsAny <string>(), It.IsAny <CancellationToken>())) .ReturnsAsync(authorizationCode); var authenticationHeader = new AuthenticationHeaderValue( "Basic", $"{clientId}:{clientSecret}".Base64Encode()); var result = await _getTokenByAuthorizationCodeGrantTypeAction.Execute( authorizationCodeGrantTypeParameter, authenticationHeader, null, null, CancellationToken.None) .ConfigureAwait(false) as Option <GrantedToken> .Error; Assert.Equal(ErrorCodes.ExpiredAuthorizationCode, result.Details.Title); Assert.Equal(Strings.TheAuthorizationCodeIsObsolete, result.Details.Detail); }
public void When_Passing_Invalid_RedirectUri_Then_Exception_Is_Thrown() { // ARRANGE InitializeFakeObject(); var parameter = new AuthorizationCodeGrantTypeParameter { Code = "code", RedirectUri = "redirectUri" }; // ACT & ASSERTS var exception = Assert.Throws <IdentityServerException>(() => _authorizationCodeGrantTypeParameterTokenEdpValidator.Validate(parameter)); Assert.True(exception.Code == ErrorCodes.InvalidRequestCode); Assert.True(exception.Message == ErrorDescriptions.TheRedirectionUriIsNotWellFormed); }
public async Task When_Granted_Client_Is_Not_The_Same_Then_Exception_Is_Thrown() { // ARRANGE InitializeFakeObjects(); var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientId = "notCorrectClientId", ClientSecret = "clientSecret" }; var result = new AuthenticationResult(new Client { ClientId = "notCorrectClientId", GrantTypes = new System.Collections.Generic.List <GrantType> { GrantType.authorization_code }, ResponseTypes = new System.Collections.Generic.List <ResponseType> { ResponseType.code } }, null); var authorizationCode = new AuthorizationCode { ClientId = "clientId" }; _clientValidatorFake.Setup(c => c.CheckPkce(It.IsAny <Client>(), It.IsAny <string>(), It.IsAny <AuthorizationCode>())) .Returns(true); _authenticateInstructionGeneratorStub.Setup(a => a.GetAuthenticateInstruction(It.IsAny <AuthenticationHeaderValue>())) .Returns(new AuthenticateInstruction()); _authenticateClientFake.Setup(a => a.AuthenticateAsync(It.IsAny <AuthenticateInstruction>(), null, It.IsAny <bool>())) .Returns(() => Task.FromResult(result)); _authorizationCodeStoreFake.Setup(a => a.GetAuthorizationCode(It.IsAny <string>())) .Returns(() => Task.FromResult(authorizationCode)); // ACT & ASSERTS var exception = await Assert.ThrowsAsync <IdentityServerException>(() => _getTokenByAuthorizationCodeGrantTypeAction.Execute(authorizationCodeGrantTypeParameter, null, null, null)); Assert.True(exception.Code == ErrorCodes.InvalidGrant); Assert.True(exception.Message == string.Format(ErrorDescriptions.TheAuthorizationCodeHasNotBeenIssuedForTheGivenClientId, authorizationCodeGrantTypeParameter.ClientId)); }
public async Task <GrantedToken> Execute( AuthorizationCodeGrantTypeParameter authorizationCodeGrantTypeParameter, AuthenticationHeaderValue authenticationHeaderValue) { if (authorizationCodeGrantTypeParameter == null) { throw new ArgumentNullException(nameof(authorizationCodeGrantTypeParameter)); } var result = await ValidateParameter( authorizationCodeGrantTypeParameter, authenticationHeaderValue); // Invalidate the authorization code by removing it ! await _authorizationCodeRepository.RemoveAsync(result.Code.Code); var grantedToken = await _grantedTokenHelper.GetValidGrantedTokenAsync( result.Code.Scopes, result.Code.ClientId, result.Code.IdTokenPayload, result.Code.UserInfoPayLoad); if (grantedToken == null) { grantedToken = await _grantedTokenGeneratorHelper.GenerateTokenAsync( result.Code.ClientId, result.Code.Scopes, result.Code.UserInfoPayLoad, result.Code.IdTokenPayload); await _grantedTokenRepository.InsertAsync(grantedToken); _simpleIdentityServerEventSource.GrantAccessToClient( result.Code.ClientId, grantedToken.AccessToken, grantedToken.IdToken); } // Fill-in the id-token if (grantedToken.IdTokenPayLoad != null) { grantedToken.IdToken = await _clientHelper.GenerateIdTokenAsync(result.Client, grantedToken.IdTokenPayLoad); } return(grantedToken); }
public async Task When_Client_Does_Not_Support_ResponseType_Code_Then_Error_Is_Returned() { InitializeFakeObjects(); var clientId = "clientId"; var clientSecret = "clientSecret"; var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { Code = "abc", ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientId = clientId, ClientSecret = clientSecret }; var client = new Client { ResponseTypes = Array.Empty <string>(), ClientId = clientId, Secrets = new[] { new ClientSecret { Type = ClientSecretTypes.SharedSecret, Value = clientSecret } }, GrantTypes = new[] { GrantTypes.AuthorizationCode } }; _clientStore.Setup(x => x.GetById(It.IsAny <string>(), It.IsAny <CancellationToken>())).ReturnsAsync(client); var authenticationValue = new AuthenticationHeaderValue( "Basic", $"{clientId}:{clientSecret}".Base64Encode()); var result = await _getTokenByAuthorizationCodeGrantTypeAction.Execute( authorizationCodeGrantTypeParameter, authenticationValue, null, null, CancellationToken.None) .ConfigureAwait(false) as Option <GrantedToken> .Error; Assert.Equal(ErrorCodes.InvalidResponse, result.Details.Title); Assert.Equal( string.Format( Strings.TheClientDoesntSupportTheResponseType, clientId, ResponseTypeNames.Code), result.Details.Detail); }
public async Task When_Pkce_Validation_Failed_Then_Exception_Is_Thrown() { // ARRANGE InitializeFakeObjects(); var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientId = "clientId", ClientSecret = "clientSecret" }; var authorizationCode = new AuthorizationCode { ClientId = "clientId" }; var client = new AuthenticationResult(new Core.Common.Models.Client { ClientId = "id", GrantTypes = new System.Collections.Generic.List <GrantType> { GrantType.authorization_code }, ResponseTypes = new System.Collections.Generic.List <ResponseType> { ResponseType.code } }, null); _authenticateInstructionGeneratorStub.Setup(a => a.GetAuthenticateInstruction(It.IsAny <AuthenticationHeaderValue>())) .Returns(new AuthenticateInstruction()); _authenticateClientFake.Setup(a => a.AuthenticateAsync(It.IsAny <AuthenticateInstruction>(), null)) .Returns(() => Task.FromResult(client)); _authorizationCodeStoreFake.Setup(a => a.GetAuthorizationCode(It.IsAny <string>())) .Returns(() => Task.FromResult(authorizationCode)); _clientValidatorFake.Setup(c => c.CheckPkce(It.IsAny <Core.Common.Models.Client>(), It.IsAny <string>(), It.IsAny <AuthorizationCode>())) .Returns(false); // ACT & ASSERTS var exception = await Assert.ThrowsAsync <IdentityServerException>(() => _getTokenByAuthorizationCodeGrantTypeAction.Execute(authorizationCodeGrantTypeParameter, null, null, null)); Assert.True(exception.Code == ErrorCodes.InvalidGrant); Assert.True(exception.Message == ErrorDescriptions.TheCodeVerifierIsNotCorrect); }
public void Validate(AuthorizationCodeGrantTypeParameter parameter) { if (string.IsNullOrWhiteSpace(parameter.Code)) { throw new IdentityServerException( ErrorCodes.InvalidRequestCode, string.Format(ErrorDescriptions.MissingParameter, Constants.StandardTokenRequestParameterNames.AuthorizationCodeName)); } // With this instruction // The redirect_uri is considered well-formed according to the RFC-3986 var redirectUrlIsCorrect = Uri.IsWellFormedUriString(parameter.RedirectUri, UriKind.Absolute); if (!redirectUrlIsCorrect) { throw new IdentityServerException( ErrorCodes.InvalidRequestCode, ErrorDescriptions.TheRedirectionUriIsNotWellFormed); } }
public async Task <Option <GrantedToken> > GetTokenByAuthorizationCodeGrantType( AuthorizationCodeGrantTypeParameter authorizationCodeGrantTypeParameter, AuthenticationHeaderValue?authenticationHeaderValue, X509Certificate2?certificate, string issuerName, CancellationToken cancellationToken) { var validation = Validate(authorizationCodeGrantTypeParameter); if (validation is Option.Error e) { return(e.Details); } return(await _getTokenByAuthorizationCodeGrantTypeAction.Execute( authorizationCodeGrantTypeParameter, authenticationHeaderValue, certificate, issuerName, cancellationToken).ConfigureAwait(false)); }
public async Task When_Client_Cannot_Be_Authenticated_Then_Exception_Is_Thrown() { // ARRANGE InitializeFakeObjects(); var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientId = "clientId", ClientSecret = "clientSecret" }; _authenticateInstructionGeneratorStub.Setup(a => a.GetAuthenticateInstruction(It.IsAny<AuthenticationHeaderValue>())) .Returns(new AuthenticateInstruction()); _authenticateClientFake.Setup(a => a.AuthenticateAsync(It.IsAny<AuthenticateInstruction>())) .Returns(() => Task.FromResult(new AuthenticationResult(null, null))); // ACT & ASSERTS var exception = await Assert.ThrowsAsync<IdentityServerException>(() => _getTokenByAuthorizationCodeGrantTypeAction.Execute(authorizationCodeGrantTypeParameter, null)); Assert.True(exception.Code == ErrorCodes.InvalidClient); }
public async Task <GrantedToken> Execute(AuthorizationCodeGrantTypeParameter authorizationCodeGrantTypeParameter, AuthenticationHeaderValue authenticationHeaderValue, X509Certificate2 certificate, string issuerName) { if (authorizationCodeGrantTypeParameter == null) { throw new ArgumentNullException(nameof(authorizationCodeGrantTypeParameter)); } var result = await ValidateParameter(authorizationCodeGrantTypeParameter, authenticationHeaderValue, certificate, issuerName).ConfigureAwait(false); await _authorizationCodeStore.RemoveAuthorizationCode(result.AuthCode.Code); // 1. Invalidate the authorization code by removing it ! var grantedToken = await _grantedTokenHelper.GetValidGrantedTokenAsync( result.AuthCode.Scopes, result.AuthCode.ClientId, result.AuthCode.IdTokenPayload, result.AuthCode.UserInfoPayLoad).ConfigureAwait(false); if (grantedToken == null) { grantedToken = await _grantedTokenGeneratorHelper.GenerateTokenAsync(result.Client, result.AuthCode.Scopes, issuerName, result.AuthCode.UserInfoPayLoad, result.AuthCode.IdTokenPayload).ConfigureAwait(false); _oauthEventSource.GrantAccessToClient( result.AuthCode.ClientId, grantedToken.AccessToken, grantedToken.IdToken); // Fill-in the id-token if (grantedToken.IdTokenPayLoad != null) { await _jwtGenerator.UpdatePayloadDate(grantedToken.IdTokenPayLoad).ConfigureAwait(false); grantedToken.IdToken = await _clientHelper.GenerateIdTokenAsync(result.Client, grantedToken.IdTokenPayLoad).ConfigureAwait(false); } await _tokenStore.AddToken(grantedToken).ConfigureAwait(false); } return(grantedToken); }
public string GetPayload(AuthorizationCodeGrantTypeParameter parameter, AuthenticationHeaderValue authenticationHeaderValue) { if (parameter == null) { throw new ArgumentNullException(nameof(parameter)); } var clientId = GetClientId(authenticationHeaderValue); if (string.IsNullOrWhiteSpace(clientId)) { clientId = parameter.ClientId; } var result = new Payload { ClientId = clientId, Authorization = BuildAuthHeader(authenticationHeaderValue), Content = parameter }; return(JsonConvert.SerializeObject(result)); }
public async Task When_Requesting_An_Existed_Granted_Token_Then_Check_Id_Token_Is_Signed_And_Encrypted() { InitializeFakeObjects(TimeSpan.FromSeconds(3000)); var handler = new JwtSecurityTokenHandler(); var accessToken = handler.CreateEncodedJwt( "test", "test", new ClaimsIdentity(), null, null, DateTime.Now, await _inMemoryJwksRepository.GetDefaultSigningKey().ConfigureAwait(false)); const string identityToken = "identityToken"; const string clientId = "clientId"; var clientSecret = "clientSecret"; var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientSecret = clientSecret, RedirectUri = new Uri("https://redirectUri"), ClientId = clientId }; var client = new Client { AllowedScopes = new[] { "scope" }, RedirectionUrls = new[] { new Uri("https://redirectUri") }, ClientId = clientId, Secrets = new[] { new ClientSecret { Type = ClientSecretTypes.SharedSecret, Value = clientSecret } }, GrantTypes = new[] { GrantTypes.AuthorizationCode }, ResponseTypes = new[] { ResponseTypeNames.Code }, IdTokenSignedResponseAlg = SecurityAlgorithms.RsaSha256, IdTokenEncryptedResponseAlg = SecurityAlgorithms.RsaPKCS1, IdTokenEncryptedResponseEnc = SecurityAlgorithms.Aes128CbcHmacSha256 }; var authorizationCode = new AuthorizationCode { ClientId = clientId, RedirectUri = new Uri("https://redirectUri"), CreateDateTime = DateTimeOffset.UtcNow, Scopes = "scope" }; var grantedToken = new GrantedToken { ClientId = clientId, AccessToken = accessToken, IdToken = identityToken, IdTokenPayLoad = new JwtPayload(), CreateDateTime = DateTimeOffset.UtcNow, ExpiresIn = 100000 }; _clientStore.Setup(x => x.GetById(It.IsAny <string>(), It.IsAny <CancellationToken>())).ReturnsAsync(client); _authorizationCodeStoreFake.Setup(a => a.Get(It.IsAny <string>(), It.IsAny <CancellationToken>())) .ReturnsAsync(authorizationCode); _tokenStoreFake .Setup( x => x.GetToken( It.IsAny <string>(), It.IsAny <string>(), It.IsAny <JwtPayload>(), It.IsAny <JwtPayload>(), It.IsAny <CancellationToken>())) .ReturnsAsync(grantedToken); var authenticationHeader = new AuthenticationHeaderValue( "Basic", $"{clientId}:{clientSecret}".Base64Encode()); var r = await _getTokenByAuthorizationCodeGrantTypeAction.Execute( authorizationCodeGrantTypeParameter, authenticationHeader, null, null, CancellationToken.None) .ConfigureAwait(false); Assert.NotNull(r); }
public async Task When_Requesting_Token_And_There_Is_No_Valid_Granted_Token_Then_Grant_A_New_One() { InitializeFakeObjects(); const string clientId = "clientId"; var clientSecret = "clientSecret"; var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { Code = "abc", ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientSecret = clientSecret, RedirectUri = new Uri("https://redirectUri"), ClientId = clientId }; var client = new Client { RequirePkce = false, ClientName = clientId, RedirectionUrls = new[] { new Uri("https://redirectUri") }, ClientId = clientId, Secrets = new[] { new ClientSecret { Type = ClientSecretTypes.SharedSecret, Value = clientSecret } }, GrantTypes = new[] { GrantTypes.AuthorizationCode }, ResponseTypes = new[] { ResponseTypeNames.Code }, JsonWebKeys = "supersecretlongkey".CreateJwk(JsonWebKeyUseNames.Sig, KeyOperations.Sign, KeyOperations.Verify) .ToSet(), IdTokenSignedResponseAlg = SecurityAlgorithms.RsaSha256 }; var authorizationCode = new AuthorizationCode { Scopes = "scope", ClientId = clientId, RedirectUri = new Uri("https://redirectUri"), CreateDateTime = DateTimeOffset.UtcNow }; _clientStore.Setup(x => x.GetById(It.IsAny <string>(), It.IsAny <CancellationToken>())).ReturnsAsync(client); _authorizationCodeStoreFake.Setup(a => a.Get(It.IsAny <string>(), It.IsAny <CancellationToken>())) .ReturnsAsync(authorizationCode); _simpleAuthOptions = new RuntimeSettings(authorizationCodeValidityPeriod: TimeSpan.FromSeconds(3000)); _tokenStoreFake.Setup( x => x.GetToken( It.IsAny <string>(), It.IsAny <string>(), It.IsAny <JwtPayload>(), It.IsAny <JwtPayload>(), It.IsAny <CancellationToken>())) .ReturnsAsync((GrantedToken)null); var authenticationHeader = new AuthenticationHeaderValue( "Basic", $"{clientId}:{clientSecret}".Base64Encode()); var result = await _getTokenByAuthorizationCodeGrantTypeAction.Execute( authorizationCodeGrantTypeParameter, authenticationHeader, null, null, CancellationToken.None) .ConfigureAwait(false); _tokenStoreFake.Verify(g => g.AddToken(It.IsAny <GrantedToken>(), It.IsAny <CancellationToken>())); _eventPublisher.Verify(s => s.Publish(It.IsAny <TokenGranted>())); }
/// <summary> /// Check the parameters based on the RFC : http://openid.net/specs/openid-connect-core-1_0.html#TokenRequestValidation /// </summary> /// <param name="authorizationCodeGrantTypeParameter"></param> /// <param name="authenticationHeaderValue"></param> /// <returns></returns> private async Task <ValidationResult> ValidateParameter( AuthorizationCodeGrantTypeParameter authorizationCodeGrantTypeParameter, AuthenticationHeaderValue authenticationHeaderValue) { // 1. Authenticate the client var instruction = CreateAuthenticateInstruction(authorizationCodeGrantTypeParameter, authenticationHeaderValue); var authResult = await _authenticateClient.AuthenticateAsync(instruction); var client = authResult.Client; if (client == null) { throw new IdentityServerException(ErrorCodes.InvalidClient, authResult.ErrorMessage); } var authorizationCode = await _authorizationCodeRepository.GetAsync(authorizationCodeGrantTypeParameter.Code); // 2. Check if the authorization code is valid if (authorizationCode == null) { throw new IdentityServerException(ErrorCodes.InvalidGrant, ErrorDescriptions.TheAuthorizationCodeIsNotCorrect); } // 3. Check PKCE if (!_clientValidator.CheckPkce(client, authorizationCodeGrantTypeParameter.CodeVerifier, authorizationCode)) { throw new IdentityServerException(ErrorCodes.InvalidGrant, ErrorDescriptions.TheCodeVerifierIsNotCorrect); } // 4. Ensure the authorization code was issued to the authenticated client. var authorizationClientId = authorizationCode.ClientId; if (authorizationClientId != client.ClientId) { throw new IdentityServerException(ErrorCodes.InvalidGrant, string.Format(ErrorDescriptions.TheAuthorizationCodeHasNotBeenIssuedForTheGivenClientId, client.ClientId)); } if (authorizationCode.RedirectUri != authorizationCodeGrantTypeParameter.RedirectUri) { throw new IdentityServerException(ErrorCodes.InvalidGrant, ErrorDescriptions.TheRedirectionUrlIsNotTheSame); } // 5. Ensure the authorization code is still valid. var authCodeValidity = await _configurationService.GetAuthorizationCodeValidityPeriodInSecondsAsync(); var expirationDateTime = authorizationCode.CreateDateTime.AddSeconds(authCodeValidity); var currentDateTime = DateTime.UtcNow; if (currentDateTime > expirationDateTime) { throw new IdentityServerException(ErrorCodes.InvalidGrant, ErrorDescriptions.TheAuthorizationCodeIsObsolete); } // Ensure that the redirect_uri parameter value is identical to the redirect_uri parameter value. var redirectionUrl = _clientValidator.GetRedirectionUrls(client, authorizationCodeGrantTypeParameter.RedirectUri); if (!redirectionUrl.Any()) { throw new IdentityServerException( ErrorCodes.InvalidGrant, string.Format(ErrorDescriptions.RedirectUrlIsNotValid, authorizationCodeGrantTypeParameter.RedirectUri)); } return(new ValidationResult { Client = client, Code = authorizationCode }); }
public async Task When_Requesting_Token_And_There_Is_No_Valid_Granted_Token_Then_Grant_A_New_One() { // ARRANGE InitializeFakeObjects(); const string accessToken = "accessToken"; const string identityToken = "identityToken"; const string clientId = "clientId"; var authorizationCodeGrantTypeParameter = new AuthorizationCodeGrantTypeParameter { ClientAssertion = "clientAssertion", ClientAssertionType = "clientAssertionType", ClientSecret = "clientSecret", RedirectUri = "redirectUri", ClientId = clientId }; var authResult = new AuthenticationResult(new Models.Client { ClientId = clientId }, null); var authorizationCode = new AuthorizationCode { ClientId = clientId, RedirectUri = "redirectUri", CreateDateTime = DateTime.UtcNow }; var grantedToken = new GrantedToken { AccessToken = accessToken, IdToken = identityToken }; _clientValidatorFake.Setup(c => c.CheckPkce(It.IsAny <Client>(), It.IsAny <string>(), It.IsAny <AuthorizationCode>())) .Returns(true); _authenticateInstructionGeneratorStub.Setup(a => a.GetAuthenticateInstruction(It.IsAny <AuthenticationHeaderValue>())) .Returns(new AuthenticateInstruction()); _authenticateClientFake.Setup(a => a.AuthenticateAsync(It.IsAny <AuthenticateInstruction>())) .Returns(Task.FromResult(authResult)); _authorizationCodeRepositoryFake.Setup(a => a.GetAsync(It.IsAny <string>())) .Returns(Task.FromResult(authorizationCode)); _simpleIdentityServerConfiguratorFake.Setup(s => s.GetAuthorizationCodeValidityPeriodInSecondsAsync()) .Returns(Task.FromResult((double)3000)); _clientValidatorFake.Setup(c => c.GetRedirectionUrls(It.IsAny <Models.Client>(), It.IsAny <string>())) .Returns(new[] { "redirectUri" }); _grantedTokenHelperStub.Setup(g => g.GetValidGrantedTokenAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <JwsPayload>(), It.IsAny <JwsPayload>())) .Returns(() => Task.FromResult((GrantedToken)null)); _grantedTokenGeneratorHelperFake.Setup(g => g.GenerateTokenAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <JwsPayload>(), It.IsAny <JwsPayload>())) .Returns(Task.FromResult(grantedToken));; // ACT var result = await _getTokenByAuthorizationCodeGrantTypeAction.Execute(authorizationCodeGrantTypeParameter, null); // ASSERTS _grantedTokenRepositoryFake.Verify(g => g.InsertAsync(grantedToken)); _simpleIdentityServerEventSourceFake.Verify(s => s.GrantAccessToClient( clientId, accessToken, identityToken)); Assert.True(result.AccessToken == accessToken); }