/// <summary> /// Processes the authorize response. /// </summary> /// <param name="data">The response data.</param> /// <param name="state">The state.</param> /// <param name="backChannelParameters">Parameters for back-channel call</param> /// <param name="cancellationToken">A token that can be used to cancel the request</param> /// <returns> /// Result of the login response validation /// </returns> public virtual async Task <LoginResult> ProcessResponseAsync( string data, AuthorizeState state, BackChannelParameters backChannelParameters = null, CancellationToken cancellationToken = default) { _logger.LogTrace("ProcessResponseAsync"); _logger.LogInformation("Processing response."); backChannelParameters = backChannelParameters ?? new BackChannelParameters(); await EnsureConfigurationAsync(cancellationToken); _logger.LogDebug("Authorize response: {response}", data); var authorizeResponse = new AuthorizeResponse(data); if (authorizeResponse.IsError) { _logger.LogError(authorizeResponse.Error); return(new LoginResult(authorizeResponse.Error, authorizeResponse.ErrorDescription)); } var result = await _processor.ProcessResponseAsync(authorizeResponse, state, backChannelParameters, cancellationToken); if (result.IsError) { _logger.LogError(result.Error); return(new LoginResult(result.Error, result.ErrorDescription)); } var userInfoClaims = Enumerable.Empty <Claim>(); if (Options.LoadProfile) { var userInfoResult = await GetUserInfoAsync(result.TokenResponse.AccessToken, cancellationToken); if (userInfoResult.IsError) { var error = $"Error contacting userinfo endpoint: {userInfoResult.Error}"; _logger.LogError(error); return(new LoginResult(error)); } userInfoClaims = userInfoResult.Claims; var userInfoSub = userInfoClaims.FirstOrDefault(c => c.Type == JwtClaimTypes.Subject); if (userInfoSub == null) { var error = "sub claim is missing from userinfo endpoint"; _logger.LogError(error); return(new LoginResult(error)); } if (result.TokenResponse.IdentityToken != null) { if (!string.Equals(userInfoSub.Value, result.User.FindFirst(JwtClaimTypes.Subject).Value)) { var error = "sub claim from userinfo endpoint is different than sub claim from identity token."; _logger.LogError(error); return(new LoginResult(error)); } } } var user = ProcessClaims(result.User, userInfoClaims); var loginResult = new LoginResult { User = user, AccessToken = result.TokenResponse.AccessToken, RefreshToken = result.TokenResponse.RefreshToken, AccessTokenExpiration = DateTimeOffset.Now.AddSeconds(result.TokenResponse.ExpiresIn), IdentityToken = result.TokenResponse.IdentityToken, AuthenticationTime = DateTimeOffset.Now, TokenResponse = result.TokenResponse // In some cases there is additional custom response data that clients need access to }; if (loginResult.RefreshToken.IsPresent()) { loginResult.RefreshTokenHandler = new RefreshTokenDelegatingHandler( this, loginResult.AccessToken, loginResult.RefreshToken, Options.RefreshTokenInnerHttpHandler); } return(loginResult); }
/// <summary> /// Processes the authorize response. /// </summary> /// <param name="data">The response data.</param> /// <param name="state">The state.</param> /// <returns>Result of the login response validation</returns> public async Task <LoginResult> ProcessResponseAsync(string data, AuthorizeState state) { _logger.LogTrace("ProcessResponseAsync"); _logger.LogInformation("Processing response."); await EnsureConfigurationAsync(); _logger.LogDebug("Authorize response: {response}", data); var authorizeResponse = new AuthorizeResponse(data); if (authorizeResponse.IsError) { _logger.LogError(authorizeResponse.Error); return(new LoginResult(authorizeResponse.Error)); } var result = await _processor.ProcessResponseAsync(authorizeResponse, state); if (result.IsError) { _logger.LogError(result.Error); return(new LoginResult(result.Error)); } var userInfoClaims = Enumerable.Empty <Claim>(); if (_options.LoadProfile) { var userInfoResult = await GetUserInfoAsync(result.TokenResponse.AccessToken); if (userInfoResult.IsError) { var error = $"Error contacting userinfo endpoint: {userInfoResult.Error}"; _logger.LogError(error); return(new LoginResult(error)); } userInfoClaims = userInfoResult.Claims; var userInfoSub = userInfoClaims.FirstOrDefault(c => c.Type == JwtClaimTypes.Subject); if (userInfoSub == null) { var error = "sub claim is missing from userinfo endpoint"; _logger.LogError(error); return(new LoginResult(error)); } if (!string.Equals(userInfoSub.Value, result.User.FindFirst(JwtClaimTypes.Subject).Value)) { var error = "sub claim from userinfo endpoint is different than sub claim from identity token."; _logger.LogError(error); return(new LoginResult(error)); } } var user = ProcessClaims(result.User, userInfoClaims); var loginResult = new LoginResult { User = user, AccessToken = result.TokenResponse.AccessToken, RefreshToken = result.TokenResponse.RefreshToken, AccessTokenExpiration = DateTime.Now.AddSeconds(result.TokenResponse.ExpiresIn), IdentityToken = result.TokenResponse.IdentityToken, AuthenticationTime = DateTime.Now }; if (!string.IsNullOrWhiteSpace(loginResult.RefreshToken)) { loginResult.RefreshTokenHandler = new RefreshTokenHandler( TokenClientFactory.Create(_options), loginResult.RefreshToken, loginResult.AccessToken); } return(loginResult); }