/// <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));
        }
Esempio n. 3
0
        /// <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());
        }
Esempio n. 5
0
        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);
                    }
                }
            }
        }
Esempio n. 7
0
        // 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."
                });
            }
        }
Esempio n. 8
0
        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);
            }
        }
Esempio n. 9
0
        /// <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);
        }
Esempio n. 11
0
        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);
        }
Esempio n. 12
0
        public static async Task RemoveAccount()
        {
            BuildConfidentialClientApplication();

            var userAccount = await clientapp.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId());

            if (userAccount != null)
            {
                await clientapp.RemoveAsync(userAccount);
            }
        }
Esempio n. 13
0
        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);
        }
Esempio n. 15
0
        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);
        }
Esempio n. 16
0
        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);
        }
Esempio n. 18
0
		/// <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();
        }
Esempio n. 20
0
        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);
        }
Esempio n. 21
0
        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);
        }
Esempio n. 22
0
        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);
            }
        }
Esempio n. 23
0
        /// <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());
        }
Esempio n. 29
0
        /// <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;
            }
        }
Esempio n. 30
0
        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());
        }