/// <summary> /// Gets an access token for a downstream API on behalf of the user described by its claimsPrincipal. /// </summary> /// <param name="application"><see cref="IConfidentialClientApplication"/>.</param> /// <param name="claimsPrincipal">Claims principal for the user on behalf of whom to get a token.</param> /// <param name="scopes">Scopes for the downstream API to call.</param> /// <param name="tenant">(optional) Specific tenant for which to acquire a token to access the scopes /// on behalf of the user described in the claimsPrincipal.</param> /// <param name="userFlow">Azure AD B2C user flow to target.</param> private async Task <string> GetAccessTokenOnBehalfOfUserFromCacheAsync( IConfidentialClientApplication application, ClaimsPrincipal claimsPrincipal, IEnumerable <string> scopes, string?tenant, string?userFlow = null) { IAccount?account = null; if (_microsoftIdentityOptions.IsB2C && !string.IsNullOrEmpty(userFlow)) { string?nameIdentifierId = claimsPrincipal.GetNameIdentifierId(); string?utid = claimsPrincipal.GetHomeTenantId(); string?b2cAccountIdentifier = string.Format(CultureInfo.InvariantCulture, "{0}-{1}.{2}", nameIdentifierId, userFlow, utid); account = await application.GetAccountAsync(b2cAccountIdentifier).ConfigureAwait(false); } else { string?accountIdentifier = claimsPrincipal.GetMsalAccountId(); if (accountIdentifier != null) { account = await application.GetAccountAsync(accountIdentifier).ConfigureAwait(false); } } return(await GetAccessTokenOnBehalfOfUserFromCacheAsync( application, account, scopes, tenant).ConfigureAwait(false)); }
/// <summary> /// Gets an access token for a downstream API on behalf of the user described by its claimsPrincipal. /// </summary> /// <param name="application"><see cref="IConfidentialClientApplication"/>.</param> /// <param name="claimsPrincipal">Claims principal for the user on behalf of whom to get a token.</param> /// <param name="scopes">Scopes for the downstream API to call.</param> /// <param name="authority">(optional) Authority based on a specific tenant for which to acquire a token to access the scopes /// on behalf of the user described in the claimsPrincipal.</param> /// <param name="userFlow">Azure AD B2C user flow to target.</param> /// <param name="tokenAcquisitionOptions">Options passed-in to create the token acquisition object which calls into MSAL .NET.</param> private async Task <AuthenticationResult> GetAuthenticationResultForWebAppWithAccountFromCacheAsync( IConfidentialClientApplication application, ClaimsPrincipal?claimsPrincipal, IEnumerable <string> scopes, string?authority, string?userFlow = null, TokenAcquisitionOptions?tokenAcquisitionOptions = null) { IAccount?account = null; if (_microsoftIdentityOptions.IsB2C && !string.IsNullOrEmpty(userFlow)) { string?nameIdentifierId = claimsPrincipal?.GetNameIdentifierId(); string?utid = claimsPrincipal?.GetHomeTenantId(); string?b2cAccountIdentifier = string.Format(CultureInfo.InvariantCulture, "{0}-{1}.{2}", nameIdentifierId, userFlow, utid); account = await application.GetAccountAsync(b2cAccountIdentifier).ConfigureAwait(false); } else { string?accountIdentifier = claimsPrincipal?.GetMsalAccountId(); if (accountIdentifier != null) { account = await application.GetAccountAsync(accountIdentifier).ConfigureAwait(false); } } return(await GetAuthenticationResultForWebAppWithAccountFromCacheAsync( application, account, scopes, authority, userFlow, tokenAcquisitionOptions).ConfigureAwait(false)); }
/// <summary> /// Removes the account associated with context.HttpContext.User from the MSAL.NET cache. /// </summary> /// <param name="context">RedirectContext passed-in to a <see cref="OpenIdConnectEvents.OnRedirectToIdentityProviderForSignOut"/> /// OpenID Connect event.</param> /// <returns>A <see cref="Task"/> that represents a completed account removal operation.</returns> public async Task RemoveAccountAsync(RedirectContext context) { ClaimsPrincipal user = context.HttpContext.User; string? userId = user.GetMsalAccountId(); if (!string.IsNullOrEmpty(userId)) { IConfidentialClientApplication app = await GetOrBuildConfidentialClientApplicationAsync().ConfigureAwait(false); // For B2C, we should remove all accounts of the user regardless the user flow if (_microsoftIdentityOptions.IsB2C) { var b2cAccounts = await app.GetAccountsAsync().ConfigureAwait(false); foreach (var b2cAccount in b2cAccounts) { await app.RemoveAsync(b2cAccount).ConfigureAwait(false); } await _tokenCacheProvider.ClearAsync(userId).ConfigureAwait(false); } else { string? identifier = context.HttpContext.User.GetMsalAccountId(); IAccount account = await app.GetAccountAsync(identifier).ConfigureAwait(false); if (account != null) { await app.RemoveAsync(account).ConfigureAwait(false); await _tokenCacheProvider.ClearAsync(userId).ConfigureAwait(false); } } } }
private async Task <AuthenticationResult> AcquireTokenForScopes(string[] scopes) { IConfidentialClientApplication cca = MsalAppBuilder.BuildConfidentialClientApplication(); var account = await cca.GetAccountAsync(ClaimsPrincipal.Current.GetB2CMsalAccountIdentifier()); return(await cca.AcquireTokenSilent(scopes, account).ExecuteAsync()); }
public async Task <ActionResult> GetMe() { IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(AuthenticationConfig.ClientId) .WithAuthority(new Uri(AuthenticationConfig.Authority)) .WithClientSecret(AuthenticationConfig.ClientSecret) .Build(); AuthenticationResult result = null; var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId()); try { // try to get token silently //result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false); result = await app.AcquireTokenForClient(AuthenticationConfig.Scopes).ExecuteAsync().ConfigureAwait(false); } catch (MsalUiRequiredException) { ViewBag.Relogin = "******"; return(View()); } catch (Exception eee) { ViewBag.Error = "An error has occurred. Details: " + eee.Message; return(View()); } if (result != null) { // Use the token to read email //HttpClient hc = new HttpClient(); //hc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", result.AccessToken); //HttpResponseMessage hrm = await hc.GetAsync("https://graph.microsoft.com/v1.0/me"); //string rez = await hrm.Content.ReadAsStringAsync(); //ViewBag.Message = rez; var accessToken = result.AccessToken; var graphClient = new GraphServiceClient(new DelegateAuthenticationProvider(async(requestMessage) => { // Retrieve an access token for Microsoft Graph (gets a fresh token if needed). //var authResult = await app.AcquireTokenForClient(scopes).ExecuteAsync().ConfigureAwait(false); // Add the access token in the Authorization header of the API request.requestMessage.Headers.Authorization = requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); })); //var eml = System.Web.HttpContext.Current.User.Identity.Name; var eml = ClaimsPrincipal.Current.FindFirst("preferred_username"); string upn = eml.Value; var user = await graphClient.Users[upn].Request() //.Filter(eml) .Select("id, department, displayName, employeeId, givenName, surname, jobTitle, userPrincipalName, officeLocation, onPremisesExtensionAttributes, userType") .GetAsync(); ViewBag.Message = user.UserPrincipalName; } return(View()); }
/// <summary> /// Removes the account associated with context.HttpContext.User from the MSAL.NET cache. /// </summary> /// <param name="context">RedirectContext passed-in to a <see cref="OpenIdConnectEvents.OnRedirectToIdentityProviderForSignOut"/> /// OpenID Connect event.</param> /// <returns>A <see cref="Task"/> that represents a completed account removal operation.</returns> public async Task RemoveAccountAsync(RedirectContext context) { ClaimsPrincipal user = context.HttpContext.User; string? userId = user.GetMsalAccountId(); if (!string.IsNullOrEmpty(userId)) { IConfidentialClientApplication app = await GetOrBuildConfidentialClientApplicationAsync().ConfigureAwait(false); if (_microsoftIdentityOptions.IsB2C) { await _tokenCacheProvider.ClearAsync(userId).ConfigureAwait(false); } else { string? identifier = context.HttpContext.User.GetMsalAccountId(); IAccount account = await app.GetAccountAsync(identifier).ConfigureAwait(false); if (account != null) { await app.RemoveAsync(account).ConfigureAwait(false); await _tokenCacheProvider.ClearAsync(userId).ConfigureAwait(false); } } } }
// Gets an access token. First tries to get the access token from the token cache. // Using password (secret) to authenticate. Production apps should use a certificate. public async Task <string> GetUserAccessTokenAsync(string userId) { var account = await _app.GetAccountAsync(userId); if (account == null) { throw new ServiceException(new Error { Code = "TokenNotFound", Message = "User not found in token cache. Maybe the server was restarted." }); } try { var result = await _app.AcquireTokenSilent(_scopes, account).ExecuteAsync(); return(result.AccessToken); } // Unable to retrieve the access token silently. catch (Exception) { throw new ServiceException(new Error { Code = GraphErrorCode.AuthenticationFailure.ToString(), Message = "Caller needs to authenticate. Unable to retrieve the access token silently." }); } }
public async Task <string> GetAccessToken() { try { // First attempt to get token from the cache for this user // Check for a matching account in the cache var account = await _msalClient.GetAccountAsync(_tokenResult.MsalAccountId); if (account != null) { // Make a "silent" request for a token. This will // return the cached token if still valid, and will handle // refreshing the token if needed var cacheResult = await _msalClient .AcquireTokenSilent(_scopes, account) .ExecuteAsync(); _logger.LogInformation($"User access token: {cacheResult.AccessToken}"); return(cacheResult.AccessToken); } } catch (MsalUiRequiredException) { // This exception indicates that a new token // can only be obtained by invoking the on-behalf-of // flow. "UiRequired" isn't really accurate since the OBO // flow doesn't involve UI. // Catching the exception so code will continue to the // AcquireTokenOnBehalfOf call below. } catch (Exception exception) { _logger.LogError(exception, "Error getting access token via on-behalf-of flow"); return(null); } try { _logger.LogInformation("Token not found in cache, attempting OBO flow"); // Use the token sent by the calling client as a // user assertion var userAssertion = new UserAssertion(_tokenResult.Token); // Invoke on-behalf-of flow var result = await _msalClient .AcquireTokenOnBehalfOf(_scopes, userAssertion) .ExecuteAsync(); _logger.LogInformation($"User access token: {result.AccessToken}"); return(result.AccessToken); } catch (Exception exception) { _logger.LogError(exception, "Error getting access token from cache"); return(null); } }
/// <summary> /// We obtain access token for Microsoft Graph with the scope "user.readbasic.all". Since this access token was obtained during the initial sign in process /// (OnAuthorizationCodeReceived) and cached, the user will not be prompted to sign in again. /// </summary> /// <returns></returns> private async Task <string> GetGraphAccessToken() { IConfidentialClientApplication cc = MsalAppBuilder.BuildConfidentialClientApplication(); var userAccount = await cc.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId()); AuthenticationResult result = await cc.AcquireTokenSilent(new string[] { "user.readbasic.all" }, userAccount).ExecuteAsync(); return(result.AccessToken); }
/// <summary> /// We obtain access token for Microsoft Graph with the scope "group.read.all". Since this access token was not obtained during the initial sign in process /// (OnAuthorizationCodeReceived), the user will be prompted to consent again. /// </summary> /// <returns></returns> private async Task <string> GetGraphAccessToken(string[] scopes) { IConfidentialClientApplication cc = MsalAppBuilder.BuildConfidentialClientApplication(); IAccount userAccount = await cc.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId()); Microsoft.Identity.Client.AuthenticationResult result = await cc.AcquireTokenSilent(scopes, userAccount).ExecuteAsync(); return(result.AccessToken); }
public async Task <AuthenticationResult> GetAccessTokenByAuthorizationCodeAsync(ClaimsPrincipal principal, string code) { IConfidentialClientApplication app = BuildApp(principal); AuthenticationResult result = await app.AcquireTokenByAuthorizationCode(_scopes, code).ExecuteAsync().ConfigureAwait(false); IAccount account = await app.GetAccountAsync(principal.GetMsalAccountId()); return(result); }
public static async Task RemoveAccount() { BuildConfidentialClientApplication(); var userAccount = await clientapp.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId()); if (userAccount != null) { await clientapp.RemoveAsync(userAccount); } }
public static async Task RemoveAccount(string clientId, string clientSecret, string redirectUri, string authority, string accountId) { BuildConfidentialClientApplication(clientId, clientSecret, redirectUri, authority); var userAccount = await _cca.GetAccountAsync(accountId); if (userAccount != null) { await _cca.RemoveAsync(userAccount); } }
/// <summary> /// Gets an access token for a downstream API on behalf of the user which account ID is passed as an argument /// </summary> /// <param name="application"></param> /// <param name="accountIdentifier"> /// User account identifier for which to acquire a token. /// See <see cref="Microsoft.Identity.Client.AccountId.Identifier" /> /// </param> /// <param name="scopes">Scopes for the downstream API to call</param> /// <param name="loginHint"></param> /// <param name="tenant"></param> private async Task <string> GetAccessTokenOnBehalfOfUserFromCacheAsync( IConfidentialClientApplication application, string accountIdentifier, IEnumerable <string> scopes, string loginHint, string tenant) { if (accountIdentifier == null) { throw new ArgumentNullException(nameof(accountIdentifier)); } if (scopes == null) { throw new ArgumentNullException(nameof(scopes)); } // Get the account var account = await application.GetAccountAsync(accountIdentifier).ConfigureAwait(false); // Special case for guest users as the Guest oid / tenant id are not surfaced. if (account == null) { if (loginHint == null) { throw new ArgumentNullException(nameof(loginHint)); } var accounts = await application.GetAccountsAsync().ConfigureAwait(false); account = accounts.FirstOrDefault(a => a.Username == loginHint); } AuthenticationResult result; if (string.IsNullOrWhiteSpace(tenant)) { result = await application .AcquireTokenSilent(scopes.Except(_scopesRequestedByMsalNet), account) .ExecuteAsync() .ConfigureAwait(false); } else { var authority = application.Authority.Replace(new Uri(application.Authority).PathAndQuery, $"/{tenant}/"); result = await application .AcquireTokenSilent(scopes.Except(_scopesRequestedByMsalNet), account) .WithAuthority(authority) .ExecuteAsync() .ConfigureAwait(false); } return(result.AccessToken); }
private async Task <string> GetTokenForUser() { // Get the account. string userObjectId = User.FindFirstValue(Constants.ClaimIds.UserObjectId); string tenantId = User.FindFirstValue(Constants.ClaimIds.TenantId); var accountIdentifier = $"{userObjectId}.{tenantId}"; IAccount account = await application.GetAccountAsync(accountIdentifier); var authResult = await application.AcquireTokenSilent(Constants.ProductCatalogAPI.SCOPES.ToArray(), account).ExecuteAsync(); return(authResult.AccessToken); }
public async Task <string> GetToken(string scope) { var scopes = scope.Split(" "); var AccountId = UserHttpContext.HttpContext.User.Claims.Where(c => c.Type == CustomClaimTypes.ObjectId).FirstOrDefault().Value; var TenantId = UserHttpContext.HttpContext.User.Claims.Where(c => c.Type == CustomClaimTypes.TenantId).FirstOrDefault().Value; var account = await client.GetAccountAsync($"{AccountId}.{TenantId}"); var result = await client.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false); return(result.AccessToken); }
/// <summary> /// Removes the account associated with context.HttpContext.User from the MSAL.NET cache /// </summary> /// <param name="context">RedirectContext passed-in to a <see cref="OnRedirectToIdentityProviderForSignOut"/> /// Openidconnect event</param> /// <returns></returns> public async Task RemoveAccount(RedirectContext context) { ClaimsPrincipal user = context.HttpContext.User; IConfidentialClientApplication app = CreateApplication(context.HttpContext, user); IAccount account = await app.GetAccountAsync(context.HttpContext.User.GetMsalAccountId()); // Workaround for the guest account if (account == null) { var accounts = await app.GetAccountsAsync(); account = accounts.FirstOrDefault(a => a.Username == user.GetLoginHint()); } await app.RemoveAsync(account); }
/// <summary> /// Common method to remove the cached tokens for the currently signed in user /// </summary> /// <returns></returns> public static async Task ClearUserTokenCache() { IConfidentialClientApplication clientapp = ConfidentialClientApplicationBuilder.Create(Globals.ClientId) .WithClientSecret(Globals.ClientSecret) .WithRedirectUri(Globals.RedirectUri) .WithAuthority(new Uri(Globals.Authority)) .Build(); // We only clear the user's tokens. MSALPerUserMemoryTokenCache userTokenCache = new MSALPerUserMemoryTokenCache(clientapp.UserTokenCache); var userAccount = await clientapp.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId()); //Remove the users from the MSAL's internal cache await clientapp.RemoveAsync(userAccount); userTokenCache.Clear(); }
public static async Task ClearUserTokenCache() { IConfidentialClientApplication clientapp = ConfidentialClientApplicationBuilder.Create(AuthenticationConfig.ClientId) .WithClientSecret(AuthenticationConfig.ClientSecret) .WithRedirectUri(AuthenticationConfig.RedirectUri) .WithAdfsAuthority(AuthenticationConfig.Authority) .Build(); // We only clear the user's tokens. MSALPerUserMemoryTokenCache userTokenCache = new MSALPerUserMemoryTokenCache(clientapp.UserTokenCache); var userAccount = await clientapp.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId()); await clientapp.RemoveAsync(userAccount); userTokenCache.Clear(); }
public async Task <AuthenticationResult> GetAccessTokenAsync(ClaimsPrincipal principal, string[] scopes) { IConfidentialClientApplication app = BuildApp(principal); IAccount account = await app.GetAccountAsync(principal.GetMsalAccountId()); // guest?? if (null == account) { System.Collections.Generic.IEnumerable <IAccount> accounts = await app.GetAccountsAsync(); account = accounts.FirstOrDefault(a => a.Username == principal.GetLoginHint()); } AuthenticationResult token = await app.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false); return(token); }
public async Task <AuthenticationResult> AcquireTokenAsync(string tenantId, string audience) { InstantiateConfidentialClient(tenantId); var account = app_.GetAccountAsync(ClientId) .ConfigureAwait(false) .GetAwaiter() .GetResult(); var scopes = new List <string>() { audience }; AuthenticationResult authResult = null; try { // go for the cache authResult = app_.AcquireTokenSilent(scopes, account) .ExecuteAsync() .ConfigureAwait(false) .GetAwaiter() .GetResult(); return(authResult); } catch (MsalUiRequiredException ex) { Console.WriteLine($"silent token acquisition failed: {ex.GetType()}: {ex.ErrorCode}; falling back to interactive."); } try { authResult = await app_.AcquireTokenForClient(scopes) .ExecuteAsync() .ConfigureAwait(false); } catch (MsalClientException ex) { Console.WriteLine($"failed to acquire token for client: {ex.GetType()}: {ex.ErrorCode}; giving up."); throw; } return(authResult); }
public static async Task RemoveAccount() { IConfidentialClientApplication clientapp = ConfidentialClientApplicationBuilder.Create(AuthenticationConfig.ClientId) .WithClientSecret(AuthenticationConfig.ClientSecret) .WithRedirectUri(AuthenticationConfig.RedirectUri) .WithAuthority(new Uri(AuthenticationConfig.Authority)) .Build(); // We only clear the user's tokens. IMsalTokenCacheProvider memoryTokenCacheProvider = CreateTokenCacheSerializer(); await memoryTokenCacheProvider.InitializeAsync(clientapp.UserTokenCache); var userAccount = await clientapp.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId()); if (userAccount != null) { await clientapp.RemoveAsync(userAccount); } }
/// <summary> /// Removes the account associated with context.HttpContext.User from the MSAL.NET cache /// </summary> /// <param name="context">RedirectContext passed-in to a Openidconnect event</param> /// <returns></returns> public async Task RemoveAccountAsync(RedirectContext context) { ClaimsPrincipal user = context.HttpContext.User; IConfidentialClientApplication app = BuildConfidentialClientApplication(context.HttpContext, user); IAccount account = await app.GetAccountAsync(context.HttpContext.User.GetMsalAccountId()).ConfigureAwait(false); // Workaround for the guest account if (account == null) { var accounts = await app.GetAccountsAsync().ConfigureAwait(false); account = accounts.FirstOrDefault(a => a.Username == user.GetLoginHint()); } // AppTokenCacheProvider?.Clear(); _userTokenCacheProvider?.Clear(); await app.RemoveAsync(account).ConfigureAwait(false); }
public async Task <ActionResult> SendMail() { // Before we render the send email screen, we use the incremental consent to obtain and cache the access token with the correct scopes IConfidentialClientApplication app = await MsalAppBuilder.BuildConfidentialClientApplication(); AuthenticationResult result = null; var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId()); string[] scopes = { "Mail.Send" }; try { // try to get an already cached token result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false); } catch (MsalUiRequiredException ex) { // A MsalUiRequiredException happened on AcquireTokenSilentAsync. // This indicates you need to call AcquireTokenAsync to acquire a token Debug.WriteLine($"MsalUiRequiredException: {ex.Message}"); try { // Build the auth code request Uri string authReqUrl = await OAuth2RequestManager.GenerateAuthorizationRequestUrl(scopes, app, this.HttpContext, Url); ViewBag.AuthorizationRequest = authReqUrl; ViewBag.Relogin = "******"; } catch (MsalException msalex) { Response.Write($"Error Acquiring Token:{System.Environment.NewLine}{msalex}"); } } catch (Exception ex) { Response.Write($"Error Acquiring Token Silently:{System.Environment.NewLine}{ex}"); } return(View()); }
/// <summary> /// Removes the account associated with context.HttpContext.User from the MSAL.NET cache. /// </summary> /// <param name="context">RedirectContext passed-in to a <see cref="OpenIdConnectEvents.OnRedirectToIdentityProviderForSignOut"/> /// Openidconnect event.</param> /// <returns></returns> public async Task RemoveAccountAsync(RedirectContext context) { ClaimsPrincipal user = context.HttpContext.User; IConfidentialClientApplication app = await GetOrBuildConfidentialClientApplicationAsync().ConfigureAwait(false); IAccount account = null; // For B2C, we should remove all accounts of the user regardless the user flow if (_microsoftIdentityOptions.IsB2C) { var b2cAccounts = await app.GetAccountsAsync().ConfigureAwait(false); foreach (var b2cAccount in b2cAccounts) { await app.RemoveAsync(b2cAccount).ConfigureAwait(false); } _tokenCacheProvider?.ClearAsync().ConfigureAwait(false); } else { account = await app.GetAccountAsync(context.HttpContext.User.GetMsalAccountId()).ConfigureAwait(false); // Workaround for the guest account if (account == null) { var accounts = await app.GetAccountsAsync().ConfigureAwait(false); account = accounts.FirstOrDefault(a => a.Username == user.GetLoginHint()); } if (account != null) { await app.RemoveAsync(account).ConfigureAwait(false); _tokenCacheProvider?.ClearAsync().ConfigureAwait(false); } } }
/// <summary> /// Clears the user token cache. /// </summary> /// <returns></returns> public static async Task ClearUserTokenCache() { IConfidentialClientApplication clientApplication = ConfidentialClientApplicationBuilder .Create(VeracityIntegrationOptions.ClientId) .WithClientSecret(VeracityIntegrationOptions.ClientSecret) .WithRedirectUri(VeracityIntegrationOptions.RedirectUri) .WithAuthority(new Uri(VeracityIntegrationOptions.Authority)) .Build(); // We only clear the user's tokens. MSALPerUserMemoryTokenCache userTokenCache = new MSALPerUserMemoryTokenCache(clientApplication.UserTokenCache); var msalAccountId = ClaimsPrincipal.Current.GetMsalAccountId(); var userAccount = await clientApplication.GetAccountAsync(msalAccountId); // remove all the tokens in the cache for the specified account await clientApplication.RemoveAsync(userAccount); // clear the client applications token cache copy of the users token cache userTokenCache.Clear(); }
/// <summary> /// Gets an access token for a downstream API on behalf of the user described by its claimsPrincipal. /// </summary> /// <param name="application"></param> /// <param name="claimsPrincipal">Claims principal for the user on behalf of whom to get a token.</param> /// <param name="scopes">Scopes for the downstream API to call.</param> /// <param name="tenant">(optional) Specific tenant for which to acquire a token to access the scopes /// on behalf of the user described in the claimsPrincipal.</param> private async Task <string> GetAccessTokenOnBehalfOfUserFromCacheAsync( IConfidentialClientApplication application, ClaimsPrincipal claimsPrincipal, IEnumerable <string> scopes, string tenant) { // Gets MsalAccountId for AAD and B2C scenarios string accountIdentifier = claimsPrincipal.GetMsalAccountId(); string loginHint = claimsPrincipal.GetLoginHint(); IAccount account = null; if (accountIdentifier != null) { account = await application.GetAccountAsync(accountIdentifier).ConfigureAwait(false); // Special case for guest users as the Guest oid / tenant id are not surfaced. // B2C should not follow this logic since loginHint is not present if (!_microsoftIdentityOptions.IsB2C && account == null) { if (loginHint == null) { throw new ArgumentNullException(nameof(loginHint)); } var accounts = await application.GetAccountsAsync().ConfigureAwait(false); account = accounts.FirstOrDefault(a => a.Username == loginHint); } } // If it is B2C and could not get an account (most likely because there is no tid claims), try to get it by user flow if (_microsoftIdentityOptions.IsB2C && account == null) { string currentUserFlow = claimsPrincipal.GetUserFlowId(); account = GetAccountByUserFlow(await application.GetAccountsAsync().ConfigureAwait(false), currentUserFlow); } return(await GetAccessTokenOnBehalfOfUserFromCacheAsync(application, account, scopes, tenant).ConfigureAwait(false)); }
public async Task <ActionResult> ReadMail() { IConfidentialClientApplication app = await MsalAppBuilder.BuildConfidentialClientApplication(); AuthenticationResult result = null; var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId()); string[] scopes = { "Mail.Read" }; try { // try to get token silently result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false); } catch (MsalUiRequiredException) { ViewBag.Relogin = "******"; return(View()); } catch (Exception eee) { ViewBag.Error = "An error has occurred. Details: " + eee.Message; return(View()); } if (result != null) { // Use the token to read email HttpClient hc = new HttpClient(); hc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", result.AccessToken); HttpResponseMessage hrm = await hc.GetAsync("https://graph.microsoft.com/v1.0/me/messages"); string rez = await hrm.Content.ReadAsStringAsync(); ViewBag.Message = rez; } return(View()); }
/// <summary> /// For web app, gets an access token for a downstream API on behalf of the signed-in user.. /// </summary> /// <param name="requestedScopes"></param> /// <returns></returns> public async Task <AuthenticationResult> GetAccessTokenForUserAsync(IEnumerable <string> requestedScopes) { AuthenticationResult result = null; this.PrepareConfidentialClientInstanceAsync(); try { IAccount account = await _application.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId()); result = await _application.AcquireTokenSilent(requestedScopes, account) .ExecuteAsync(); return(result); } catch (MsalUiRequiredException ex) { // Case of the web app: we let the MsalUiRequiredException be caught by the // AuthorizeForScopesAttribute exception filter so that the user can consent, do 2FA, etc ... //throw new MicrosoftIdentityWebChallengeUserException(ex, requestedScopes.ToArray(), null); throw ex; } }
public async Task <ActionResult> SendMail(string recipient, string subject, string body) { string messagetemplate = @"{{ ""Message"": {{ ""Subject"": ""{0}"", ""Body"": {{ ""ContentType"": ""Text"", ""Content"": ""{1}"" }}, ""ToRecipients"": [ {{ ""EmailAddress"": {{ ""Address"": ""{2}"" }} }} ], ""Attachments"": [] }}, ""SaveToSentItems"": ""false"" }} "; string message = String.Format(messagetemplate, subject, body, recipient); HttpClient client = new HttpClient(); HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "https://graph.microsoft.com/v1.0/me/sendMail") { Content = new StringContent(message, Encoding.UTF8, "application/json") }; IConfidentialClientApplication app = MsalAppBuilder.BuildConfidentialClientApplication(); AuthenticationResult result = null; var account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetMsalAccountId()); string[] scopes = { "Mail.Send" }; try { // try to get an already cached token result = await app.AcquireTokenSilent(scopes, account).ExecuteAsync().ConfigureAwait(false); } catch (Exception ex) { /* * When the user access this page (from the HTTP GET action result) we check if they have the scope "Mail.Send" and * we handle the additional consent step in case it is needed. Then, we acquire an access token and MSAL cache it for us. * So in this HTTP POST action result, we can always expect a token to be in cache. If they are not in the cache, * it means that the user accessed this route via an unsual way. */ ViewBag.Error = "An error has occurred acquiring the token from cache. Details: " + ex.Message; return(View()); } if (result != null) { // Use the token to send email request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken); HttpResponseMessage response = await client.SendAsync(request); if (response.IsSuccessStatusCode) { ViewBag.AuthorizationRequest = null; return(View("MailSent")); } } return(View()); }