public async Task <ClientRecord> FetchClientRecordAsync(string scheme, string clientId) { var key = $"{scheme}.{clientId}"; var result = await _cacheClientRecord.GetAsync(key, CachingExpiration, () => _inner.FetchClientRecordAsync(scheme, clientId), _logger); return(result); }
public async Task <AuthorizeRequestValidationResult> ValidateAsync(ValidatedAuthorizeRequest request) { var parameters = request.Raw; request.Nonce = parameters.Get(OidcConstants.AuthorizeRequest.Nonce); var state = parameters.Get(OidcConstants.AuthorizeRequest.State); if (state.IsPresent()) { request.State = state; } ////////////////////////////////////////////////////////// // redirect_uri must be present and supported ////////////////////////////////////////////////////////// var redirectUri = parameters.Get(OidcConstants.AuthorizeRequest.RedirectUri); if (redirectUri.IsMissing()) { _logger.LogError($"Missing {OidcConstants.AuthorizeRequest.RedirectUri}"); return(Invalid(request, OidcConstants.AuthorizeErrors.InvalidRequestUri, $"Missing {OidcConstants.AuthorizeRequest.RedirectUri}")); } ////////////////////////////////////////////////////////// // response_type must be present and supported ////////////////////////////////////////////////////////// var responseType = parameters.Get(OidcConstants.AuthorizeRequest.ResponseType); if (responseType.IsMissing()) { _logger.LogError($"Missing {OidcConstants.AuthorizeRequest.ResponseType}"); return(Invalid(request, OidcConstants.AuthorizeErrors.UnsupportedResponseType, $"Missing {OidcConstants.AuthorizeRequest.ResponseType}")); } if (!SupportedResponseTypes.Contains(responseType, _responseTypeEqualityComparer)) { _logger.LogError("Response type not supported", responseType); return(Invalid(request, OidcConstants.AuthorizeErrors.UnsupportedResponseType, "Response type not supported")); } request.ResponseType = SupportedResponseTypes.First( supportedResponseType => _responseTypeEqualityComparer.Equals(supportedResponseType, responseType)); ////////////////////////////////////////////////////////// // match response_type to grant type ////////////////////////////////////////////////////////// request.GrantType = Constants.ResponseTypeToGrantTypeMapping[responseType]; ////////////////////////////////////////////////////////// // check if flow is allowed at authorize endpoint ////////////////////////////////////////////////////////// if (!Constants.AllowedGrantTypesForAuthorizeEndpoint.Contains(request.GrantType)) { LogError("Invalid grant type", request.GrantType, request); return(Invalid(request, description: "Invalid response_type")); } // set default response mode for flow; this is needed for any client error processing below request.ResponseMode = Constants.AllowedResponseModesForGrantType[request.GrantType].First(); ////////////////////////////////////////////////////////// // client_id must be present and supported ////////////////////////////////////////////////////////// request.ClientId = parameters.Get(OidcConstants.AuthorizeRequest.ClientId); if (request.ClientId.IsMissing()) { _logger.LogError($"Missing {OidcConstants.AuthorizeRequest.ClientId}"); return(Invalid(request, OidcConstants.AuthorizeErrors.UnauthorizedClient, $"Missing {OidcConstants.AuthorizeRequest.ClientId}")); } ////////////////////////////////////////////////////////// // redirect_uri must be present, and a valid uri ////////////////////////////////////////////////////////// request.RedirectUri = parameters.Get(OidcConstants.AuthorizeRequest.RedirectUri); if (request.RedirectUri.IsMissing()) { _logger.LogError($"Missing {OidcConstants.AuthorizeRequest.RedirectUri}"); return(Invalid(request, OidcConstants.AuthorizeRequest.RedirectUri, $"Missing {OidcConstants.AuthorizeRequest.RedirectUri}")); } var clientRecord = await _clientSecretStore.FetchClientRecordAsync(_options.Scheme, request.ClientId); if (clientRecord == null) { _logger.LogError($"Missing {OidcConstants.AuthorizeRequest.ClientId}"); return(Invalid(request, OidcConstants.AuthorizeErrors.UnauthorizedClient, $"Missing {OidcConstants.AuthorizeRequest.ClientId}")); } if (!clientRecord.RedirectUris.Contains(request.RedirectUri)) { _logger.LogError($"Missing {OidcConstants.AuthorizeRequest.RedirectUri}"); return(Invalid(request, OidcConstants.AuthorizeErrors.UnauthorizedClient, $"Missing {OidcConstants.AuthorizeRequest.ClientId}")); } ////////////////////////////////////////////////////////// // check response_mode parameter and set response_mode ////////////////////////////////////////////////////////// // check if response_mode parameter is present and valid var responseMode = parameters.Get(OidcConstants.AuthorizeRequest.ResponseMode); if (responseMode.IsPresent()) { if (Constants.SupportedResponseModes.Contains(responseMode)) { if (Constants.AllowedResponseModesForGrantType[request.GrantType].Contains(responseMode)) { request.ResponseMode = responseMode; } else { LogError("Invalid response_mode for flow", responseMode, request); return(Invalid(request, OidcConstants.AuthorizeErrors.UnsupportedResponseType, description: "Invalid response_mode")); } } else { LogError("Unsupported response_mode", responseMode, request); return(Invalid(request, OidcConstants.AuthorizeErrors.UnsupportedResponseType, description: "Invalid response_mode")); } } ////////////////////////////////////////////////////////// // check if PKCE is required and validate parameters ////////////////////////////////////////////////////////// if (request.GrantType == GrantType.AuthorizationCode || request.GrantType == GrantType.Hybrid) { _logger.LogDebug("Checking for PKCE parameters"); ///////////////////////////////////////////////////////////////////////////// // validate code_challenge and code_challenge_method ///////////////////////////////////////////////////////////////////////////// var proofKeyResult = ValidatePkceParameters(request); if (proofKeyResult.IsError) { return(proofKeyResult); } } return(Valid(request)); }