public async Task When_Passing_No_Authentication_Instruction_Then_Exception_Is_Thrown() { // ARRANGE InitializeFakeObjects(); // ACT & ASSERT await Assert.ThrowsAsync <ArgumentNullException>(() => _authenticateClient.AuthenticateAsync(null)); }
public async Task <GrantedToken> Execute(RefreshTokenGrantTypeParameter refreshTokenGrantTypeParameter, AuthenticationHeaderValue authenticationHeaderValue, X509Certificate2 certificate, string issuerName) { if (refreshTokenGrantTypeParameter == null) { throw new ArgumentNullException(nameof(refreshTokenGrantTypeParameter)); } // 1. Try to authenticate the client var instruction = CreateAuthenticateInstruction(refreshTokenGrantTypeParameter, authenticationHeaderValue, certificate); var authResult = await _authenticateClient.AuthenticateAsync(instruction, issuerName); var client = authResult.Client; if (authResult.Client == null) { _oauthEventSource.Info(authResult.ErrorMessage); throw new IdentityServerException(ErrorCodes.InvalidClient, authResult.ErrorMessage); } // 2. Check client if (client.GrantTypes == null || !client.GrantTypes.Contains(GrantType.refresh_token)) { throw new IdentityServerException(ErrorCodes.InvalidClient, string.Format(ErrorDescriptions.TheClientDoesntSupportTheGrantType, client.ClientId, GrantType.refresh_token)); } // 3. Validate parameters var grantedToken = await ValidateParameter(refreshTokenGrantTypeParameter); if (grantedToken.ClientId != client.ClientId) { throw new IdentityServerException(ErrorCodes.InvalidGrant, ErrorDescriptions.TheRefreshTokenCanBeUsedOnlyByTheSameIssuer); } // 4. Generate a new access token & insert it var generatedToken = await _grantedTokenGeneratorHelper.GenerateTokenAsync( grantedToken.ClientId, grantedToken.Scope, issuerName, grantedToken.UserInfoPayLoad, grantedToken.IdTokenPayLoad); generatedToken.ParentTokenId = grantedToken.Id; // 5. Fill-in the idtoken if (generatedToken.IdTokenPayLoad != null) { await _jwtGenerator.UpdatePayloadDate(generatedToken.IdTokenPayLoad); generatedToken.IdToken = await _clientHelper.GenerateIdTokenAsync(generatedToken.ClientId, generatedToken.IdTokenPayLoad); } await _tokenStore.AddToken(generatedToken); _oauthEventSource.GrantAccessToClient(generatedToken.ClientId, generatedToken.AccessToken, generatedToken.Scope); return(generatedToken); }
public async Task <bool> Execute(RevokeTokenParameter revokeTokenParameter, AuthenticationHeaderValue authenticationHeaderValue, X509Certificate2 certificate, string issuerName) { if (revokeTokenParameter == null) { throw new ArgumentNullException(nameof(revokeTokenParameter)); } if (string.IsNullOrWhiteSpace(revokeTokenParameter.Token)) { throw new ArgumentNullException(nameof(revokeTokenParameter.Token)); } // 1. Check the client credentials var errorMessage = string.Empty; var instruction = CreateAuthenticateInstruction(revokeTokenParameter, authenticationHeaderValue, certificate); var authResult = await _authenticateClient.AuthenticateAsync(instruction, issuerName); var client = authResult.Client; if (client == null) { throw new IdentityServerException(ErrorCodes.InvalidClient, authResult.ErrorMessage); } // 2. Retrieve the granted token & check if it exists GrantedToken grantedToken = await _tokenStore.GetAccessToken(revokeTokenParameter.Token); bool isAccessToken = true; if (grantedToken == null) { grantedToken = await _tokenStore.GetRefreshToken(revokeTokenParameter.Token); isAccessToken = false; } if (grantedToken == null) { throw new IdentityServerException(ErrorCodes.InvalidToken, ErrorDescriptions.TheTokenDoesntExist); } // 3. Verifies whether the token was issued to the client making the revocation request if (grantedToken.ClientId != client.ClientId) { throw new IdentityServerException(ErrorCodes.InvalidToken, string.Format(ErrorDescriptions.TheTokenHasNotBeenIssuedForTheGivenClientId, client.ClientId)); } // 4. Invalid the granted token if (isAccessToken) { return(await _tokenStore.RemoveAccessToken(grantedToken.AccessToken)); } return(await _tokenStore.RemoveRefreshToken(grantedToken.RefreshToken)); }
public async Task <bool> Execute(RevokeTokenParameter revokeTokenParameter, AuthenticationHeaderValue authenticationHeaderValue) { if (revokeTokenParameter == null) { throw new ArgumentNullException(nameof(revokeTokenParameter)); } if (string.IsNullOrWhiteSpace(revokeTokenParameter.Token)) { throw new ArgumentNullException(nameof(revokeTokenParameter.Token)); } // 1. Check the client credentials var errorMessage = string.Empty; var instruction = CreateAuthenticateInstruction(revokeTokenParameter, authenticationHeaderValue); var authResult = await _authenticateClient.AuthenticateAsync(instruction); var client = authResult.Client; if (client == null) { client = await _clientRepository.GetClientByIdAsync(Constants.AnonymousClientId); if (client == null) { throw new IdentityServerException(ErrorCodes.InternalError, string.Format(ErrorDescriptions.ClientIsNotValid, Constants.AnonymousClientId)); } } // 2. Retrieve the granted token & check if it exists GrantedToken grantedToken = await _grantedTokenRepository.GetTokenAsync(revokeTokenParameter.Token); if (grantedToken == null) { grantedToken = await _grantedTokenRepository.GetTokenByRefreshTokenAsync(revokeTokenParameter.Token); } if (grantedToken == null) { return(false); } // 3. Verifies whether the token was issued to the client making the revocation request if (grantedToken.ClientId != client.ClientId) { throw new IdentityServerException(ErrorCodes.InvalidToken, string.Format(ErrorDescriptions.TheTokenHasNotBeenIssuedForTheGivenClientId, client.ClientId)); } // 4. Invalid the granted token return(await _grantedTokenRepository.DeleteAsync(grantedToken)); }
/// <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 <GrantedToken> Execute(ClientCredentialsGrantTypeParameter clientCredentialsGrantTypeParameter, AuthenticationHeaderValue authenticationHeaderValue, X509Certificate2 certificate, string issuerName) { if (clientCredentialsGrantTypeParameter == null) { throw new ArgumentNullException(nameof(clientCredentialsGrantTypeParameter)); } _clientCredentialsGrantTypeParameterValidator.Validate(clientCredentialsGrantTypeParameter); // 1. Authenticate the client var instruction = CreateAuthenticateInstruction(clientCredentialsGrantTypeParameter, authenticationHeaderValue, certificate); var authResult = await _authenticateClient.AuthenticateAsync(instruction, issuerName); var client = authResult.Client; if (client == null) { throw new IdentityServerException(ErrorCodes.InvalidClient, authResult.ErrorMessage); } // 2. Check client if (client.GrantTypes == null || !client.GrantTypes.Contains(GrantType.client_credentials)) { throw new IdentityServerException(ErrorCodes.InvalidClient, string.Format(ErrorDescriptions.TheClientDoesntSupportTheGrantType, client.ClientId, GrantType.client_credentials)); } if (client.ResponseTypes == null || !client.ResponseTypes.Contains(ResponseType.token)) { throw new IdentityServerException(ErrorCodes.InvalidClient, string.Format(ErrorDescriptions.TheClientDoesntSupportTheResponseType, client.ClientId, ResponseType.token)); } // 3. Check scopes string allowedTokenScopes = string.Empty; if (!string.IsNullOrWhiteSpace(clientCredentialsGrantTypeParameter.Scope)) { var scopeValidation = _scopeValidator.Check(clientCredentialsGrantTypeParameter.Scope, client); if (!scopeValidation.IsValid) { throw new IdentityServerException( ErrorCodes.InvalidScope, scopeValidation.ErrorMessage); } allowedTokenScopes = string.Join(" ", scopeValidation.Scopes); } // 4. Generate the JWT access token on the fly. var grantedToken = await _grantedTokenHelper.GetValidGrantedTokenAsync(allowedTokenScopes, client.ClientId); if (grantedToken == null) { grantedToken = await _grantedTokenGeneratorHelper.GenerateTokenAsync(client, allowedTokenScopes, issuerName); await _tokenStore.AddToken(grantedToken); _oauthEventSource.GrantAccessToClient(client.ClientId, grantedToken.AccessToken, allowedTokenScopes); } return(grantedToken); }
public async Task <GrantedToken> Execute(ResourceOwnerGrantTypeParameter resourceOwnerGrantTypeParameter, AuthenticationHeaderValue authenticationHeaderValue, X509Certificate2 certificate = null) { if (resourceOwnerGrantTypeParameter == null) { throw new ArgumentNullException(nameof(resourceOwnerGrantTypeParameter)); } // 1. Try to authenticate the client var instruction = CreateAuthenticateInstruction(resourceOwnerGrantTypeParameter, authenticationHeaderValue, certificate); var authResult = await _authenticateClient.AuthenticateAsync(instruction); var client = authResult.Client; if (authResult.Client == null) { _simpleIdentityServerEventSource.Info(ErrorDescriptions.TheClientCannotBeAuthenticated); client = await _clientRepository.GetClientByIdAsync(Constants.AnonymousClientId); if (client == null) { throw new IdentityServerException(ErrorCodes.InternalError, string.Format(ErrorDescriptions.ClientIsNotValid, Constants.AnonymousClientId)); } } // 2. Try to authenticate a resource owner var resourceOwner = await _authenticateResourceOwnerService.AuthenticateResourceOwnerAsync(resourceOwnerGrantTypeParameter.UserName, resourceOwnerGrantTypeParameter.Password); if (resourceOwner == null) { throw new IdentityServerException(ErrorCodes.InvalidGrant, ErrorDescriptions.ResourceOwnerCredentialsAreNotValid); } // 3. Check if the requested scopes are valid var allowedTokenScopes = string.Empty; if (!string.IsNullOrWhiteSpace(resourceOwnerGrantTypeParameter.Scope)) { var scopeValidation = _scopeValidator.Check(resourceOwnerGrantTypeParameter.Scope, client); if (!scopeValidation.IsValid) { throw new IdentityServerException(ErrorCodes.InvalidScope, scopeValidation.ErrorMessage); } allowedTokenScopes = string.Join(" ", scopeValidation.Scopes); } // 4. Generate the user information payload and store it. var claims = resourceOwner.Claims; var claimsIdentity = new ClaimsIdentity(claims, "simpleIdentityServer"); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); var authorizationParameter = new AuthorizationParameter { Scope = resourceOwnerGrantTypeParameter.Scope }; var payload = await _jwtGenerator.GenerateUserInfoPayloadForScopeAsync(claimsPrincipal, authorizationParameter); var generatedToken = await _grantedTokenHelper.GetValidGrantedTokenAsync(allowedTokenScopes, client.ClientId, payload, payload); if (generatedToken == null) { generatedToken = await _grantedTokenGeneratorHelper.GenerateTokenAsync(client.ClientId, allowedTokenScopes, payload, payload); await _grantedTokenRepository.InsertAsync(generatedToken); // Fill-in the id-token if (generatedToken.IdTokenPayLoad != null) { generatedToken.IdToken = await _clientHelper.GenerateIdTokenAsync(client, generatedToken.IdTokenPayLoad); } _simpleIdentityServerEventSource.GrantAccessToClient(client.ClientId, generatedToken.AccessToken, allowedTokenScopes); } return(generatedToken); }
public async Task <IntrospectionResult> Execute( IntrospectionParameter introspectionParameter, AuthenticationHeaderValue authenticationHeaderValue, string issuerName) { // 1. Validate the parameters if (introspectionParameter == null) { throw new ArgumentNullException(nameof(introspectionParameter)); } if (string.IsNullOrWhiteSpace(introspectionParameter.Token)) { throw new ArgumentNullException(nameof(introspectionParameter.Token)); } _introspectionParameterValidator.Validate(introspectionParameter); // 2. Authenticate the client var instruction = CreateAuthenticateInstruction(introspectionParameter, authenticationHeaderValue); var authResult = await _authenticateClient.AuthenticateAsync(instruction, issuerName); if (authResult.Client == null) { throw new IdentityServerException(ErrorCodes.InvalidClient, authResult.ErrorMessage); } // 3. Retrieve the token type hint var tokenTypeHint = Constants.StandardTokenTypeHintNames.AccessToken; if (Constants.AllStandardTokenTypeHintNames.Contains(introspectionParameter.TokenTypeHint)) { tokenTypeHint = introspectionParameter.TokenTypeHint; } // 4. Trying to fetch the information about the access_token || refresh_token GrantedToken grantedToken = null; if (tokenTypeHint == Constants.StandardTokenTypeHintNames.AccessToken) { grantedToken = await _tokenStore.GetAccessToken(introspectionParameter.Token); if (grantedToken == null) { grantedToken = await _tokenStore.GetRefreshToken(introspectionParameter.Token); } } else { grantedToken = await _tokenStore.GetRefreshToken(introspectionParameter.Token); if (grantedToken == null) { grantedToken = await _tokenStore.GetAccessToken(introspectionParameter.Token); } } // 5. Throw an exception if there's no granted token if (grantedToken == null) { throw new IdentityServerException( ErrorCodes.InvalidToken, ErrorDescriptions.TheTokenIsNotValid); } // 6. Fill-in parameters //// TODO : Specifiy the other parameters : NBF & JTI var result = new IntrospectionResult { Scope = grantedToken.Scope, ClientId = grantedToken.ClientId, Expiration = grantedToken.ExpiresIn, TokenType = grantedToken.TokenType }; // 7. Fill-in the other parameters if (grantedToken.IdTokenPayLoad != null) { var audiences = string.Empty; var audiencesArr = grantedToken.IdTokenPayLoad.GetArrayClaim(StandardClaimNames.Audiences); var issuedAt = grantedToken.IdTokenPayLoad.Iat; var issuer = grantedToken.IdTokenPayLoad.Issuer; var subject = grantedToken.IdTokenPayLoad.GetClaimValue(Jwt.Constants.StandardResourceOwnerClaimNames.Subject); var userName = grantedToken.IdTokenPayLoad.GetClaimValue(Jwt.Constants.StandardResourceOwnerClaimNames.Name); if (audiencesArr.Any()) { audiences = string.Join(" ", audiencesArr); } result.Audience = audiences; result.IssuedAt = issuedAt; result.Issuer = issuer; result.Subject = subject; result.UserName = userName; } // 8. Based on the expiration date disable OR enable the introspection result var expirationDateTime = grantedToken.CreateDateTime.AddSeconds(grantedToken.ExpiresIn); var tokenIsExpired = DateTime.UtcNow > expirationDateTime; if (tokenIsExpired) { result.Active = false; } else { result.Active = true; } return(result); }
public async Task <GrantedToken> Execute(GetTokenViaTicketIdParameter parameter, AuthenticationHeaderValue authenticationHeaderValue, X509Certificate2 certificate, string issuerName) { // 1. Check parameters. if (parameter == null) { throw new ArgumentNullException(nameof(parameter)); } if (string.IsNullOrWhiteSpace(parameter.Ticket)) { throw new BaseUmaException(ErrorCodes.InvalidRequestCode, string.Format(ErrorDescriptions.TheParameterNeedsToBeSpecified, PostAuthorizationNames.TicketId)); } if (string.IsNullOrWhiteSpace(parameter.Ticket)) { throw new ArgumentNullException(nameof(parameter.Ticket)); } // 2. Try to authenticate the client. var instruction = CreateAuthenticateInstruction(parameter, authenticationHeaderValue, certificate); var authResult = await _authenticateClient.AuthenticateAsync(instruction, issuerName); var client = authResult.Client; if (client == null) { throw new BaseUmaException(ErrorCodes.InvalidClient, authResult.ErrorMessage); } if (client.GrantTypes == null || !client.GrantTypes.Contains(GrantType.uma_ticket)) { throw new BaseUmaException(ErrorCodes.InvalidGrant, string.Format(ErrorDescriptions.TheClientDoesntSupportTheGrantType, client.ClientId, GrantType.uma_ticket)); } // 3. Retrieve the ticket. var json = JsonConvert.SerializeObject(parameter); _umaServerEventSource.StartGettingAuthorization(json); var ticket = await _ticketStore.GetAsync(parameter.Ticket); if (ticket == null) { throw new BaseUmaException(ErrorCodes.InvalidTicket, string.Format(ErrorDescriptions.TheTicketDoesntExist, parameter.Ticket)); } // 4. Check the ticket. if (ticket.ExpirationDateTime < DateTime.UtcNow) { throw new BaseUmaException(ErrorCodes.ExpiredTicket, ErrorDescriptions.TheTicketIsExpired); } _umaServerEventSource.CheckAuthorizationPolicy(json); var claimTokenParameter = new ClaimTokenParameter { Token = parameter.ClaimToken, Format = parameter.ClaimTokenFormat }; // 4. Check the authorization. var authorizationResult = await _authorizationPolicyValidator.IsAuthorized(ticket, client.ClientId, claimTokenParameter); if (authorizationResult.Type != AuthorizationPolicyResultEnum.Authorized) { _umaServerEventSource.RequestIsNotAuthorized(json); throw new BaseUmaException(ErrorCodes.InvalidGrant, ErrorDescriptions.TheAuthorizationPolicyIsNotSatisfied); } // 5. Generate a granted token. var grantedToken = await GenerateTokenAsync(client, ticket.Lines, "openid", issuerName); await _tokenStore.AddToken(grantedToken); await _ticketStore.RemoveAsync(ticket.Id); return(grantedToken); }
public async Task <GrantedToken> Execute(ResourceOwnerGrantTypeParameter resourceOwnerGrantTypeParameter, AuthenticationHeaderValue authenticationHeaderValue, X509Certificate2 certificate, string issuerName) { if (resourceOwnerGrantTypeParameter == null) { throw new ArgumentNullException(nameof(resourceOwnerGrantTypeParameter)); } // 1. Try to authenticate the client var instruction = CreateAuthenticateInstruction(resourceOwnerGrantTypeParameter, authenticationHeaderValue, certificate); var authResult = await _authenticateClient.AuthenticateAsync(instruction, issuerName); var client = authResult.Client; if (authResult.Client == null) { _oauthEventSource.Info(authResult.ErrorMessage); throw new IdentityServerException(ErrorCodes.InvalidClient, authResult.ErrorMessage); } // 2. Check the client. if (client.GrantTypes == null || !client.GrantTypes.Contains(GrantType.password)) { throw new IdentityServerException(ErrorCodes.InvalidClient, string.Format(ErrorDescriptions.TheClientDoesntSupportTheGrantType, client.ClientId, GrantType.password)); } if (client.ResponseTypes == null || !client.ResponseTypes.Contains(ResponseType.token) || !client.ResponseTypes.Contains(ResponseType.id_token)) { throw new IdentityServerException(ErrorCodes.InvalidClient, string.Format(ErrorDescriptions.TheClientDoesntSupportTheResponseType, client.ClientId, "token id_token")); } // 3. Try to authenticate a resource owner var resourceOwner = await _resourceOwnerAuthenticateHelper.Authenticate(resourceOwnerGrantTypeParameter.UserName, resourceOwnerGrantTypeParameter.Password, resourceOwnerGrantTypeParameter.AmrValues); if (resourceOwner == null) { throw new IdentityServerException(ErrorCodes.InvalidGrant, ErrorDescriptions.ResourceOwnerCredentialsAreNotValid); } // 4. Check if the requested scopes are valid var allowedTokenScopes = string.Empty; if (!string.IsNullOrWhiteSpace(resourceOwnerGrantTypeParameter.Scope)) { var scopeValidation = _scopeValidator.Check(resourceOwnerGrantTypeParameter.Scope, client); if (!scopeValidation.IsValid) { throw new IdentityServerException(ErrorCodes.InvalidScope, scopeValidation.ErrorMessage); } allowedTokenScopes = string.Join(" ", scopeValidation.Scopes); } // 5. Generate the user information payload and store it. var claims = resourceOwner.Claims; var claimsIdentity = new ClaimsIdentity(claims, "simpleIdentityServer"); var claimsPrincipal = new ClaimsPrincipal(claimsIdentity); var authorizationParameter = new AuthorizationParameter { Scope = resourceOwnerGrantTypeParameter.Scope }; var payload = await _jwtGenerator.GenerateIdTokenPayloadForScopesAsync(claimsPrincipal, authorizationParameter, issuerName); var generatedToken = await _grantedTokenHelper.GetValidGrantedTokenAsync(allowedTokenScopes, client.ClientId, payload, payload); if (generatedToken == null) { generatedToken = await _grantedTokenGeneratorHelper.GenerateTokenAsync(client, allowedTokenScopes, issuerName, payload, payload); if (generatedToken.IdTokenPayLoad != null) { await _jwtGenerator.UpdatePayloadDate(generatedToken.IdTokenPayLoad); generatedToken.IdToken = await _clientHelper.GenerateIdTokenAsync(client, generatedToken.IdTokenPayLoad); } await _tokenStore.AddToken(generatedToken); _oauthEventSource.GrantAccessToClient(client.ClientId, generatedToken.AccessToken, allowedTokenScopes); } return(generatedToken); }