/// <inheritdoc/>
        public async Task <MexDocument> GetMexDocumentAsync(string federationMetadataUrl, RequestContext requestContext)
        {
            var          uri          = new UriBuilder(federationMetadataUrl);
            HttpResponse httpResponse = await _httpManager.SendGetAsync(uri.Uri, null, requestContext).ConfigureAwait(false);

            if (httpResponse.StatusCode != System.Net.HttpStatusCode.OK)
            {
                string message = string.Format(CultureInfo.CurrentCulture,
                                               MsalErrorMessage.HttpRequestUnsuccessful,
                                               (int)httpResponse.StatusCode, httpResponse.StatusCode);

                throw new MsalServiceException(MsalError.AccessingWsMetadataExchangeFailed, message)
                      {
                          HttpResponse = httpResponse
                      };
            }

            var mexDoc = new MexDocument(httpResponse.Body);

            requestContext.Logger.InfoPii(
                $"MEX document fetched and parsed from '{federationMetadataUrl}'",
                "Fetched and parsed MEX");

            return(mexDoc);
        }
        /// <inheritdoc/>
        public async Task <MexDocument> GetMexDocumentAsync(string federationMetadataUrl, RequestContext requestContext)
        {
            var          uri          = new UriBuilder(federationMetadataUrl);
            HttpResponse httpResponse = await _httpManager.SendGetAsync(uri.Uri, null, requestContext).ConfigureAwait(false);

            if (httpResponse.StatusCode != System.Net.HttpStatusCode.OK)
            {
                throw MsalExceptionFactory.GetServiceException(
                          CoreErrorCodes.AccessingWsMetadataExchangeFailed,
                          string.Format(CultureInfo.CurrentCulture,
                                        CoreErrorMessages.HttpRequestUnsuccessful,
                                        (int)httpResponse.StatusCode, httpResponse.StatusCode),
                          new ExceptionDetail()
                {
                    StatusCode        = (int)httpResponse.StatusCode,
                    ServiceErrorCodes = new[] { httpResponse.StatusCode.ToString() }
                });
            }

            var mexDoc = new MexDocument(httpResponse.Body);

            requestContext.Logger.InfoPii(
                $"MEX document fetched and parsed from '{federationMetadataUrl}'",
                "Fetched and parsed MEX");

            return(mexDoc);
        }
        /// <inheritdoc/>
        public async Task <MexDocument> GetMexDocumentAsync(string federationMetadataUrl, RequestContext requestContext)
        {
            IDictionary <string, string> msalIdParams = MsalIdHelper.GetMsalIdParameters(requestContext.Logger);

            var          uri          = new UriBuilder(federationMetadataUrl);
            HttpResponse httpResponse = await _httpManager.SendGetAsync(
                uri.Uri,
                msalIdParams,
                requestContext.Logger,
                cancellationToken : requestContext.UserCancellationToken).ConfigureAwait(false);

            if (httpResponse.StatusCode != System.Net.HttpStatusCode.OK)
            {
                string message = string.Format(CultureInfo.CurrentCulture,
                                               MsalErrorMessage.HttpRequestUnsuccessful + "See https://aka.ms/msal-net-ropc for more information. ",
                                               (int)httpResponse.StatusCode, httpResponse.StatusCode);

                throw MsalServiceExceptionFactory.FromHttpResponse(
                          MsalError.AccessingWsMetadataExchangeFailed,
                          message,
                          httpResponse);
            }

            var mexDoc = new MexDocument(httpResponse.Body);

            requestContext.Logger.InfoPii(
                $"MEX document fetched and parsed from '{federationMetadataUrl}'",
                "Fetched and parsed MEX");

            return(mexDoc);
        }
Example #4
0
        private async Task <string> GetRegionAsync(RequestContext requestContext)
        {
            string region = Environment.GetEnvironmentVariable(RegionName);

            if (!string.IsNullOrEmpty(region))
            {
                requestContext.Logger.Info($"[Region discovery] Region found in environment variable: {region}.");

                LogTelemetryData(region, RegionSource.EnvVariable, requestContext);

                return(region);
            }

            try
            {
                var headers = new Dictionary <string, string>
                {
                    { "Metadata", "true" }
                };

                HttpResponse response = await _httpManager.SendGetAsync(BuildImdsUri(DefaultApiVersion), headers, requestContext.Logger, retry : false, GetCancellationToken(requestContext.UserCancellationToken)).ConfigureAwait(false);

                // A bad request occurs when the version in the IMDS call is no longer supported.
                if (response.StatusCode == HttpStatusCode.BadRequest)
                {
                    string apiVersion = await GetImdsUriApiVersionAsync(requestContext.Logger, headers, requestContext.UserCancellationToken).ConfigureAwait(false);                                                       // Get the latest version

                    response = await _httpManager.SendGetAsync(BuildImdsUri(apiVersion), headers, requestContext.Logger, retry : false, GetCancellationToken(requestContext.UserCancellationToken)).ConfigureAwait(false); // Call again with updated version
                }

                if (response.StatusCode == HttpStatusCode.OK && !response.Body.IsNullOrEmpty())
                {
                    region = response.Body;
                    LogTelemetryData(region, RegionSource.Imds, requestContext);
                    return(region);
                }

                requestContext.Logger.Info($"[Region discovery] Call to local IMDS failed with status code: {response.StatusCode} or an empty response.");

                throw MsalServiceExceptionFactory.FromImdsResponse(
                          MsalError.RegionDiscoveryFailed,
                          MsalErrorMessage.RegionDiscoveryFailed,
                          response);
            }
            catch (MsalServiceException e)
            {
                if (MsalError.RequestTimeout.Equals(e.ErrorCode))
                {
                    throw new MsalServiceException(MsalError.RegionDiscoveryFailed, MsalErrorMessage.RegionDiscoveryFailedWithTimeout, e);
                }

                throw e;
            }
            catch (Exception e)
            {
                requestContext.Logger.Info("[Region discovery] Call to local IMDS failed. " + e);
                throw new MsalServiceException(MsalError.RegionDiscoveryFailed, MsalErrorMessage.RegionDiscoveryFailed, e);
            }
        }
        private async Task <RegionInfo> DiscoverAsync(ICoreLogger logger, CancellationToken requestCancellationToken)
        {
            string region = Environment.GetEnvironmentVariable("REGION_NAME");

            if (ValidateRegion(region, "REGION_NAME env variable", logger)) // this is just to validate the region string
            {
                logger.Info($"[Region discovery] Region found in environment variable: {region}.");
                return(new RegionInfo(region, RegionAutodetectionSource.EnvVariable));
            }

            try
            {
                var headers = new Dictionary <string, string>
                {
                    { "Metadata", "true" }
                };

                Uri imdsUri = BuildImdsUri(DefaultApiVersion);

                HttpResponse response = await _httpManager.SendGetAsync(imdsUri, headers, logger, retry : false, GetCancellationToken(requestCancellationToken))
                                        .ConfigureAwait(false);

                // A bad request occurs when the version in the IMDS call is no longer supported.
                if (response.StatusCode == HttpStatusCode.BadRequest)
                {
                    string apiVersion = await GetImdsUriApiVersionAsync(logger, headers, requestCancellationToken).ConfigureAwait(false); // Get the latest version

                    imdsUri  = BuildImdsUri(apiVersion);
                    response = await _httpManager.SendGetAsync(BuildImdsUri(apiVersion), headers, logger, retry : false, GetCancellationToken(requestCancellationToken))
                               .ConfigureAwait(false); // Call again with updated version
                }

                if (response.StatusCode == HttpStatusCode.OK && !response.Body.IsNullOrEmpty())
                {
                    region = response.Body;

                    if (ValidateRegion(region, $"IMDS call to {imdsUri.AbsoluteUri}", logger))
                    {
                        logger.Info($"[Region discovery] Call to local IMDS succeeded. Region: {region}.");
                        return(new RegionInfo(region, RegionAutodetectionSource.Imds));
                    }
                }
                else
                {
                    logger.Warning($"[Region discovery] Call to local IMDS failed with status code {response.StatusCode} or an empty response.");
                }
            }
            catch (Exception e)
            {
                if (e is MsalServiceException msalEx && MsalError.RequestTimeout.Equals(msalEx?.ErrorCode))
                {
                    logger.Warning($"[Region discovery] Call to local IMDS timed out after {_imdsCallTimeoutMs}.");
                }
        private async Task SendEmailVerificationCodeAsync()
        {
            var authorizationUri = CreateAuthorizationUri(true, true);
            var uiEvent          = new UiEvent();

            using (ServiceBundle.TelemetryManager.CreateTelemetryHelper(
                       AuthenticationRequestParameters.RequestContext.TelemetryRequestId,
                       AuthenticationRequestParameters.ClientId,
                       uiEvent))
            {
                var requestContext = AuthenticationRequestParameters.RequestContext;
                var response       = await _httpManager.SendGetAsync(authorizationUri, new Dictionary <string, string>(), requestContext).ConfigureAwait(false);

                if (response != null &&
                    response.StatusCode == HttpStatusCode.OK &&
                    !string.IsNullOrEmpty(response.Body))
                {
                    _csrf       = GetField(response.Body, "csrf");
                    _transId    = GetField(response.Body, "transId");
                    _policy     = GetField(response.Body, "policy"); // B2C_1_password_reset
                    _pageViewId = GetField(response.Body, "pageViewId");
                    var verifyEmailUri = CreateResetPasswordUri(_transId, _policy);
                    var postData       = new Dictionary <string, string>
                    {
                        ["request_type"] = "VERIFICATION_REQUEST",
                        ["claim_id"]     = "email",
                        ["claim_value"]  = Email
                    };
                    var response2 = await _httpManager.SendPostAsync(verifyEmailUri, new Dictionary <string, string> {
                        ["X-CSRF-TOKEN"] = _csrf
                    }, postData, requestContext).ConfigureAwait(false);

                    if (response2 != null &&
                        response2.StatusCode == HttpStatusCode.OK)
                    {
                        AuthorizationResult = new AuthorizationResult(AuthorizationStatus.Success);
                    }
                    else
                    {
                        AuthorizationResult = new AuthorizationResult(AuthorizationStatus.ErrorHttp);
                    }
                }
                else
                {
                    AuthorizationResult = new AuthorizationResult(AuthorizationStatus.ErrorHttp);
                }
                uiEvent.UserCancelled = AuthorizationResult.Status == AuthorizationStatus.UserCancel;
                uiEvent.AccessDenied  = AuthorizationResult.Status == AuthorizationStatus.ProtocolError;
            }
        }
        internal async Task <T> ExecuteRequestAsync <T>(Uri endPoint, HttpMethod method, RequestContext requestContext, bool expectErrorsOn200OK = false)
        {
            bool addCorrelationId = requestContext != null && !string.IsNullOrEmpty(requestContext.Logger.CorrelationId.ToString());

            AddCommonHeaders(requestContext, addCorrelationId);

            HttpResponse response    = null;
            Uri          endpointUri = CreateFullEndpointUri(endPoint);
            var          httpEvent   = new HttpEvent(requestContext.CorrelationId.AsMatsCorrelationId())
            {
                HttpPath    = endpointUri,
                QueryParams = endpointUri.Query
            };

            using (_telemetryManager.CreateTelemetryHelper(httpEvent))
            {
                if (method == HttpMethod.Post)
                {
                    response = await _httpManager.SendPostAsync(endpointUri, _headers, _bodyParameters, requestContext.Logger)
                               .ConfigureAwait(false);
                }
                else
                {
                    response = await _httpManager.SendGetAsync(endpointUri, _headers, requestContext.Logger).ConfigureAwait(false);
                }

                DecorateHttpEvent(method, requestContext, response, httpEvent);

                if (response.StatusCode != HttpStatusCode.OK || expectErrorsOn200OK)
                {
                    try
                    {
                        httpEvent.OauthErrorCode = MsalError.UnknownError;
                        // In cases where the end-point is not found (404) response.body will be empty.
                        // CreateResponse handles throwing errors - in the case of HttpStatusCode <> and ErrorResponse will be created.
                        if (!string.IsNullOrWhiteSpace(response.Body))
                        {
                            var msalTokenResponse = JsonHelper.DeserializeFromJson <MsalTokenResponse>(response.Body);
                            if (msalTokenResponse != null)
                            {
                                httpEvent.OauthErrorCode = msalTokenResponse?.Error;
                            }

                            if (response.StatusCode == HttpStatusCode.OK &&
                                expectErrorsOn200OK &&
                                !string.IsNullOrEmpty(msalTokenResponse.Error))
                            {
                                ThrowServerException(response, requestContext);
                            }
                        }
                    }
                    catch (JsonException) // in the rare case we get an error response we cannot deserialize
                    {
                        // CreateErrorResponse does the same validation. Will be logging the error there.
                    }
                }
            }

            return(CreateResponse <T>(response, requestContext, addCorrelationId));
        }
        private async Task <string> GetRegionAsync(ICoreLogger logger)
        {
            if (!Environment.GetEnvironmentVariable(RegionName).IsNullOrEmpty())
            {
                logger.Info($"[Region discovery] Region: {Environment.GetEnvironmentVariable(RegionName)}");
                return(Environment.GetEnvironmentVariable(RegionName));
            }

            try
            {
                HttpResponse response = await _httpManager.SendGetAsync(_ImdsUri, Headers, logger).ConfigureAwait(false);

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    throw new MsalClientException(
                              MsalError.RegionDiscoveryFailed,
                              MsalErrorMessage.RegionDiscoveryFailed);
                }

                LocalImdsResponse localImdsResponse = JsonHelper.DeserializeFromJson <LocalImdsResponse>(response.Body);

                logger.Info($"[Region discovery] Call to local IMDS returned region: {localImdsResponse.location}");
                return(localImdsResponse.location);
            }
            catch (Exception e)
            {
                logger.Info("[Region discovery] Call to local imds failed." + e.Message);
                throw;
            }
        }
        internal async Task <T> ExecuteRequestAsync <T>(Uri endPoint, HttpMethod method, RequestContext requestContext)
        {
            HttpResponse response    = null;
            Uri          endpointUri = CreateFullEndpointUri(endPoint);

            if (method == HttpMethod.Post)
            {
                response = await _httpManager.SendPostAsync(endpointUri, _headers, _bodyParameters, requestContext)
                           .ConfigureAwait(false);
            }
            else
            {
                response = await _httpManager.SendGetAsync(endpointUri, _headers, requestContext).ConfigureAwait(false);
            }

            return(CreateResponse <T>(response, requestContext));
        }
Example #10
0
        internal async Task <T> ExecuteRequestAsync <T>(Uri endPoint, HttpMethod method, RequestContext requestContext)
        {
            bool addCorrelationId =
                requestContext != null && !string.IsNullOrEmpty(requestContext.Logger.CorrelationId.ToString());

            if (addCorrelationId)
            {
                _headers.Add(OAuth2Header.CorrelationId, requestContext.Logger.CorrelationId.ToString());
                _headers.Add(OAuth2Header.RequestCorrelationIdInResponse, "true");
            }

            HttpResponse response    = null;
            var          endpointUri = CreateFullEndpointUri(endPoint);
            var          httpEvent   = new HttpEvent()
            {
                HttpPath    = endpointUri,
                QueryParams = endpointUri.Query
            };

            using (_telemetryManager.CreateTelemetryHelper(requestContext.TelemetryRequestId, requestContext.ClientId, httpEvent))
            {
                if (method == HttpMethod.Post)
                {
                    response = await _httpManager.SendPostAsync(endpointUri, _headers, _bodyParameters, requestContext)
                               .ConfigureAwait(false);
                }
                else
                {
                    response = await _httpManager.SendGetAsync(endpointUri, _headers, requestContext).ConfigureAwait(false);
                }

                httpEvent.HttpResponseStatus = (int)response.StatusCode;
                httpEvent.UserAgent          = response.UserAgent;
                httpEvent.HttpMethod         = method.Method;

                IDictionary <string, string> headersAsDictionary = response.HeadersAsDictionary;
                if (headersAsDictionary.ContainsKey("x-ms-request-id") &&
                    headersAsDictionary["x-ms-request-id"] != null)
                {
                    httpEvent.RequestIdHeader = headersAsDictionary["x-ms-request-id"];
                }

                if (headersAsDictionary.ContainsKey("x-ms-clitelem") &&
                    headersAsDictionary["x-ms-clitelem"] != null)
                {
                    XmsCliTelemInfo xmsCliTeleminfo = new XmsCliTelemInfoParser().ParseXMsTelemHeader(headersAsDictionary["x-ms-clitelem"], requestContext);
                    if (xmsCliTeleminfo != null)
                    {
                        httpEvent.TokenAge           = xmsCliTeleminfo.TokenAge;
                        httpEvent.SpeInfo            = xmsCliTeleminfo.SpeInfo;
                        httpEvent.ServerErrorCode    = xmsCliTeleminfo.ServerErrorCode;
                        httpEvent.ServerSubErrorCode = xmsCliTeleminfo.ServerSubErrorCode;
                    }
                }

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    try
                    {
                        httpEvent.OauthErrorCode = JsonHelper.DeserializeFromJson <MsalTokenResponse>(response.Body).Error;
                    }
                    catch (SerializationException) // in the rare case we get an error response we cannot deserialize
                    {
                        throw MsalExceptionFactory.GetServiceException(
                                  CoreErrorCodes.NonParsableOAuthError,
                                  CoreErrorMessages.NonParsableOAuthError,
                                  response);
                    }
                }
            }

            return(CreateResponse <T>(response, requestContext, addCorrelationId));
        }
        private async Task <string> GetRegionAsync(RequestContext requestContext)
        {
            ICoreLogger logger = requestContext.Logger;
            string      region = Environment.GetEnvironmentVariable(RegionName);

            if (!string.IsNullOrEmpty(region))
            {
                logger.Info($"[Region discovery] Region found in environment variable: {region}.");

                LogTelemetryData(region, RegionSource.EnvVariable, requestContext);

                return(region);
            }

            try
            {
                var headers = new Dictionary <string, string>
                {
                    { "Metadata", "true" }
                };

                HttpResponse response = await _httpManager.SendGetAsync(BuildImdsUri(DefaultApiVersion), headers, logger).ConfigureAwait(false);

                // A bad request occurs when the version in the IMDS call is no longer supported.
                if (response.StatusCode == HttpStatusCode.BadRequest)
                {
                    string apiVersion = await GetImdsUriApiVersionAsync(logger, headers).ConfigureAwait(false);                  // Get the latest version

                    response = await _httpManager.SendGetAsync(BuildImdsUri(apiVersion), headers, logger).ConfigureAwait(false); // Call again with updated version
                }

                if (response.StatusCode == HttpStatusCode.OK && !response.Body.IsNullOrEmpty())
                {
                    LocalImdsResponse localImdsResponse = JsonHelper.DeserializeFromJson <LocalImdsResponse>(response.Body);

                    if (localImdsResponse != null && !localImdsResponse.location.IsNullOrEmpty())
                    {
                        logger.Info($"[Region discovery] Call to local IMDS returned region: {localImdsResponse.location}");
                        LogTelemetryData(localImdsResponse.location, RegionSource.Imds, requestContext);

                        return(localImdsResponse.location);
                    }
                }

                logger.Info($"[Region discovery] Call to local IMDS failed with status code: {response.StatusCode} or an empty response.");

                throw MsalServiceExceptionFactory.FromImdsResponse(
                          MsalError.RegionDiscoveryFailed,
                          MsalErrorMessage.RegionDiscoveryFailed,
                          response);
            }
            catch (MsalServiceException)
            {
                throw;
            }
            catch (Exception e)
            {
                logger.Info("[Region discovery] Call to local imds failed." + e.Message);
                throw new MsalServiceException(MsalError.RegionDiscoveryFailed, MsalErrorMessage.RegionDiscoveryFailed);
            }
        }
Example #12
0
        internal async Task <T> ExecuteRequestAsync <T>(
            Uri endPoint,
            HttpMethod method,
            RequestContext requestContext,
            bool expectErrorsOn200OK = false,
            bool addCommonHeaders    = true,
            Func <OnBeforeTokenRequestData, Task> onBeforePostRequestData = null)
        {
            //Requests that are replayed by PKeyAuth do not need to have headers added because they already exist
            if (addCommonHeaders)
            {
                AddCommonHeaders(requestContext);
            }

            HttpResponse response    = null;
            Uri          endpointUri = AddExtraQueryParams(endPoint);

            using (requestContext.Logger.LogBlockDuration($"[Oauth2Client] Sending {method} request "))
            {
                if (method == HttpMethod.Post)
                {
                    if (onBeforePostRequestData != null)
                    {
                        var requestData = new OnBeforeTokenRequestData(_bodyParameters, _headers, endpointUri, requestContext.UserCancellationToken);
                        await onBeforePostRequestData(requestData).ConfigureAwait(false);
                    }

                    response = await _httpManager.SendPostAsync(
                        endpointUri,
                        _headers,
                        _bodyParameters,
                        requestContext.Logger,
                        requestContext.UserCancellationToken)
                               .ConfigureAwait(false);
                }
                else
                {
                    response = await _httpManager.SendGetAsync(
                        endpointUri,
                        _headers,
                        requestContext.Logger,
                        cancellationToken : requestContext.UserCancellationToken)
                               .ConfigureAwait(false);
                }
            }

            if (requestContext.ApiEvent != null)
            {
                requestContext.ApiEvent.DurationInHttpInMs += _httpManager.LastRequestDurationInMs;
            }

            if (response.StatusCode != HttpStatusCode.OK || expectErrorsOn200OK)
            {
                requestContext.Logger.Verbose("[Oauth2Client] Processing error response ");

                try
                {
                    // In cases where the end-point is not found (404) response.body will be empty.
                    // CreateResponse handles throwing errors - in the case of HttpStatusCode <> and ErrorResponse will be created.
                    if (!string.IsNullOrWhiteSpace(response.Body))
                    {
                        var msalTokenResponse = JsonHelper.DeserializeFromJson <MsalTokenResponse>(response.Body);

                        if (response.StatusCode == HttpStatusCode.OK &&
                            expectErrorsOn200OK &&
                            !string.IsNullOrEmpty(msalTokenResponse?.Error))
                        {
                            ThrowServerException(response, requestContext);
                        }
                    }
                }
                catch (JsonException) // in the rare case we get an error response we cannot deserialize
                {
                    // CreateErrorResponse does the same validation. Will be logging the error there.
                }
            }

            return(CreateResponse <T>(response, requestContext));
        }
Example #13
0
        internal async Task <T> ExecuteRequestAsync <T>(Uri endPoint, HttpMethod method, RequestContext requestContext)
        {
            bool addCorrelationId = requestContext != null && !string.IsNullOrEmpty(requestContext.Logger.CorrelationId.ToString());

            if (addCorrelationId)
            {
                _headers.Add(OAuth2Header.CorrelationId, requestContext.Logger.CorrelationId.ToString());
                _headers.Add(OAuth2Header.RequestCorrelationIdInResponse, "true");
            }

            if (!string.IsNullOrWhiteSpace(requestContext.Logger.ClientName))
            {
                _headers.Add(OAuth2Header.AppName, requestContext.Logger.ClientName);
            }

            if (!string.IsNullOrWhiteSpace(requestContext.Logger.ClientVersion))
            {
                _headers.Add(OAuth2Header.AppVer, requestContext.Logger.ClientVersion);
            }

            HttpResponse response    = null;
            Uri          endpointUri = CreateFullEndpointUri(endPoint);
            var          httpEvent   = new HttpEvent(requestContext.TelemetryCorrelationId)
            {
                HttpPath    = endpointUri,
                QueryParams = endpointUri.Query
            };

            using (_telemetryManager.CreateTelemetryHelper(httpEvent))
            {
                if (method == HttpMethod.Post)
                {
                    response = await _httpManager.SendPostAsync(endpointUri, _headers, _bodyParameters, requestContext.Logger)
                               .ConfigureAwait(false);
                }
                else
                {
                    response = await _httpManager.SendGetAsync(endpointUri, _headers, requestContext.Logger).ConfigureAwait(false);
                }

                httpEvent.HttpResponseStatus = (int)response.StatusCode;
                httpEvent.UserAgent          = response.UserAgent;
                httpEvent.HttpMethod         = method.Method;

                IDictionary <string, string> headersAsDictionary = response.HeadersAsDictionary;
                if (headersAsDictionary.ContainsKey("x-ms-request-id") &&
                    headersAsDictionary["x-ms-request-id"] != null)
                {
                    httpEvent.RequestIdHeader = headersAsDictionary["x-ms-request-id"];
                }

                if (headersAsDictionary.ContainsKey("x-ms-clitelem") &&
                    headersAsDictionary["x-ms-clitelem"] != null)
                {
                    XmsCliTelemInfo xmsCliTeleminfo = new XmsCliTelemInfoParser().ParseXMsTelemHeader(
                        headersAsDictionary["x-ms-clitelem"],
                        requestContext.Logger);

                    if (xmsCliTeleminfo != null)
                    {
                        httpEvent.TokenAge           = xmsCliTeleminfo.TokenAge;
                        httpEvent.SpeInfo            = xmsCliTeleminfo.SpeInfo;
                        httpEvent.ServerErrorCode    = xmsCliTeleminfo.ServerErrorCode;
                        httpEvent.ServerSubErrorCode = xmsCliTeleminfo.ServerSubErrorCode;
                    }
                }

                if (response.StatusCode != HttpStatusCode.OK)
                {
                    try
                    {
                        httpEvent.OauthErrorCode = MsalError.UnknownError;
                        // In cases where the end-point is not found (404) response.body will be empty.
                        // CreateResponse handles throwing errors - in the case of HttpStatusCode <> and ErrorResponse will be created.
                        if (!string.IsNullOrWhiteSpace(response.Body))
                        {
                            var msalTokenResponse = JsonHelper.DeserializeFromJson <MsalTokenResponse>(response.Body);
                            if (msalTokenResponse != null)
                            {
                                httpEvent.OauthErrorCode = msalTokenResponse.Error;
                            }
                        }
                    }
                    catch (SerializationException) // in the rare case we get an error response we cannot deserialize
                    {
                        // CreateErrorResponse does the same validation. Will be logging the error there.
                    }
                }
            }

            return(CreateResponse <T>(response, requestContext, addCorrelationId));
        }
        internal async Task <T> ExecuteRequestAsync <T>(Uri endPoint, HttpMethod method, RequestContext requestContext, bool expectErrorsOn200OK = false, bool addCommonHeaders = true)
        {
            //Requests that are replayed by PKeyAuth do not need to have headers added because they already exist
            if (addCommonHeaders)
            {
                AddCommonHeaders(requestContext);
            }

            HttpResponse response    = null;
            Uri          endpointUri = AddExtraQueryParams(endPoint);
            var          httpEvent   = new HttpEvent(requestContext.CorrelationId.AsMatsCorrelationId())
            {
                HttpPath    = endpointUri,
                QueryParams = endpointUri.Query
            };

            using (requestContext.CreateTelemetryHelper(httpEvent))
            {
                if (method == HttpMethod.Post)
                {
                    response = await _httpManager.SendPostAsync(endpointUri, _headers, _bodyParameters, requestContext.Logger)
                               .ConfigureAwait(false);
                }
                else
                {
                    response = await _httpManager.SendGetAsync(
                        endpointUri,
                        _headers,
                        requestContext.Logger,
                        cancellationToken : requestContext.UserCancellationToken).ConfigureAwait(false);
                }

                if (requestContext.ApiEvent != null)
                {
                    requestContext.ApiEvent.DurationInHttpInMs += _httpManager.LastRequestDurationInMs;
                }

                DecorateHttpEvent(method, requestContext, response, httpEvent);

                if (response.StatusCode != HttpStatusCode.OK || expectErrorsOn200OK)
                {
                    try
                    {
                        httpEvent.OauthErrorCode = MsalError.UnknownError;
                        // In cases where the end-point is not found (404) response.body will be empty.
                        // CreateResponse handles throwing errors - in the case of HttpStatusCode <> and ErrorResponse will be created.
                        if (!string.IsNullOrWhiteSpace(response.Body))
                        {
                            var msalTokenResponse = JsonHelper.DeserializeFromJson <MsalTokenResponse>(response.Body);
                            if (msalTokenResponse != null)
                            {
                                httpEvent.OauthErrorCode = msalTokenResponse?.Error;
                            }

                            if (response.StatusCode == HttpStatusCode.OK &&
                                expectErrorsOn200OK &&
                                !string.IsNullOrEmpty(msalTokenResponse?.Error))
                            {
                                ThrowServerException(response, requestContext);
                            }
                        }
                    }
                    catch (JsonException) // in the rare case we get an error response we cannot deserialize
                    {
                        // CreateErrorResponse does the same validation. Will be logging the error there.
                    }
                }
            }

            return(CreateResponse <T>(response, requestContext));
        }
Example #15
0
        internal protected override async Task AcquireAuthorizationAsync()
        {
            var authorizationUri = CreateAuthorizationUri(true, true);

            var uiEvent = new UiEvent();

            using (ServiceBundle.TelemetryManager.CreateTelemetryHelper(
                       AuthenticationRequestParameters.RequestContext.TelemetryRequestId,
                       AuthenticationRequestParameters.ClientId,
                       uiEvent))
            {
                var requestContext = AuthenticationRequestParameters.RequestContext;
                var response       = await _httpManager.SendGetAsync(authorizationUri, new Dictionary <string, string>(), requestContext).ConfigureAwait(false);

                if (response != null &&
                    response.StatusCode == HttpStatusCode.OK &&
                    !string.IsNullOrEmpty(response.Body))
                {
                    var csrf       = GetField(response.Body, "csrf");
                    var transId    = GetField(response.Body, "transId");
                    var policy     = GetField(response.Body, "policy");
                    var pageViewId = GetField(response.Body, "pageViewId");
                    var api        = GetField(response.Body, "api");
                    var logonUri   = CreateLogonUri(transId, policy);
                    var postData   = new Dictionary <string, string>
                    {
                        ["request_type"]    = "RESPONSE",
                        ["logonIdentifier"] = Username,
                        ["password"]        = Password
                    };
                    var response2 = await _httpManager.SendPostAsync(logonUri, new Dictionary <string, string> {
                        ["X-CSRF-TOKEN"] = csrf
                    }, postData, requestContext).ConfigureAwait(false);

                    if (response2 != null &&
                        response2.StatusCode == HttpStatusCode.OK)
                    {
                        var confirmedUri = CreateConfirmedUri(csrf, transId, policy, pageViewId, api);
                        var response3    = await _httpManager.SendGetAsync(confirmedUri, new Dictionary <string, string> {
                            ["x-ms-cpim-pageviewid"] = pageViewId
                        }, requestContext).ConfigureAwait(false);

                        if (response3 != null &&
                            (response3.StatusCode == HttpStatusCode.Found ||
                             response3.StatusCode == HttpStatusCode.OK))
                        {
                            AuthorizationResult = new AuthorizationResult(AuthorizationStatus.Success, response3.Headers?.Location);
                        }
                        else
                        {
                            AuthorizationResult = new AuthorizationResult(AuthorizationStatus.ErrorHttp);
                        }
                    }
                    else
                    {
                        AuthorizationResult = new AuthorizationResult(AuthorizationStatus.ErrorHttp);
                    }
                }
                else
                {
                    AuthorizationResult = new AuthorizationResult(AuthorizationStatus.ErrorHttp);
                }
                uiEvent.UserCancelled = AuthorizationResult.Status == AuthorizationStatus.UserCancel;
                uiEvent.AccessDenied  = AuthorizationResult.Status == AuthorizationStatus.ProtocolError;
            }
        }