private async Task <(string clientId, string redirectUri, OpenIdConnectMessage error)> ValidateClientIdAndRedirectUri( IDictionary <string, string[]> requestParameters, string state) { var(clientId, clientIdError) = RequestParametersHelper.ValidateParameterIsUnique(requestParameters, OpenIdConnectParameterNames.ClientId, _errorProvider); if (clientIdError != null) { clientIdError.State = state; return(null, null, clientIdError); } if (!await _clientIdValidator.ValidateClientIdAsync(clientId)) { clientIdError = _errorProvider.InvalidClientId(clientId); clientIdError.State = state; return(null, null, clientIdError); } var(redirectUri, redirectUriError) = RequestParametersHelper.ValidateOptionalParameterIsUnique(requestParameters, OpenIdConnectParameterNames.RedirectUri, _errorProvider); if (redirectUriError != null) { redirectUriError.State = state; return(null, null, redirectUriError); } if (redirectUri != null) { if (!Uri.IsWellFormedUriString(redirectUri, UriKind.Absolute)) { redirectUriError = _errorProvider.InvalidUriFormat(redirectUri); redirectUriError.State = state; return(null, null, redirectUriError); } var parsedUri = new Uri(redirectUri, UriKind.Absolute); if (!string.IsNullOrEmpty(parsedUri.Fragment)) { redirectUriError = _errorProvider.InvalidUriFormat(redirectUri); redirectUriError.State = state; return(null, null, redirectUriError); } } var resolvedUriResult = await _redirectUrlValidator.ResolveRedirectUriAsync(clientId, redirectUri); if (!resolvedUriResult.IsValid) { resolvedUriResult.Error.State = state; return(null, null, resolvedUriResult.Error); } return(clientId, resolvedUriResult.Uri, null); }
private async Task <OpenIdConnectMessage> ValidateAuthorizationCode( IDictionary <string, string[]> requestParameters, string clientId, AuthorizationGrant consentGrant) { if (!(consentGrant.Token is AuthorizationCode code)) { throw new InvalidOperationException("Granted token must be an authorization code."); } var(redirectUri, redirectUriError) = RequestParametersHelper.ValidateOptionalParameterIsUnique(requestParameters, OpenIdConnectParameterNames.RedirectUri, _errorProvider); if (redirectUriError != null) { return(redirectUriError); } var tokenRedirectUri = code.RedirectUri; if (redirectUri == null && tokenRedirectUri != null) { return(_errorProvider.MissingRequiredParameter(OpenIdConnectParameterNames.RedirectUri)); } if (!string.Equals(redirectUri, tokenRedirectUri, StringComparison.Ordinal)) { return(_errorProvider.MismatchedRedirectUrl(redirectUri)); } var resolution = await _redirectUriValidator.ResolveRedirectUriAsync(clientId, redirectUri); if (!resolution.IsValid) { return(_errorProvider.InvalidRedirectUri(redirectUri)); } if (code.CodeChallenge != null) { if (!ProofOfKeyForCodeExchangeChallengeMethods.SHA256.Equals(code.CodeChallengeMethod, StringComparison.Ordinal)) { throw new InvalidOperationException("Unsupported code challenge method."); } var(verifier, verifierError) = RequestParametersHelper.ValidateParameterIsUnique(requestParameters, ProofOfKeyForCodeExchangeParameterNames.CodeVerifier, _errorProvider); if (verifierError != null) { return(verifierError); } // code-verifier = [a-zA-Z0-9\-._~]{43,128} if (verifier.Length < 43 || verifier.Length > 128) { return(_errorProvider.InvalidCodeVerifier()); } for (var i = 0; i < verifier.Length; i++) { if (verifier[i] > 127 || !ValidCodeVerifierCharacters[verifier[i]]) { return(_errorProvider.InvalidCodeVerifier()); } } if (!string.Equals(code.CodeChallenge, GetComputedChallenge(verifier), StringComparison.Ordinal)) { return(_errorProvider.InvalidCodeVerifier()); } } return(null); }