/// <summary>
        /// When the Web API needs consent, it can sent a 403 with information in the WWW-Authenticate header in
        /// order to challenge the user
        /// </summary>
        /// <param name="response">HttpResonse received from the service</param>
        /// <returns></returns>
        private async Task HandleChallengeFromWebApi(HttpResponseMessage response, IAccount account)
        {
            WwwAuthenticateParameters wwwAuthenticateParameters = WwwAuthenticateParameters.CreateFromResponseHeaders(response.Headers);
            string claims         = wwwAuthenticateParameters.Claims;
            string proposedAction = wwwAuthenticateParameters["proposedAction"];
            string consentUri     = wwwAuthenticateParameters["consentUri"];

            string loginHint            = account?.Username;
            string domainHint           = IsConsumerAccount(account) ? "consumers" : "organizations";
            string extraQueryParameters = $"claims={claims}&domainHint={domainHint}";

            if (proposedAction == "forceRefresh")
            {
                // Removes the account, but then re-signs-in
                await _app.RemoveAsync(account);

                await _app.AcquireTokenInteractive(new string[] { "user.read" })
                .WithPrompt(Prompt.Consent)
                .WithLoginHint(loginHint)
                .WithExtraQueryParameters(extraQueryParameters)
                .WithAuthority(_app.Authority)
                .ExecuteAsync()
                .ConfigureAwait(false);
            }
            else if (proposedAction == "consent")
            {
                if (System.Windows.MessageBox.Show("You need to consent to the Web API. If you press Ok, you'll be redirected to a browser page to consent",
                                                   "Consent needed for the Web API",
                                                   MessageBoxButton.OKCancel) == MessageBoxResult.OK)
                {
                    Process.Start(consentUri);
                }
            }
        }
Exemple #2
0
        public void CreateRawParameters_ClaimsAndErrorReturned(string claims)
        {
            // Arrange
            HttpResponseMessage httpResponse = CreateClaimsHttpResponse(claims);

            // Act
            var authParams = WwwAuthenticateParameters.CreateFromResponseHeaders(httpResponse.Headers);

            // Assert
            const string errorValue = "insufficient_claims";

            Assert.IsTrue(authParams.RawParameters.TryGetValue(AuthorizationUriKey, out string authorizationUri));
            Assert.AreEqual(AuthorizationValue, authorizationUri);
            Assert.AreEqual(AuthorizationValue, authParams[AuthorizationUriKey]);
            Assert.IsTrue(authParams.RawParameters.ContainsKey(Realm));
            Assert.IsTrue(authParams.RawParameters.TryGetValue(Realm, out string realmValue));
            Assert.AreEqual(string.Empty, realmValue);
            Assert.AreEqual(string.Empty, authParams[Realm]);
            Assert.IsTrue(authParams.RawParameters.TryGetValue(ClaimsKey, out string claimsValue));
            Assert.AreEqual(claims, claimsValue);
            Assert.AreEqual(claimsValue, authParams[ClaimsKey]);
            Assert.IsTrue(authParams.RawParameters.TryGetValue(ErrorKey, out string errorValueParam));
            Assert.AreEqual(errorValue, errorValueParam);
            Assert.AreEqual(errorValue, authParams[ErrorKey]);
        }
Exemple #3
0
        public void ExtractClaimChallengeFromHeader_IncorrectError_ReturnNull()
        {
            // Arrange
            HttpResponseMessage httpResponse = CreateClaimsHttpErrorResponse();

            // Act & Assert
            Assert.IsNull(WwwAuthenticateParameters.GetClaimChallengeFromResponseHeaders(httpResponse.Headers));
        }
Exemple #4
0
        public async Task CreateFromResourceResponseAsync_HttpClient_Null_Async(HttpClient httpClient)
        {
            const string resourceUri = "https://example.com/";

            Func <Task> action = () => WwwAuthenticateParameters.CreateFromResourceResponseAsync(httpClient, resourceUri);

            await Assert.ThrowsExceptionAsync <ArgumentNullException>(action).ConfigureAwait(false);
        }
Exemple #5
0
        public async Task CreateWwwAuthenticateResponseFromGraphUrlAsync()
        {
            var authParams = await WwwAuthenticateParameters.CreateFromResourceResponseAsync("https://graph.microsoft.com/v1.0/me").ConfigureAwait(false);

            Assert.AreEqual("https://login.microsoftonline.com/common", authParams.Authority);
            Assert.AreEqual("common", authParams.GetTenantId());
            Assert.AreEqual(3, authParams.RawParameters.Count);
            Assert.IsNull(authParams.Claims);
            Assert.IsNull(authParams.Error);
        }
Exemple #6
0
        public async Task CreateWwwAuthenticateResponseFromKeyVaultUrlAsync()
        {
            var authParams = await WwwAuthenticateParameters.CreateFromResourceResponseAsync("https://buildautomation.vault.azure.net/secrets/CertName/CertVersion").ConfigureAwait(false);

            Assert.AreEqual("login.windows.net", new Uri(authParams.Authority).Host);
            Assert.AreEqual("72f988bf-86f1-41af-91ab-2d7cd011db47", authParams.GetTenantId()); // because the Key Vault resource belong to Microsoft Corp tenant
            Assert.AreEqual(2, authParams.RawParameters.Count);
            Assert.IsNull(authParams.Claims);
            Assert.IsNull(authParams.Error);
        }
Exemple #7
0
        public void ExtractEncodedClaimChallengeFromHeader()
        {
            // Arrange
            HttpResponseMessage httpResponse = CreateClaimsHttpResponse(EncodedClaims);

            // Act
            string extractedClaims = WwwAuthenticateParameters.GetClaimChallengeFromResponseHeaders(httpResponse.Headers);

            // Assert
            Assert.AreEqual(DecodedClaims, extractedClaims);
        }
Exemple #8
0
        public async Task CreateWwwAuthenticateResponseFromKeyVaultUrlAsync()
        {
            var authParams = await WwwAuthenticateParameters.CreateFromResourceResponseAsync("https://msidentitywebsamples.vault.azure.net/secrets/CertName/CertVersion").ConfigureAwait(false);

            Assert.AreEqual("https://vault.azure.net", authParams.Resource);
            Assert.AreEqual("login.windows.net", new Uri(authParams.Authority).Host);
            Assert.AreEqual("https://vault.azure.net/.default", authParams.Scopes.FirstOrDefault());
            Assert.AreEqual(2, authParams.RawParameters.Count);
            Assert.IsNull(authParams.Claims);
            Assert.IsNull(authParams.Error);
        }
Exemple #9
0
        public async Task CreateWwwAuthenticateResponseFromAzureResourceManagerUrlAsync(string hostName, string subscriptionId, string authority, string tenantId)
        {
            const string apiVersion = "2020-08-01"; // current latest API version for /subscriptions/get
            var          url        = $"https://{hostName}/subscriptions/{subscriptionId}?api-version={apiVersion}";

            var authParams = await WwwAuthenticateParameters.CreateFromResourceResponseAsync(url).ConfigureAwait(false);

            Assert.AreEqual($"https://{authority}/{tenantId}", authParams.Authority); // authority URI consists of AAD endpoint and tenant ID
            Assert.AreEqual(tenantId, authParams.GetTenantId());                      // tenant ID is extracted out of authority URI
            Assert.AreEqual(3, authParams.RawParameters.Count);
            Assert.IsNull(authParams.Claims);
            Assert.AreEqual("invalid_token", authParams.Error);
        }
Exemple #10
0
        public async Task CreateFromResourceResponseAsync_HttpClient_ADFS_GetTenantId_Null_Async(string authority)
        {
            const string resourceUri = "https://example.com/";
            string       tenantId    = Guid.NewGuid().ToString();

            var handler = new MockHttpMessageHandler
            {
                ExpectedMethod  = HttpMethod.Get,
                ExpectedUrl     = resourceUri,
                ResponseMessage = CreateInvalidTokenHttpErrorResponse(tenantId, authority)
            };
            var httpClient = new HttpClient(handler);
            var authParams = await WwwAuthenticateParameters.CreateFromResourceResponseAsync(httpClient, resourceUri).ConfigureAwait(false);

            Assert.IsNull(authParams.GetTenantId());
        }
Exemple #11
0
        public async Task CreateFromResourceResponseAsync_HttpClient_B2C_GetTenantId_Async()
        {
            const string resourceUri = "https://example.com/";
            const string tenantId    = "tenant";

            var handler = new MockHttpMessageHandler
            {
                ExpectedMethod  = HttpMethod.Get,
                ExpectedUrl     = resourceUri,
                ResponseMessage = CreateInvalidTokenHttpErrorResponse(authority: TestConstants.B2CAuthority)
            };
            var httpClient = new HttpClient(handler);
            var authParams = await WwwAuthenticateParameters.CreateFromResourceResponseAsync(httpClient, resourceUri).ConfigureAwait(false);

            Assert.AreEqual(authParams.GetTenantId(), tenantId);
        }
Exemple #12
0
        public void CreateWwwAuthenticateResponse(string resource, string authorizationUri)
        {
            // Arrange
            HttpResponseMessage httpResponse = new HttpResponseMessage(HttpStatusCode.Unauthorized);

            httpResponse.Headers.Add(WwwAuthenticateHeaderName, $"Bearer realm=\"\", {resource}, {authorizationUri}");

            // Act
            var authParams = WwwAuthenticateParameters.CreateFromResponseHeaders(httpResponse.Headers);

            // Assert
            Assert.AreEqual(TestConstants.AuthorityCommonTenant.TrimEnd('/'), authParams.Authority);
            Assert.AreEqual(3, authParams.RawParameters.Count);
            Assert.IsNull(authParams.Claims);
            Assert.IsNull(authParams.Error);
        }
Exemple #13
0
        public void CreateWwwAuthenticateParamsFromWwwAuthenticateHeader(string clientId, string authorizationUri)
        {
            // Arrange
            HttpResponseMessage httpResponse = new HttpResponseMessage(HttpStatusCode.Unauthorized);

            httpResponse.Headers.Add(WwwAuthenticateHeaderName, $"Bearer realm=\"\", {clientId}, {authorizationUri}");

            var wwwAuthenticateResponse = httpResponse.Headers.WwwAuthenticate.First().Parameter;

            // Act
            var authParams = WwwAuthenticateParameters.CreateFromWwwAuthenticateHeaderValue(wwwAuthenticateResponse);

            // Assert
            Assert.AreEqual(TestConstants.AuthorityCommonTenant.TrimEnd('/'), authParams.Authority);
            Assert.AreEqual(3, authParams.RawParameters.Count);
            Assert.IsNull(authParams.Claims);
            Assert.IsNull(authParams.Error);
        }
Exemple #14
0
        public void CreateRawParameters(string resourceHeaderKey, string authorizationUriHeaderKey)
        {
            // Arrange
            HttpResponseMessage httpResponse = CreateGraphHttpResponse(resourceHeaderKey, authorizationUriHeaderKey);

            // Act
            var authParams = WwwAuthenticateParameters.CreateFromResponseHeaders(httpResponse.Headers);

            // Assert
            Assert.IsTrue(authParams.RawParameters.ContainsKey(resourceHeaderKey));
            Assert.IsTrue(authParams.RawParameters.ContainsKey(authorizationUriHeaderKey));
            Assert.IsTrue(authParams.RawParameters.ContainsKey(Realm));
            Assert.AreEqual(string.Empty, authParams[Realm]);
            Assert.AreEqual(GraphGuid, authParams[resourceHeaderKey]);
            Assert.ThrowsException <KeyNotFoundException>(
                () => authParams[ErrorKey]);
            Assert.ThrowsException <KeyNotFoundException>(
                () => authParams[ClaimsKey]);
        }
Exemple #15
0
        public async Task <IActionResult> Profile()
        {
            User currentUser = null;

            try
            {
                currentUser = await _graphServiceClient.Me.Request().GetAsync();
            }
            // Catch CAE exception from Graph SDK
            catch (ServiceException svcex) when(svcex.Message.Contains("Continuous access evaluation resulted in claims challenge"))
            {
                try
                {
                    Console.WriteLine($"{svcex}");
                    string claimChallenge = WwwAuthenticateParameters.GetClaimChallengeFromResponseHeaders(svcex.ResponseHeaders);
                    _consentHandler.ChallengeUser(_graphScopes, claimChallenge);
                    return(new EmptyResult());
                }
                catch (Exception ex2)
                {
                    _consentHandler.HandleException(ex2);
                }
            }

            try
            {
                // Get user photo
                using (var photoStream = await _graphServiceClient.Me.Photo.Content.Request().GetAsync())
                {
                    byte[] photoByte = ((MemoryStream)photoStream).ToArray();
                    ViewData["Photo"] = Convert.ToBase64String(photoByte);
                }
            }
            catch (Exception pex)
            {
                Console.WriteLine($"{pex.Message}");
                ViewData["Photo"] = null;
            }

            ViewData["Me"] = currentUser;
            return(View());
        }
        public void CreateWwwAuthenticateResponse(string resource, string authorizationUri)
        {
            // Arrange
            HttpResponseMessage httpResponse = new HttpResponseMessage((HttpStatusCode)401)
            {
            };

            httpResponse.Headers.Add("WWW-Authenticate", $"Bearer realm=\"\", {resource}, {authorizationUri}");

            // Act
            var authParams = WwwAuthenticateParameters.CreateFromResponseHeaders(httpResponse.Headers);

            // Assert
            Assert.AreEqual(GraphGuid, authParams.Resource);
            Assert.AreEqual(TestConstants.AuthorityCommonTenant.TrimEnd('/'), authParams.Authority);
            Assert.AreEqual($"{GraphGuid}/.default", authParams.Scopes.FirstOrDefault());
            Assert.AreEqual(3, authParams.RawParameters.Count);
            Assert.IsNull(authParams.Claims);
            Assert.IsNull(authParams.Error);
        }
Exemple #17
0
        public async Task CreateFromResourceResponseAsync_Incorrect_ResourceUri_Async(string resourceUri)
        {
            Func <Task> action = () => WwwAuthenticateParameters.CreateFromResourceResponseAsync(resourceUri);

            await Assert.ThrowsExceptionAsync <ArgumentNullException>(action).ConfigureAwait(false);
        }