private async Task <AuthenticationResult> RefreshAccessTokenAsync(AuthenticationResult result)
        {
            AuthenticationResult newResult = null;

            if (this.Resource != null)
            {
                try
                {
                    newResult = await this.SendTokenRequestByRefreshTokenAsync(result.RefreshToken);

                    this.Authenticator.UpdateTenantId(result.TenantId);

                    if (newResult.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.
                        newResult.UpdateTenantAndUserInfo(result.TenantId, result.IdToken, 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,
                                  (WebException)serviceException.InnerException);
                    }

                    newResult = null;
                }
            }

            return(newResult);
        }
示例#2
0
        private void VerifyAuthorizationResult()
        {
            if (this.promptBehavior == PromptBehavior.Never && this.authorizationResult.Error == OAuthError.LoginRequired)
            {
                var ex = new AdalException(AdalError.UserInteractionRequired);
                Logger.LogException(this.CallState, ex);
                throw ex;
            }

            if (this.authorizationResult.Status != AuthorizationStatus.Success)
            {
                var ex = new AdalServiceException(this.authorizationResult.Error, this.authorizationResult.ErrorDescription);
                Logger.LogException(this.CallState, ex);
                throw ex;
            }
        }
示例#3
0
        private static async Task <AuthenticationParameters> CreateFromResourceUrlCommonAsync(Uri resourceUrl)
        {
            CallState callState = new CallState(Guid.NewGuid(), false);

            if (resourceUrl == null)
            {
                throw new ArgumentNullException("resourceUrl");
            }

            IHttpWebResponse         response = null;
            AuthenticationParameters authParams;

            try
            {
                IHttpWebRequest request = NetworkPlugin.HttpWebRequestFactory.Create(resourceUrl.AbsoluteUri);
                request.ContentType = "application/x-www-form-urlencoded";
                response            = await request.GetResponseSyncOrAsync(callState);

                var ex = new AdalException(AdalError.UnauthorizedResponseExpected);
                Logger.Error(null, ex);
                throw ex;
            }
            catch (WebException ex)
            {
                response = NetworkPlugin.HttpWebRequestFactory.CreateResponse(ex.Response);
                if (response == null)
                {
                    var serviceEx = new AdalServiceException(AdalErrorMessage.UnauthorizedHttpStatusCodeExpected, ex);
                    Logger.Error(null, serviceEx);
                    throw serviceEx;
                }

                authParams = CreateFromUnauthorizedResponseCommon(response);
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }

            return(authParams);
        }
示例#4
0
        private async Task <AuthenticationResultEx> RefreshAccessTokenAsync(AuthenticationResultEx result)
        {
            AuthenticationResultEx newResultEx = null;

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

                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);
        }
        internal static async Task <UserRealmDiscoveryResponse> CreateByDiscoveryAsync(string userRealmUri, string userName, CallState callState)
        {
            string userRealmEndpoint = userRealmUri;

            userRealmEndpoint += (userName + "?api-version=1.0");

            userRealmEndpoint = HttpHelper.CheckForExtraQueryParameter(userRealmEndpoint);
            Logger.Information(callState, "Sending user realm discovery request to '{0}'", userRealmEndpoint);

            UserRealmDiscoveryResponse userRealmResponse;
            ClientMetrics clientMetrics = new ClientMetrics();

            try
            {
                IHttpWebRequest request = NetworkPlugin.HttpWebRequestFactory.Create(userRealmEndpoint);
                request.Method = "GET";
                request.Accept = "application/json";
                HttpHelper.AddCorrelationIdHeadersToRequest(request, callState);
                AdalIdHelper.AddAsHeaders(request);

                clientMetrics.BeginClientMetricsRecord(request, callState);

                using (var response = await request.GetResponseSyncOrAsync(callState))
                {
                    HttpHelper.VerifyCorrelationIdHeaderInReponse(response, callState);
                    userRealmResponse = HttpHelper.DeserializeResponse <UserRealmDiscoveryResponse>(response);
                    clientMetrics.SetLastError(null);
                }
            }
            catch (WebException ex)
            {
                var serviceException = new AdalServiceException(AdalError.UserRealmDiscoveryFailed, ex);
                clientMetrics.SetLastError(new[] { serviceException.StatusCode.ToString() });
                throw serviceException;
            }
            finally
            {
                clientMetrics.EndClientMetricsRecord(ClientMetricsEndpointType.UserRealmDiscovery, callState);
            }

            return(userRealmResponse);
        }
        internal static async Task<UserRealmDiscoveryResponse> CreateByDiscoveryAsync(string userRealmUri, string userName, CallState callState)
        {
            string userRealmEndpoint = userRealmUri;
            userRealmEndpoint += (userName + "?api-version=1.0");

            userRealmEndpoint = HttpHelper.CheckForExtraQueryParameter(userRealmEndpoint);
            Logger.Information(callState, "Sending user realm discovery request to '{0}'", userRealmEndpoint);

            UserRealmDiscoveryResponse userRealmResponse;
            ClientMetrics clientMetrics = new ClientMetrics();

            try
            {
                IHttpWebRequest request = NetworkPlugin.HttpWebRequestFactory.Create(userRealmEndpoint);
                request.Method = "GET";
                request.Accept = "application/json";
                HttpHelper.AddCorrelationIdHeadersToRequest(request, callState);
                AdalIdHelper.AddAsHeaders(request);

                clientMetrics.BeginClientMetricsRecord(request, callState);

                using (var response = await request.GetResponseSyncOrAsync(callState))
                {
                    HttpHelper.VerifyCorrelationIdHeaderInReponse(response, callState);
                    userRealmResponse = HttpHelper.DeserializeResponse<UserRealmDiscoveryResponse>(response);
                    clientMetrics.SetLastError(null);
                }
            }
            catch (WebException ex)
            {
                var serviceException = new AdalServiceException(AdalError.UserRealmDiscoveryFailed, ex);
                clientMetrics.SetLastError(new[] { serviceException.StatusCode.ToString() });
                throw serviceException;
            }
            finally
            {
                clientMetrics.EndClientMetricsRecord(ClientMetricsEndpointType.UserRealmDiscovery, callState);
            }

            return userRealmResponse;
        }
示例#7
0
        private async Task <T> GetResponseAsync <T>(bool respondToDeviceAuthChallenge)
        {
            T typedResponse = default(T);
            IHttpWebResponse response;

            try
            {
                if (PlatformPlugin.HttpClientFactory.AddAdditionalHeaders)
                {
                    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;
                    PlatformPlugin.Logger.Information(this.CallState, "Network timeout - " + ex.InnerException.Message);
                }

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

                        if ((int)ex.WebResponse.StatusCode >= 500 && (int)ex.WebResponse.StatusCode < 600)
                        {
                            PlatformPlugin.Logger.Information(this.CallState, "HttpStatus code: " + ex.WebResponse.StatusCode + " - " + ex.InnerException.Message);
                            Resiliency = true;
                        }
                    }
                    else
                    {
                        serviceEx = new AdalServiceException(AdalError.Unknown, ex);
                    }

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

                            RetryOnce = false;
                            PlatformPlugin.Logger.Information(this.CallState, "Retrying one more time..");
                            return(await this.GetResponseAsync <T>(respondToDeviceAuthChallenge).ConfigureAwait(false));
                        }

                        PlatformPlugin.Logger.Information(this.CallState,
                                                          "Retry Failed - " + ex.InnerException.Message);
                    }

                    PlatformPlugin.Logger.Error(CallState, serviceEx);
                    throw serviceEx;
                }
                else
                {
                    response = ex.WebResponse;
                }
            }
            //check for pkeyauth challenge
            if (this.isDeviceAuthChallenge(response, respondToDeviceAuthChallenge))
            {
                return(await HandleDeviceAuthChallenge <T>(response).ConfigureAwait(false));
            }

            return(typedResponse);
        }
        public static AuthenticationResult ParseTokenResponse(TokenResponse tokenResponse, CallState callState)
        {
            AuthenticationResult result;

            if (tokenResponse.AccessToken != null)
            {
                DateTimeOffset expiresOn = DateTime.UtcNow + TimeSpan.FromSeconds(tokenResponse.ExpiresIn);

                result = new AuthenticationResult(tokenResponse.TokenType, tokenResponse.AccessToken, tokenResponse.RefreshToken, expiresOn)
                {
                    // This is only needed for AcquireTokenByAuthorizationCode in which parameter resource is optional and we need
                    // to get it from the STS response.
                    Resource = tokenResponse.Resource,
                    IsMultipleResourceRefreshToken = (!string.IsNullOrWhiteSpace(tokenResponse.RefreshToken) && !string.IsNullOrWhiteSpace(tokenResponse.Resource)),
                };

                IdToken idToken = ParseIdToken(tokenResponse.IdToken);
                if (idToken != null)
                {
                    string tenantId      = idToken.TenantId;
                    string uniqueId      = null;
                    string displayableId = null;

                    if (!string.IsNullOrWhiteSpace(idToken.ObjectId))
                    {
                        uniqueId = idToken.ObjectId;
                    }
                    else if (!string.IsNullOrWhiteSpace(idToken.Subject))
                    {
                        uniqueId = idToken.Subject;
                    }

                    if (!string.IsNullOrWhiteSpace(idToken.UPN))
                    {
                        displayableId = idToken.UPN;
                    }
                    else if (!string.IsNullOrWhiteSpace(idToken.Email))
                    {
                        displayableId = idToken.Email;
                    }

                    string         givenName             = idToken.GivenName;
                    string         familyName            = idToken.FamilyName;
                    string         identityProvider      = idToken.IdentityProvider ?? idToken.Issuer;
                    DateTimeOffset?passwordExpiresOffest = null;
                    if (idToken.PasswordExpiration > 0)
                    {
                        passwordExpiresOffest = DateTime.UtcNow + TimeSpan.FromSeconds(idToken.PasswordExpiration);
                    }

                    Uri changePasswordUri = null;
                    if (!string.IsNullOrEmpty(idToken.PasswordChangeUrl))
                    {
                        changePasswordUri = new Uri(idToken.PasswordChangeUrl);
                    }

                    result.UpdateTenantAndUserInfo(tenantId, tokenResponse.IdToken, new UserInfo {
                        UniqueId = uniqueId, DisplayableId = displayableId, GivenName = givenName, FamilyName = familyName, IdentityProvider = identityProvider, PasswordExpiresOn = passwordExpiresOffest, PasswordChangeUrl = changePasswordUri
                    });
                }
            }
            else if (tokenResponse.Error != null)
            {
                var ex = new AdalServiceException(tokenResponse.Error, tokenResponse.ErrorDescription);
                PlatformPlugin.Logger.LogException(callState, ex);
                throw ex;
            }
            else
            {
                var ex = new AdalServiceException(AdalError.Unknown, AdalErrorMessage.Unknown);
                PlatformPlugin.Logger.LogException(callState, ex);
                throw ex;
            }

            return(result);
        }
        public async Task TimeoutTest()
        {
            const string TestServiceUrl = "http://localhost:8080";
            using (WebApp.Start<TestService>(TestServiceUrl))
            {
                HttpClientWrapper webClient = new HttpClientWrapper(TestServiceUrl + "?delay=0&response_code=200", null) { TimeoutInMilliSeconds = 10000 };
                await webClient.GetResponseAsync();

                webClient = new HttpClientWrapper(TestServiceUrl + "?delay=0&response_code=200", null) { TimeoutInMilliSeconds = 10000 };
                await webClient.GetResponseAsync();

                try
                {
                    webClient = new HttpClientWrapper(TestServiceUrl + "?delay=0&response_code=400", null) { TimeoutInMilliSeconds = 10000 };
                    await webClient.GetResponseAsync();
                }
                catch (HttpRequestWrapperException ex)
                {
                    Verify.AreEqual(ex.WebResponse.StatusCode, HttpStatusCode.BadRequest);
                }


                try
                {
                    webClient = new HttpClientWrapper(TestServiceUrl + "?delay=10000&response_code=200", null) { TimeoutInMilliSeconds = 500 };
                    await webClient.GetResponseAsync();
                }
                catch (HttpRequestWrapperException ex)
                {
                    Verify.IsTrue(ex.InnerException is TaskCanceledException);
                    var serviceException = new AdalServiceException(AdalError.Unknown, ex);
                    Verify.AreEqual(serviceException.StatusCode, (int)HttpStatusCode.RequestTimeout);
                }
            }
        }
        private static async Task<AuthenticationParameters> CreateFromResourceUrlCommonAsync(Uri resourceUrl)
        {
            CallState callState = new CallState(Guid.NewGuid(), false);

            if (resourceUrl == null)
            {
                throw new ArgumentNullException("resourceUrl");
            }

            IHttpWebResponse response = null;
            AuthenticationParameters authParams;

            try
            {
                IHttpWebRequest request = NetworkPlugin.HttpWebRequestFactory.Create(resourceUrl.AbsoluteUri);
                request.ContentType = "application/x-www-form-urlencoded";
                response = await request.GetResponseSyncOrAsync(callState);
                var ex = new AdalException(AdalError.UnauthorizedResponseExpected);
                Logger.Error(null, ex);
                throw ex;
            }
            catch (WebException ex)
            {
                response = NetworkPlugin.HttpWebRequestFactory.CreateResponse(ex.Response);
                if (response == null)
                {
                    var serviceEx = new AdalServiceException(AdalErrorMessage.UnauthorizedHttpStatusCodeExpected, ex);
                    Logger.Error(null, serviceEx);
                    throw serviceEx;
                }

                authParams = CreateFromUnauthorizedResponseCommon(response);
            }
            finally
            {
                if (response != null)
                {
                    response.Close();
                }
            }

            return authParams;
        }
        private static async Task<AuthenticationParameters> CreateFromResourceUrlCommonAsync(Uri resourceUrl)
        {
            if (resourceUrl == null)
            {
                throw new ArgumentNullException("resourceUrl");
            }

            AuthenticationParameters authParams;

            try
            {
                IHttpClient request = PlatformPlugin.HttpClientFactory.Create(resourceUrl.AbsoluteUri, null);
                using (await request.GetResponseAsync())
                {
                    var ex = new AdalException(AdalError.UnauthorizedResponseExpected);
                    PlatformPlugin.Logger.Error(null, ex);
                    throw ex;                    
                }
            }
            catch (HttpRequestWrapperException ex)
            {
                IHttpWebResponse response = ex.WebResponse;
                if (response == null)
                {
                    var serviceEx = new AdalServiceException(AdalErrorMessage.UnauthorizedHttpStatusCodeExpected, ex);
                    PlatformPlugin.Logger.Error(null, serviceEx);
                    throw serviceEx;
                }

                authParams = CreateFromUnauthorizedResponseCommon(response);
            }

            return authParams;
        }
        private async Task <T> GetResponseAsync <T>(string endpointType, bool respondToDeviceAuthChallenge)
        {
            T typedResponse = default(T);
            IHttpWebResponse response;
            ClientMetrics    clientMetrics = new ClientMetrics();

            try
            {
                clientMetrics.BeginClientMetricsRecord(this.CallState);

                if (PlatformPlugin.HttpClientFactory.AddAdditionalHeaders)
                {
                    Dictionary <string, string> clientMetricsHeaders = clientMetrics.GetPreviousRequestRecord(this.CallState);
                    foreach (KeyValuePair <string, string> kvp in clientMetricsHeaders)
                    {
                        this.Client.Headers[kvp.Key] = kvp.Value;
                    }

                    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())
                {
                    typedResponse = DeserializeResponse <T>(response.ResponseStream);
                    clientMetrics.SetLastError(null);
                }
            }
            catch (HttpRequestWrapperException ex)
            {
                if (!this.isDeviceAuthChallenge(endpointType, ex.WebResponse, respondToDeviceAuthChallenge))
                {
                    AdalServiceException serviceEx;
                    if (ex.WebResponse != null)
                    {
                        TokenResponse tokenResponse = TokenResponse.CreateFromErrorResponse(ex.WebResponse);
                        string[]      errorCodes    = tokenResponse.ErrorCodes ?? new[] { ex.WebResponse.StatusCode.ToString() };
                        serviceEx = new AdalServiceException(tokenResponse.Error, tokenResponse.ErrorDescription,
                                                             errorCodes, ex);
                    }
                    else
                    {
                        serviceEx = new AdalServiceException(AdalError.Unknown, ex);
                    }

                    clientMetrics.SetLastError(serviceEx.ServiceErrorCodes);
                    PlatformPlugin.Logger.Error(CallState, serviceEx);
                    throw serviceEx;
                }
                else
                {
                    response = ex.WebResponse;
                }
            }
            finally
            {
                clientMetrics.EndClientMetricsRecord(endpointType, this.CallState);
            }

            //check for pkeyauth challenge
            if (this.isDeviceAuthChallenge(endpointType, response, respondToDeviceAuthChallenge))
            {
                return(await HandleDeviceAuthChallenge <T>(endpointType, response));
            }

            return(typedResponse);
        }