/// <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); } } }
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]); }
public void ExtractClaimChallengeFromHeader_IncorrectError_ReturnNull() { // Arrange HttpResponseMessage httpResponse = CreateClaimsHttpErrorResponse(); // Act & Assert Assert.IsNull(WwwAuthenticateParameters.GetClaimChallengeFromResponseHeaders(httpResponse.Headers)); }
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); }
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); }
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); }
public void ExtractEncodedClaimChallengeFromHeader() { // Arrange HttpResponseMessage httpResponse = CreateClaimsHttpResponse(EncodedClaims); // Act string extractedClaims = WwwAuthenticateParameters.GetClaimChallengeFromResponseHeaders(httpResponse.Headers); // Assert Assert.AreEqual(DecodedClaims, extractedClaims); }
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); }
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); }
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()); }
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); }
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); }
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); }
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]); }
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); }
public async Task CreateFromResourceResponseAsync_Incorrect_ResourceUri_Async(string resourceUri) { Func <Task> action = () => WwwAuthenticateParameters.CreateFromResourceResponseAsync(resourceUri); await Assert.ThrowsExceptionAsync <ArgumentNullException>(action).ConfigureAwait(false); }