private async Task <MsalTokenResponse> SendHttpAndClearTelemetryAsync(string tokenEndpoint, Core.ICoreLogger logger) { UriBuilder builder = new UriBuilder(tokenEndpoint); builder.AppendQueryParameters(_requestParams.ExtraQueryParameters); Uri tokenEndpointWithQueryParams = builder.Uri; try { logger.Verbose("[Token Client] Fetching MsalTokenResponse .... "); MsalTokenResponse msalTokenResponse = await _oAuth2Client .GetTokenAsync(tokenEndpointWithQueryParams, _requestParams.RequestContext, true, _requestParams.OnBeforeTokenRequestHandler) .ConfigureAwait(false); // Clear failed telemetry data as we've just sent it _serviceBundle.HttpTelemetryManager.ResetPreviousUnsentData(); return(msalTokenResponse); } catch (MsalServiceException ex) { if (!ex.IsAadUnavailable()) { // Clear failed telemetry data as we've just sent it ... // even if we received an error from the server, // telemetry would have been recorded _serviceBundle.HttpTelemetryManager.ResetPreviousUnsentData(); } if (ex.StatusCode == (int)HttpStatusCode.Unauthorized) { string responseHeader = string.Empty; var isChallenge = _serviceBundle.DeviceAuthManager.TryCreateDeviceAuthChallengeResponse( ex.Headers, new Uri(tokenEndpoint), // do not add query params to PKeyAuth https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/issues/2359 out responseHeader); if (isChallenge) { //Injecting PKeyAuth response here and replaying request to attempt device auth _oAuth2Client.AddHeader("Authorization", responseHeader); return(await _oAuth2Client.GetTokenAsync( tokenEndpointWithQueryParams, _requestParams.RequestContext, false, _requestParams.OnBeforeTokenRequestHandler).ConfigureAwait(false)); } } throw; } finally { _requestInProgress = false; } }
private async Task <MsalTokenResponse> SendHttpAndClearTelemetryAsync(string tokenEndpoint) { UriBuilder builder = new UriBuilder(tokenEndpoint); try { builder.AppendQueryParameters(_requestParams.ExtraQueryParameters); MsalTokenResponse msalTokenResponse = await _oAuth2Client .GetTokenAsync(builder.Uri, _requestParams.RequestContext) .ConfigureAwait(false); // Clear failed telemetry data as we've just sent it _serviceBundle.HttpTelemetryManager.ResetPreviousUnsentData(); return(msalTokenResponse); } catch (MsalServiceException ex) { if (!ex.IsAadUnavailable()) { // Clear failed telemetry data as we've just sent it ... // even if we received an error from the server, // telemetry would have been recorded _serviceBundle.HttpTelemetryManager.ResetPreviousUnsentData(); } if (ex.StatusCode == (int)HttpStatusCode.Unauthorized) { string responseHeader = string.Empty; var isChallenge = _serviceBundle.DeviceAuthManager.TryCreateDeviceAuthChallengeResponseAsync(ex.Headers, builder.Uri, out responseHeader); if (isChallenge) { //Injecting PKeyAuth response here and replaying request to attempt device auth _oAuth2Client.AddHeader("Authorization", responseHeader); return(await _oAuth2Client.GetTokenAsync(builder.Uri, _requestParams.RequestContext, false).ConfigureAwait(false)); } } throw; } finally { _requestInProgress = false; } }
private static MsalServiceException ExtractErrorsFromTheResponse(HttpResponse response, ref bool shouldLogAsError) { // In cases where the end-point is not found (404) response.body will be empty. if (string.IsNullOrWhiteSpace(response.Body)) { return(null); } MsalTokenResponse msalTokenResponse = null; try { msalTokenResponse = JsonHelper.DeserializeFromJson <MsalTokenResponse>(response.Body); } catch (JsonException) { //Throttled responses for client credential flows do not have a parsable response. if ((int)response.StatusCode == 429) { return(MsalServiceExceptionFactory.FromThrottledAuthenticationResponse(response)); } throw; } if (msalTokenResponse?.Error == null) { return(null); } // For device code flow, AuthorizationPending can occur a lot while waiting // for the user to auth via browser and this causes a lot of error noise in the logs. // So suppress this particular case to an Info so we still see the data but don't // log it as an error since it's expected behavior while waiting for the user. if (string.Compare(msalTokenResponse.Error, OAuth2Error.AuthorizationPending, StringComparison.OrdinalIgnoreCase) == 0) { shouldLogAsError = false; } return(MsalServiceExceptionFactory.FromHttpResponse( msalTokenResponse.Error, msalTokenResponse.ErrorDescription, response)); }
private async Task <MsalTokenResponse> SendHttpMessageAsync(string tokenEndpoint) { UriBuilder builder = new UriBuilder(tokenEndpoint); builder.AppendQueryParameters(_requestParams.ExtraQueryParameters); MsalTokenResponse msalTokenResponse = await _oAuth2Client .GetTokenAsync(builder.Uri, _requestParams.RequestContext) .ConfigureAwait(false); if (string.IsNullOrEmpty(msalTokenResponse.Scope)) { msalTokenResponse.Scope = _requestParams.Scope.AsSingleString(); _requestParams.RequestContext.Logger.Info("ScopeSet was missing from the token response, so using developer provided scopes in the result. "); } return(msalTokenResponse); }
internal static MsalTokenResponse CreateFromAppProviderResponse(TokenProviderResult tokenProviderResponse) { ValidateTokenProviderResult(tokenProviderResponse); var response = new MsalTokenResponse { AccessToken = tokenProviderResponse.AccessToken, RefreshToken = null, IdToken = null, TokenType = BrokerResponseConst.Bearer, ExpiresIn = tokenProviderResponse.ExpiresInSeconds, ClientInfo = null, TokenSource = TokenSource.IdentityProvider, TenantId = null //Leaving as null so MSAL can use the original request Tid. This is ok for confidential client scenarios }; response.RefreshIn = tokenProviderResponse.RefreshInSeconds; return(response); }
/// <remarks> /// This method does not belong here - it is more tied to the Android code. However, that code is /// not unit testable, and this one is. /// The values of the JSON response are based on /// https://github.com/AzureAD/microsoft-authentication-library-common-for-android/blob/dev/common/src/main/java/com/microsoft/identity/common/internal/broker/BrokerResult.java /// </remarks> internal static MsalTokenResponse CreateFromAndroidBrokerResponse(string jsonResponse, string correlationId) { JObject authResult = JObject.Parse(jsonResponse); var errorCode = authResult[BrokerResponseConst.BrokerErrorCode]?.ToString(); if (!string.IsNullOrEmpty(errorCode)) { return(new MsalTokenResponse { Error = errorCode, ErrorDescription = authResult[BrokerResponseConst.BrokerErrorMessage]?.ToString(), AuthorityUrl = authResult[BrokerResponseConst.Authority]?.ToString(), TenantId = authResult[BrokerResponseConst.TenantId]?.ToString(), Upn = authResult[BrokerResponseConst.UserName]?.ToString(), AccountUserId = authResult[BrokerResponseConst.LocalAccountId]?.ToString(), }); } MsalTokenResponse msalTokenResponse = new MsalTokenResponse() { AccessToken = authResult[BrokerResponseConst.AccessToken].ToString(), IdToken = authResult[BrokerResponseConst.IdToken].ToString(), CorrelationId = correlationId, // Android response does not expose Correlation ID Scope = authResult[BrokerResponseConst.AndroidScopes].ToString(), // sadly for iOS this is "scope" and for Android "scopes" ExpiresIn = DateTimeHelpers.GetDurationFromNowInSeconds(authResult[BrokerResponseConst.ExpiresOn].ToString()), ExtendedExpiresIn = DateTimeHelpers.GetDurationFromNowInSeconds(authResult[BrokerResponseConst.ExtendedExpiresOn].ToString()), ClientInfo = authResult[BrokerResponseConst.ClientInfo].ToString(), TokenType = authResult[BrokerResponseConst.TokenType]?.ToString() ?? "Bearer", TokenSource = TokenSource.Broker, AuthorityUrl = authResult[BrokerResponseConst.Authority]?.ToString(), TenantId = authResult[BrokerResponseConst.TenantId]?.ToString(), Upn = authResult[BrokerResponseConst.UserName]?.ToString(), AccountUserId = authResult[BrokerResponseConst.LocalAccountId]?.ToString(), }; return(msalTokenResponse); }
public async Task <MsalTokenResponse> SendTokenRequestAsync( IDictionary <string, string> additionalBodyParameters, string scopeOverride = null, string tokenEndpointOverride = null, CancellationToken cancellationToken = default) { string tokenEndpoint = tokenEndpointOverride ?? _requestParams.Endpoints.TokenEndpoint; string scopes = !string.IsNullOrEmpty(scopeOverride) ? scopeOverride : GetDefaultScopes(_requestParams.Scope); AddBodyParamsAndHeaders(additionalBodyParameters, scopes); MsalTokenResponse response = await SendHttpAndClearTelemetryAsync(tokenEndpoint) .ConfigureAwait(false); if (string.IsNullOrEmpty(response.Scope)) { response.Scope = _requestParams.Scope.AsSingleString(); _requestParams.RequestContext.Logger.Info( "ScopeSet was missing from the token response, so using developer provided scopes in the result. "); } if (!string.IsNullOrEmpty(response.TokenType) && !string.Equals( response.TokenType, _requestParams.AuthenticationScheme.AccessTokenType, StringComparison.OrdinalIgnoreCase)) { throw new MsalClientException( MsalError.TokenTypeMismatch, MsalErrorMessage.TokenTypeMismatch( _requestParams.AuthenticationScheme.AccessTokenType, response.TokenType)); } return(response); }
public async Task <MsalTokenResponse> SendTokenRequestAsync( IDictionary <string, string> additionalBodyParameters, string scopeOverride = null, string tokenEndpointOverride = null, CancellationToken cancellationToken = default) { string tokenEndpoint = tokenEndpointOverride ?? _requestParams.Endpoints.TokenEndpoint; string scopes = !string.IsNullOrEmpty(scopeOverride) ? scopeOverride: GetDefaultScopes(_requestParams.Scope); _oAuth2Client.AddBodyParameter(OAuth2Parameter.ClientId, _requestParams.ClientId); _oAuth2Client.AddBodyParameter(OAuth2Parameter.ClientInfo, "1"); #if DESKTOP || NETSTANDARD1_3 || NET_CORE if (_requestParams.ClientCredential != null) { Dictionary <string, string> ccBodyParameters = ClientCredentialHelper.CreateClientCredentialBodyParameters( _requestParams.RequestContext.Logger, _serviceBundle.PlatformProxy.CryptographyManager, _requestParams.ClientCredential, _requestParams.ClientId, _requestParams.Endpoints, _requestParams.SendX5C); foreach (var entry in ccBodyParameters) { _oAuth2Client.AddBodyParameter(entry.Key, entry.Value); } } #endif _oAuth2Client.AddBodyParameter(OAuth2Parameter.Scope, scopes); _oAuth2Client.AddBodyParameter(OAuth2Parameter.Claims, _requestParams.ClaimsAndClientCapabilities); foreach (var kvp in additionalBodyParameters) { _oAuth2Client.AddBodyParameter(kvp.Key, kvp.Value); } foreach (var kvp in _requestParams.AuthenticationScheme.GetTokenRequestParams()) { _oAuth2Client.AddBodyParameter(kvp.Key, kvp.Value); } MsalTokenResponse response = await SendHttpMessageAsync(tokenEndpoint) .ConfigureAwait(false); if (!string.Equals( response.TokenType, _requestParams.AuthenticationScheme.AccessTokenType, StringComparison.OrdinalIgnoreCase)) { throw new MsalClientException( MsalError.TokenTypeMismatch, MsalErrorMessage.TokenTypeMismatch( _requestParams.AuthenticationScheme.AccessTokenType, response.TokenType)); } return(response); }