private HttpResponseMessage ProcessJwtRequest(TokenRequest request) { if (string.IsNullOrEmpty(request.Assertion)) { Tracing.Error("ADFS integration authentication request (JWT) with empty assertion"); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidGrant); } Tracing.Information("Starting ADFS integration authentication request (JWT) for scope: " + request.Scope); var bridge = new AdfsBridge(ConfigurationRepository); GenericXmlSecurityToken token; try { Tracing.Verbose("Starting ADFS integration authentication request (JWT) for assertion: " + request.Assertion); token = bridge.AuthenticateJwt(request.Assertion, request.Scope); } catch (Exception ex) { Tracing.Error("Error while communicating with ADFS: " + ex.ToString()); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidRequest); } var response = CreateTokenResponse(token, request.Scope); Tracing.Verbose("ADFS integration JWT authentication successful"); return response; }
public HttpResponseMessage Post(TokenRequest request) { Tracing.Start("OIDC Token Endpoint"); ValidatedRequest validatedRequest; try { var validator = new TokenRequestValidator(Clients, Grants); validatedRequest = validator.Validate(request, ClaimsPrincipal.Current); } catch (TokenRequestValidationException ex) { Tracing.Error("Aborting OIDC token request"); return Request.CreateOAuthErrorResponse(ex.OAuthError); } // switch over the grant type if (validatedRequest.GrantType.Equals(OAuth2Constants.GrantTypes.AuthorizationCode)) { return ProcessAuthorizationCodeRequest(validatedRequest); } else if (string.Equals(validatedRequest.GrantType, OAuth2Constants.GrantTypes.RefreshToken)) { return ProcessRefreshTokenRequest(validatedRequest); } Tracing.Error("unsupported grant type: " + request.Grant_Type); return Request.CreateOAuthErrorResponse(OAuth2Constants.Errors.UnsupportedGrantType); }
public HttpResponseMessage Post(TokenRequest tokenRequest) { Tracing.Information("OAuth2 endpoint called."); Client client = null; if (!ValidateClient(out client)) { Tracing.Error("Invalid client: " + ClaimsPrincipal.Current.Identity.Name); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidClient); } Tracing.Information("Client: " + client.Name); var tokenType = ConfigurationRepository.Global.DefaultHttpTokenType; // validate scope EndpointReference appliesTo; try { appliesTo = new EndpointReference(tokenRequest.Scope); Tracing.Information("OAuth2 endpoint called for scope: " + tokenRequest.Scope); } catch { Tracing.Error("Malformed scope: " + tokenRequest.Scope); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidScope); } // check grant type if (string.Equals(tokenRequest.Grant_Type, OAuth2Constants.GrantTypes.Password, System.StringComparison.Ordinal)) { if (ConfigurationRepository.OAuth2.EnableResourceOwnerFlow) { if (client.AllowResourceOwnerFlow) { return ProcessResourceOwnerCredentialRequest(tokenRequest.UserName, tokenRequest.Password, appliesTo, tokenType, client); } else { Tracing.Error("Client is not allowed to use the resource owner password flow:" + client.Name); } } } Tracing.Error("invalid grant type: " + tokenRequest.Grant_Type); return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType); }
private HttpResponseMessage ProcessResourceOwnerCredentialRequest(TokenRequest request, string tokenType, Client client) { Tracing.Information("Starting resource owner password credential flow for client: " + client.Name); var appliesTo = new EndpointReference(request.Scope); if (string.IsNullOrWhiteSpace(request.UserName) || string.IsNullOrWhiteSpace(request.Password)) { Tracing.Error("Invalid resource owner credentials for: " + appliesTo.Uri.AbsoluteUri); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidGrant); } if (UserRepository.ValidateUser(request.UserName, request.Password)) { return CreateTokenResponse(request.UserName, client, appliesTo, tokenType, includeRefreshToken: client.AllowRefreshToken); } else { Tracing.Error("Resource owner credential validation failed: " + request.UserName); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidGrant); } }
public HttpResponseMessage Post(TokenRequest request) { if (request == null) { return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidRequest); } Uri uri; if (string.IsNullOrEmpty(request.Scope) || !Uri.TryCreate(request.Scope, UriKind.Absolute, out uri)) { Tracing.Error("Starting ADFS integration request with invalid scope: " + request.Scope); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidScope); } if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password) && ConfigurationRepository.AdfsIntegration.UsernameAuthenticationEnabled) { return ProcessUserNameRequest(request); } // federation via SAML if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Saml2) && ConfigurationRepository.AdfsIntegration.SamlAuthenticationEnabled) { return ProcessSamlRequest(request); } // federation via JWT if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.JWT) && ConfigurationRepository.AdfsIntegration.JwtAuthenticationEnabled) { return ProcessJwtRequest(request); } Tracing.Error("Unsupported grant type: " + request.Grant_Type); return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType); }
private HttpResponseMessage ValidateRequest(TokenRequest request, out Client client) { client = null; // grant type is required if (string.IsNullOrWhiteSpace(request.Grant_Type)) { return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType); } // check supported grant types if (!request.Grant_Type.Equals(OAuth2Constants.GrantTypes.AuthorizationCode) && !request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password) && !request.Grant_Type.Equals(OAuth2Constants.GrantTypes.RefreshToken)) { return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType); } // resource owner password flow requires a well-formed scope EndpointReference appliesTo = null; if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password)) { try { appliesTo = new EndpointReference(request.Scope); Tracing.Information("OAuth2 endpoint called for scope: " + request.Scope); } catch { Tracing.Error("Malformed scope: " + request.Scope); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidScope); } } if (!ValidateClient(out client)) { Tracing.Error("Invalid client: " + ClaimsPrincipal.Current.Identity.Name); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidClient); } // validate grant types against global and client configuration if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.AuthorizationCode)) { if (!ConfigurationRepository.OAuth2.EnableCodeFlow || !client.AllowCodeFlow) { return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType); } } if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password)) { if (!ConfigurationRepository.OAuth2.EnableResourceOwnerFlow || !client.AllowResourceOwnerFlow) { return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType); } } if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.RefreshToken)) { if (!client.AllowRefreshToken) { return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType); } } return null; }
public ValidatedRequest Validate(TokenRequest request, ClaimsPrincipal clientPrincipal) { var validatedRequest = new ValidatedRequest(); // validate request model binding if (request == null) { throw new TokenRequestValidationException( "Invalid request parameters.", OAuth2Constants.Errors.InvalidRequest); } // grant type is required if (string.IsNullOrWhiteSpace(request.Grant_Type)) { throw new TokenRequestValidationException( "Missing grant_type", OAuth2Constants.Errors.UnsupportedGrantType); } // check supported grant types if (request.Grant_Type == OAuth2Constants.GrantTypes.AuthorizationCode || request.Grant_Type == OAuth2Constants.GrantTypes.RefreshToken) { validatedRequest.GrantType = request.Grant_Type; Tracing.Information("Grant type: " + validatedRequest.GrantType); } else { throw new TokenRequestValidationException( "Invalid grant_type: " + request.Grant_Type, OAuth2Constants.Errors.UnsupportedGrantType); } // validate client credentials var client = ValidateClient(clientPrincipal); if (client == null) { throw new TokenRequestValidationException( "Invalid client: " + clientPrincipal.Identity.Name, OAuth2Constants.Errors.InvalidClient); } validatedRequest.Client = client; Tracing.InformationFormat("Client: {0} ({1})", validatedRequest.Client.Name, validatedRequest.Client.ClientId); switch (request.Grant_Type) { case OAuth2Constants.GrantTypes.AuthorizationCode: ValidateCodeGrant(validatedRequest, request); break; case OAuth2Constants.GrantTypes.RefreshToken: ValidateRefreshTokenGrant(validatedRequest, request); break; default: throw new TokenRequestValidationException( "Invalid grant_type: " + request.Grant_Type, OAuth2Constants.Errors.UnsupportedGrantType); } Tracing.Information("Token request validation successful."); return validatedRequest; }
private void ValidateCodeGrant(ValidatedRequest validatedRequest, TokenRequest request) { if (!validatedRequest.Client.AllowCodeFlow) { throw new TokenRequestValidationException( "Code flow not allowed for client", OAuth2Constants.Errors.UnauthorizedClient); } // code needs to be present if (string.IsNullOrWhiteSpace(request.Code)) { throw new TokenRequestValidationException( "Missing authorization code", OAuth2Constants.Errors.InvalidGrant); } //validatedRequest.AuthorizationCode = request.Code; Tracing.Information("Authorization code: " + request.Code); // check for authorization code in datastore var grant = Grants.Get(request.Code); if (grant == null) { throw new TokenRequestValidationException( "Authorization code not found: " + request.Code, OAuth2Constants.Errors.InvalidGrant); } // make sure the handle is an authorization code if (grant.GrantType != StoredGrantType.AuthorizationCode) { throw new TokenRequestValidationException( "Tampered authorization code: " + request.Code, OAuth2Constants.Errors.InvalidGrant); } validatedRequest.Grant = grant; Tracing.Information("Token handle found: " + grant.GrantId); // check the client binding if (grant.ClientId != validatedRequest.Client.ClientId) { throw new TokenRequestValidationException( string.Format("Client {0} is trying to request token using an authorization code from {1}.", validatedRequest.Client.ClientId, grant.ClientId), OAuth2Constants.Errors.InvalidGrant); } // redirect URI is required if (string.IsNullOrWhiteSpace(request.Redirect_Uri)) { throw new TokenRequestValidationException( string.Format("Redirect URI is missing"), OAuth2Constants.Errors.InvalidRequest); } // check if redirect URI from authorize and token request match if (!grant.RedirectUri.Equals(request.Redirect_Uri)) { throw new TokenRequestValidationException( string.Format("Redirect URI in token request ({0}), does not match redirect URI from authorize request ({1})", validatedRequest.RedirectUri, grant.RedirectUri), OAuth2Constants.Errors.InvalidRequest); } }
private void ValidateRefreshTokenGrant(ValidatedRequest validatedRequest, TokenRequest request) { if (!validatedRequest.Client.AllowRefreshToken) { throw new TokenRequestValidationException( "Refresh token not allowed for client", OAuth2Constants.Errors.UnauthorizedClient); } // code needs to be present if (string.IsNullOrWhiteSpace(request.Refresh_Token)) { throw new TokenRequestValidationException( "Missing refresh token", OAuth2Constants.Errors.InvalidGrant); } Tracing.Information("Refresh token: " + request.Refresh_Token); // check for authorization code in datastore var grant = Grants.Get(request.Refresh_Token); if (grant == null) { throw new TokenRequestValidationException( "Refresh token not found: " + request.Refresh_Token, OAuth2Constants.Errors.InvalidGrant); } // make sure the handle is an authorization code if (grant.GrantType != StoredGrantType.RefreshToken) { throw new TokenRequestValidationException( "Tampered refresh token: " + request.Refresh_Token, OAuth2Constants.Errors.InvalidGrant); } validatedRequest.Grant = grant; Tracing.Information("Stored grant found: " + grant.GrantId); // check the client binding if (grant.ClientId != validatedRequest.Client.ClientId) { throw new TokenRequestValidationException( string.Format("Client {0} is trying to request a token using a refresh token from {1}.", validatedRequest.Client.ClientId, grant.ClientId), OAuth2Constants.Errors.InvalidGrant); } }
private HttpResponseMessage ValidateRequest(TokenRequest request, out Client client) { client = null; if (request == null) { return(OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidRequest)); } // grant type is required if (string.IsNullOrWhiteSpace(request.Grant_Type)) { return(OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType)); } // check supported grant types if (!request.Grant_Type.Equals(OAuth2Constants.GrantTypes.AuthorizationCode) && !request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password) && !request.Grant_Type.Equals(OAuth2Constants.GrantTypes.RefreshToken)) { return(OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType)); } // resource owner password flow requires a well-formed scope if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password)) { Uri appliesTo; if (!Uri.TryCreate(request.Scope, UriKind.Absolute, out appliesTo)) { Tracing.Error("Malformed scope: " + request.Scope); return(OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidScope)); } Tracing.Information("OAuth2 endpoint called for scope: " + request.Scope); } if (!ValidateClient(out client)) { Tracing.Error("Invalid client: " + ClaimsPrincipal.Current.Identity.Name); return(OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidClient)); } // validate grant types against global and client configuration if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.AuthorizationCode)) { if (!ConfigurationRepository.OAuth2.EnableCodeFlow || !client.AllowCodeFlow) { Tracing.Error("Code flow not allowed for client"); return(OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType)); } } if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password)) { if (!ConfigurationRepository.OAuth2.EnableResourceOwnerFlow || !client.AllowResourceOwnerFlow) { Tracing.Error("Resource owner password flow not allowed for client"); return(OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType)); } } if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.RefreshToken)) { if (!client.AllowRefreshToken) { Tracing.Error("Refresh tokens not allowed for client"); return(OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType)); } } return(null); }
private HttpResponseMessage ProcessUserNameRequest(TokenRequest request) { if (string.IsNullOrEmpty(request.UserName) || string.IsNullOrEmpty(request.Password)) { Tracing.Error("ADFS integration username authentication request with empty username or password"); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidGrant); } Tracing.Information("Starting ADFS integration username authentication request for scope: " + request.Scope); var bridge = new AdfsBridge(ConfigurationRepository); GenericXmlSecurityToken token; try { Tracing.Verbose("ADFS integration username authentication request for user: "******"Error while communicating with ADFS: " + ex.ToString()); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidRequest); } var response = CreateTokenResponse(token, request.Scope); Tracing.Verbose("ADFS integration username authentication request successful"); return response; }
private HttpResponseMessage ProcessSamlRequest(TokenRequest request) { if (string.IsNullOrEmpty(request.Assertion)) { Tracing.Error("ADFS integration SAML authentication request with empty assertion"); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidGrant); } // un-base64 saml token string string incomingSamlToken; try { incomingSamlToken = Encoding.UTF8.GetString(Convert.FromBase64String(request.Assertion)); } catch { Tracing.Error("ADFS integration SAML authentication request with malformed SAML assertion: " + request.Assertion); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidGrant); } Tracing.Information("Starting ADFS integration SAML authentication request for scope: " + request.Scope); var bridge = new AdfsBridge(ConfigurationRepository); GenericXmlSecurityToken token; try { Tracing.Verbose("ADFS integration SAML authentication request for assertion: " + request.Assertion); token = bridge.AuthenticateSaml(incomingSamlToken, request.Scope); } catch (Exception ex) { Tracing.Error("Error while communicating with ADFS: " + ex.ToString()); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidRequest); } var response = CreateTokenResponse(token, request.Scope); Tracing.Verbose("ADFS integration SAML authentication request successful"); return response; }
private HttpResponseMessage ValidateRequest(TokenRequest request, out Client client) { client = null; if (request == null) { return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidRequest); } // grant type is required if (string.IsNullOrWhiteSpace(request.Grant_Type)) { return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType); } // check supported grant types if (!request.Grant_Type.Equals(OAuth2Constants.GrantTypes.AuthorizationCode) && !request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password) && !request.Grant_Type.Equals(OAuth2Constants.GrantTypes.RefreshToken)) { return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType); } // resource owner password flow requires a well-formed scope if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password)) { Uri appliesTo; if (!Uri.TryCreate(request.Scope, UriKind.Absolute, out appliesTo)) { logger.Error("Malformed scope: " + request.Scope); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidScope); } logger.Info("OAuth2 endpoint called for scope: " + request.Scope); } if (!ValidateClient(out client)) { logger.Error("Invalid client: " + ClaimsPrincipal.Current.Identity.Name); return OAuthErrorResponseMessage(OAuth2Constants.Errors.InvalidClient); } // validate grant types against global and client configuration if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.AuthorizationCode)) { if (!ConfigurationRepository.OAuth2.EnableCodeFlow || !client.AllowCodeFlow) { logger.Error("Code flow not allowed for client"); return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType); } } if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.Password)) { if (!ConfigurationRepository.OAuth2.EnableResourceOwnerFlow || !client.AllowResourceOwnerFlow) { logger.Error("Resource owner password flow not allowed for client"); return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType); } } if (request.Grant_Type.Equals(OAuth2Constants.GrantTypes.RefreshToken)) { if (!client.AllowRefreshToken) { logger.Error("Refresh tokens not allowed for client"); return OAuthErrorResponseMessage(OAuth2Constants.Errors.UnsupportedGrantType); } } return null; }