Пример #1
0
        internal void ExceptionHandler(Exception exception)
        {
            var _exception = exception.GetBaseException() as ODataErrorException;
            AdalServiceException _serviceException = exception.GetBaseException() as AdalServiceException;

            var _innerException = _exception.InnerException;

            if (_exception != null)
            {
                throw new TIPException(
                          new Error
                {
                    Code    = _exception.Error.ErrorCode,
                    Message = _exception.Message,
                },
                          _exception.InnerException);
            }

            throw new TIPException(
                      new Error
            {
                Code    = _exception.Error.ErrorCode,
                Message = _exception.Message,
            }, _exception.InnerException);
        }
        private RetryParams ComputeAdalRetry(Exception ex)
        {
            if (ex is AdalServiceException)
            {
                AdalServiceException adalServiceException = (AdalServiceException)ex;

                // When the Service Token Server (STS) is too busy because of “too many requests”,
                // it returns an HTTP error 429 with a hint about when you can try again (Retry-After response field) as a delay in seconds
                if (adalServiceException.ErrorCode == MsalTemporarilyUnavailable || adalServiceException.StatusCode == 429)
                {
                    RetryConditionHeaderValue retryAfter = adalServiceException.Headers.RetryAfter;

                    // Depending on the service, the recommended retry time may be in retryAfter.Delta or retryAfter.Date. Check both.
                    if (retryAfter != null && retryAfter.Delta.HasValue)
                    {
                        return(new RetryParams(retryAfter.Delta.Value));
                    }
                    else if (retryAfter != null && retryAfter.Date.HasValue)
                    {
                        return(new RetryParams(retryAfter.Date.Value.Offset));
                    }

                    // We got a 429 but didn't get a specific back-off time. Use the default
                    return(RetryParams.DefaultBackOff(0));
                }
            }

            return(RetryParams.DefaultBackOff(0));
        }
Пример #3
0
        public string Authenticate(Uri requestUri, Uri callbackUri)
        {
            string key   = requestUri.AbsoluteUri + callbackUri.AbsoluteUri;
            string value = null;

            if (IOMap.ContainsKey(key))
            {
                value = IOMap[key];
                if (value[0] == 'P')
                {
                    return(value.Substring(1));
                }

                if (value[0] == 'A')
                {
                    string [] segments = value.Substring(1).Split(new [] { Delimiter }, StringSplitOptions.RemoveEmptyEntries);
                    throw new AdalServiceException(errorCode: segments[0], message: segments[1])
                          {
                              StatusCode = int.Parse(segments[2])
                          };
                }
            }

            try
            {
                string result = this.internalWebUI.Authenticate(requestUri, callbackUri);
                value = 'P' + result;
                return(result);
            }
            catch (AdalException ex)
            {
                AdalServiceException serviceException = ex as AdalServiceException;
                if (serviceException != null && serviceException.StatusCode == 503)
                {
                    value = null;
                }
                else
                {
                    value = 'A' + string.Format("{0}{1}{2}{3}{4}", ex.ErrorCode, Delimiter, ex.Message, Delimiter,
                                                (serviceException != null) ? serviceException.StatusCode : 0);
                }

                throw;
            }
            finally
            {
                if (value != null)
                {
                    IOMap.Add(key, value);
                }
            }
        }
Пример #4
0
        private bool IsAdalServiceUnavailable(Exception ex)
        {
            AdalServiceException adalServiceException = ex as AdalServiceException;

            if (adalServiceException == null)
            {
                return(false);
            }

            // When the Service Token Server (STS) is too busy because of “too many requests”,
            // it returns an HTTP error 429
            return(adalServiceException.ErrorCode == AdalError.ServiceUnavailable || adalServiceException.StatusCode == 429);
        }
        private static bool IsAdalServiceUnavailable(Exception ex)
        {
            AdalServiceException adalServiceException = ex as AdalServiceException;

            if (adalServiceException == null)
            {
                return(false);
            }

            // When the Service Token Server (STS) is too busy because of “too many requests”,
            // it returns an HTTP error 429
            return(adalServiceException.ErrorCode == MsalTemporarilyUnavailable || adalServiceException.StatusCode == HttpTooManyRequests);
        }
Пример #6
0
        public void WsTrustRequestAcceptedByService()
        {
            AuthenticationContext context = new AuthenticationContext("https://login.microsoftonline.com/common", true);

            AdalServiceException ex = AssertException.TaskThrows <AdalServiceException>(() =>
                                                                                        context.AcquireTokenAsync("https://graph.windows.net", "unknown-client-F1E93291-6F42-453A-866F-C2F672F283BD", new UserCredential("*****@*****.**")));

            Debug.WriteLine($"Error code: {ex.ErrorCode}");
            Debug.WriteLine($"Error message: {ex.Message}");

            // If the request is not well-formed then the error message returned will be something like
            //  "Federated service at https://msft.sts.microsoft.com/adfs/services/trust/13/windowstransport returned error: ID3035: The request was not valid or is malformed."
            Assert.IsFalse(ex.Message.Contains("ID3035"), "Not expecting the request to be rejected as invalid");
        }
Пример #7
0
    private void HandleAdalServiceException(AdalServiceException e, IAADLogger Logger)
    {
        // Exception: AdalServiceException
        // Represents an error produced by the STS.
        // e.ErrorCode contains the error code and description, which can be used for debugging.
        // NOTE: Do not code a dependency on the contents of the error description, as it can change over time.

        // Design time consideration: Certain errors may be caused at development and exposed through this exception.
        // Looking inside the description will give more guidance on resolving the specific issue.

        // Action: Case 1: Non-Retryable
        // Do not perform an immediate retry. Only retry after user action.
        // Example Errors: default case
        Logger.Log($"AdalServiceException Message: {e.Message}");
        Logger.Log($"AdalServiceException Status Code: {e.StatusCode.ToString()}");
    }
Пример #8
0
        private async Task <AuthenticationResultEx> RefreshAccessTokenAsync(AuthenticationResultEx result)
        {
            AuthenticationResultEx newResultEx = null;

            if (this.Resource != null)
            {
                var msg = "Refreshing access token...";
                CallState.Logger.Verbose(this.CallState, msg);
                CallState.Logger.VerbosePii(this.CallState, msg);

                try
                {
                    newResultEx = await this.SendTokenRequestByRefreshTokenAsync(result.RefreshToken)
                                  .ConfigureAwait(false);

                    this.Authenticator.UpdateTenantId(result.Result.TenantId);

                    newResultEx.Result.Authority = Authenticator.Authority;

                    if (newResultEx.Result.IdToken == null)
                    {
                        // If Id token is not returned by token endpoint when refresh token is redeemed, we should copy tenant and user information from the cached token.
                        newResultEx.Result.UpdateTenantAndUserInfo(result.Result.TenantId, result.Result.IdToken,
                                                                   result.Result.UserInfo);
                    }
                }
                catch (AdalException ex)
                {
                    AdalServiceException serviceException = ex as AdalServiceException;
                    if (serviceException != null && serviceException.ErrorCode == "invalid_request")
                    {
                        throw new AdalServiceException(
                                  AdalError.FailedToRefreshToken,
                                  AdalErrorMessage.FailedToRefreshToken + ". " + serviceException.Message,
                                  serviceException.ServiceErrorCodes,
                                  serviceException);
                    }
                    newResultEx = new AuthenticationResultEx {
                        Exception = ex
                    };
                }
            }

            return(newResultEx);
        }
Пример #9
0
        public void NegativeDeviceCodeTest()
        {
            MockHttpMessageHandler mockMessageHandler = new MockHttpMessageHandler(TestConstants.DefaultAuthorityHomeTenant)
            {
                Method          = HttpMethod.Get,
                Url             = TestConstants.DefaultAuthorityHomeTenant + "oauth2/devicecode",
                ResponseMessage = MockHelpers.CreateDeviceCodeErrorResponse()
            };

            HttpMessageHandlerFactory.AddMockHandler(mockMessageHandler);

            TokenCache            cache = new TokenCache();
            AuthenticationContext ctx   = new AuthenticationContext(TestConstants.DefaultAuthorityHomeTenant, cache);
            DeviceCodeResult      dcr;
            AdalServiceException  ex = AssertException.TaskThrows <AdalServiceException>(async() => dcr = await ctx.AcquireDeviceCodeAsync("some-resource", "some-client").ConfigureAwait(false));

            Assert.IsTrue(ex.Message.Contains("some error message"));
        }
Пример #10
0
        public async Task NegativeDeviceCodeTimeoutTestAsync()
        {
            MockHttpMessageHandler mockMessageHandler = new MockHttpMessageHandler(TestConstants.DefaultAuthorityHomeTenant)
            {
                Method          = HttpMethod.Get,
                Url             = TestConstants.DefaultAuthorityHomeTenant + "oauth2/devicecode",
                ResponseMessage = MockHelpers.CreateSuccessDeviceCodeResponseMessage("1")
            };

            HttpMessageHandlerFactory.AddMockHandler(mockMessageHandler);

            mockMessageHandler = new MockHttpMessageHandler(TestConstants.DefaultAuthorityHomeTenant)
            {
                Method          = HttpMethod.Post,
                Url             = TestConstants.DefaultAuthorityHomeTenant + "oauth2/token",
                ResponseMessage = MockHelpers.CreateFailureResponseMessage("{\"error\":\"authorization_pending\"," +
                                                                           "\"error_description\":\"AADSTS70016: Pending end-user authorization." +
                                                                           "\\r\\nTrace ID: f6c2c73f-a21d-474e-a71f-d8b121a58205\\r\\nCorrelation ID: " +
                                                                           "36fe3e82-442f-4418-b9f4-9f4b9295831d\\r\\nTimestamp: 2015-09-24 19:51:51Z\"," +
                                                                           "\"error_codes\":[70016],\"timestamp\":\"2015-09-24 19:51:51Z\",\"trace_id\":" +
                                                                           "\"f6c2c73f-a21d-474e-a71f-d8b121a58205\",\"correlation_id\":" +
                                                                           "\"36fe3e82-442f-4418-b9f4-9f4b9295831d\"}")
            };

            HttpMessageHandlerFactory.AddMockHandler(mockMessageHandler);

            mockMessageHandler = new MockHttpMessageHandler(TestConstants.DefaultAuthorityHomeTenant)
            {
                Method          = HttpMethod.Post,
                Url             = TestConstants.DefaultAuthorityHomeTenant + "oauth2/token",
                ResponseMessage = MockHelpers.CreateDeviceCodeExpirationErrorResponse()
            };
            HttpMessageHandlerFactory.AddMockHandler(mockMessageHandler);

            TokenCache            cache = new TokenCache();
            AuthenticationContext ctx   = new AuthenticationContext(TestConstants.DefaultAuthorityHomeTenant, cache);
            DeviceCodeResult      dcr   = await ctx.AcquireDeviceCodeAsync("some resource", "some authority").ConfigureAwait(false);

            Assert.IsNotNull(dcr);
            AuthenticationResult result;
            AdalServiceException ex = AssertException.TaskThrows <AdalServiceException>(async() => result = await ctx.AcquireTokenByDeviceCodeAsync(dcr).ConfigureAwait(false));

            Assert.IsTrue(ex.Message.Contains("Verification code expired"));
        }
        private async Task <T> GetResponseAsync <T>(bool respondToDeviceAuthChallenge)
        {
            T typedResponse = default(T);
            IHttpWebResponse response;

            try
            {
                IDictionary <string, string> adalIdHeaders = AdalIdHelper.GetAdalIdParameters();
                foreach (KeyValuePair <string, string> kvp in adalIdHeaders)
                {
                    this.Client.Headers[kvp.Key] = kvp.Value;
                }
                //add pkeyauth header
                this.Client.Headers[DeviceAuthHeaderName] = DeviceAuthHeaderValue;
                using (response = await this.Client.GetResponseAsync().ConfigureAwait(false))
                {
                    typedResponse = EncodingHelper.DeserializeResponse <T>(response.ResponseString);
                }
            }
            catch (HttpRequestWrapperException ex)
            {
                if (ex.InnerException is TaskCanceledException)
                {
                    Resiliency = true;

                    _callState.Logger.Information(this.CallState, "Network timeout, Exception type: " + ex.InnerException.GetType());
                    _callState.Logger.InformationPii(this.CallState, "Network timeout, Exception message: " + ex.InnerException.Message);
                }

                if (!Resiliency && ex.WebResponse == null)
                {
                    _callState.Logger.Error(CallState, ex);
                    _callState.Logger.ErrorPii(CallState, ex);
                    throw new AdalServiceException(AdalError.Unknown, ex);
                }

                //check for resiliency
                if (!Resiliency && (int)ex.WebResponse.StatusCode >= 500 && (int)ex.WebResponse.StatusCode < 600)
                {
                    _callState.Logger.Information(this.CallState,
                                                  "HttpStatus code: " + ex.WebResponse.StatusCode + ", Exception type: " + ex.InnerException?.GetType());

                    _callState.Logger.InformationPii(this.CallState,
                                                     "HttpStatus code: " + ex.WebResponse.StatusCode + ", Exception message: " + ex.InnerException?.Message);

                    Resiliency = true;
                }

                if (Resiliency)
                {
                    if (RetryOnce)
                    {
                        await Task.Delay(DelayTimePeriodMilliSeconds).ConfigureAwait(false);

                        RetryOnce = false;

                        var msg = "Retrying one more time..";
                        _callState.Logger.Information(this.CallState, msg);
                        _callState.Logger.InformationPii(this.CallState, msg);

                        return(await this.GetResponseAsync <T>(respondToDeviceAuthChallenge).ConfigureAwait(false));
                    }

                    _callState.Logger.Information(CallState,
                                                  "Retry Failed, Exception type: " + ex.InnerException?.GetType());
                    _callState.Logger.InformationPii(CallState,
                                                     "Retry Failed, Exception message: " + ex.InnerException?.Message);
                }

                if (!this.IsDeviceAuthChallenge(ex.WebResponse, respondToDeviceAuthChallenge))
                {
                    TokenResponse        tokenResponse = TokenResponse.CreateFromErrorResponse(ex.WebResponse);
                    string[]             errorCodes    = tokenResponse.ErrorCodes ?? new[] { ex.WebResponse.StatusCode.ToString() };
                    AdalServiceException serviceEx     = new AdalServiceException(tokenResponse.Error,
                                                                                  tokenResponse.ErrorDescription,
                                                                                  errorCodes, ex);

                    if (ex.WebResponse.StatusCode == HttpStatusCode.BadRequest &&
                        tokenResponse.Error == AdalError.InteractionRequired)
                    {
                        throw new AdalClaimChallengeException(tokenResponse.Error, tokenResponse.ErrorDescription, ex, tokenResponse.Claims);
                    }

                    throw serviceEx;
                }

                //attempt device auth
                return(await HandleDeviceAuthChallenge <T>(ex.WebResponse).ConfigureAwait(false));
            }

            return(typedResponse);
        }
 public LoginFailedException(AdalServiceException innerException) : base(innerException.Message, innerException)
 {
 }