internal static async Task <MobileConnectStatus> RequestToken(IAuthentication authentication, DiscoveryResponse discoveryResponse, Uri redirectedUrl, string expectedState, string expectedNonce, MobileConnectConfig config) { RequestTokenResponse response; if (string.IsNullOrEmpty(expectedState)) { return(MobileConnectStatus.Error("required_arg_missing", "ExpectedState argument was not supplied, this is needed to prevent Cross-Site Request Forgery", null)); } if (string.IsNullOrEmpty(expectedNonce)) { return(MobileConnectStatus.Error("required_arg_missing", "expectedNonce argument was not supplied, this is needed to prevent Replay Attacks", null)); } var actualState = HttpUtils.ExtractQueryValue(redirectedUrl.Query, "state"); if (expectedState != actualState) { return(MobileConnectStatus.Error("invalid_state", "State values do not match, this could suggest an attempted Cross-Site Request Forgery", null)); } try { var code = HttpUtils.ExtractQueryValue(redirectedUrl.Query, "code"); var clientId = discoveryResponse?.ResponseData?.response?.client_id ?? config.ClientId; var clientSecret = discoveryResponse?.ResponseData?.response?.client_secret ?? config.ClientSecret; var requestTokenUrl = discoveryResponse?.OperatorUrls?.RequestTokenUrl; response = await authentication.RequestTokenAsync(clientId, clientSecret, requestTokenUrl, config.RedirectUrl, code); if (response.ErrorResponse != null) { return(MobileConnectStatus.Error(response.ErrorResponse.Error, response.ErrorResponse.ErrorDescription, null, response)); } if (!Validation.IsExpectedNonce(response.ResponseData.IdToken, expectedNonce)) { return(MobileConnectStatus.Error("invalid_nonce", "Nonce values do not match, this could suggest an attempted Replay Attack", null)); } } catch (MobileConnectInvalidArgumentException e) { return(MobileConnectStatus.Error("invalid_argument", string.Format("An argument was found to be invalid during the process. The argument was {0}.", e.Argument), e)); } catch (MobileConnectEndpointHttpException e) { return(MobileConnectStatus.Error("http_failure", "An HTTP failure occured while calling the operator token endpoint, the endpoint may be inaccessible", e)); } catch (Exception e) { return(MobileConnectStatus.Error("unknown_error", "A failure occured while requesting a token", e)); } return(MobileConnectStatus.Complete(response)); }
internal static async Task <MobileConnectStatus> RefreshToken(IAuthenticationService authentication, string refreshToken, DiscoveryResponse discoveryResponse, MobileConnectConfig config) { Validate.RejectNull(discoveryResponse, "discoveryResponse"); Validate.RejectNullOrEmpty(refreshToken, "refreshToken"); if (!IsUsableDiscoveryResponse(discoveryResponse)) { return(MobileConnectStatus.StartDiscovery()); } string refreshTokenUrl = discoveryResponse.OperatorUrls.RefreshTokenUrl ?? discoveryResponse.OperatorUrls.RequestTokenUrl; var notSupported = IsSupported(refreshTokenUrl, "Refresh", discoveryResponse.ProviderMetadata?.Issuer); if (notSupported != null) { return(notSupported); } string clientId = discoveryResponse.ResponseData.response.client_id ?? config.ClientId; string clientSecret = discoveryResponse.ResponseData.response.client_secret ?? config.ClientSecret; try { RequestTokenResponse requestTokenResponse = await authentication.RefreshTokenAsync(clientId, clientSecret, refreshTokenUrl, refreshToken); ErrorResponse errorResponse = requestTokenResponse.ErrorResponse; if (errorResponse != null) { Log.Error(() => $"Responding with responseType={MobileConnectResponseType.Error} for refreshToken for authentication service responded with error={errorResponse.Error}"); return(MobileConnectStatus.Error(errorResponse)); } else { Log.Info(() => $"Refresh token success"); return(MobileConnectStatus.Complete(requestTokenResponse)); } } catch (Exception e) { Log.Error(() => $"RefreshToken failed", e); return(MobileConnectStatus.Error(ErrorCodes.Unknown, "Refresh token error", e)); } }
private static MobileConnectStatus HandleTokenResponse(IAuthenticationService authentication, RequestTokenResponse response, string clientId, string issuer, string expectedNonce, string version, JWKeyset jwks, MobileConnectRequestOptions options) { if (response.ErrorResponse != null) { return(MobileConnectStatus.Error(response.ErrorResponse.Error, response.ErrorResponse.ErrorDescription, null, response)); } response.ValidationResult = authentication.ValidateTokenResponse(response, clientId, issuer, expectedNonce, options?.MaxAge, jwks, version); var validationOptions = options?.TokenValidationOptions ?? new TokenValidationOptions(); if (!validationOptions.AcceptedValidationResults.HasFlag(response.ValidationResult)) { Log.Error(() => $"A generated tokenResponse was invalid issuer={issuer} version={version} result={response.ValidationResult}"); return(MobileConnectStatus.Error(ErrorCodes.InvalidToken, $"The token was found to be invalid with the validation result {response.ValidationResult}", null, response)); } else if (response.ValidationResult != TokenValidationResult.Valid) { Log.Warning(() => $"A generated tokenResponse was invalid but accepted issuer={issuer} version={version} result={response.ValidationResult}"); } return(MobileConnectStatus.Complete(response)); }