// this is how you get tokens obtained by the OIDC middleware //private Task<string> GetAccessTokenAsync() //{ // return httpContextAccessor.HttpContext.GetTokenAsync("access_token"); //} // this is how you get tokens with MSAL private async Task <string> GetAccessTokenAsync() { try { var principal = httpContextAccessor.HttpContext.User; var tokenCache = new DistributedTokenCache(distributedCache, principal.FindFirst(Constants.ObjectIdClaimType).Value).GetMSALCache(); var client = new ConfidentialClientApplication(authOptions.ClientId, authOptions.GetAuthority(principal.FindFirst(Constants.AcrClaimType).Value), "https://app", // it's not really needed new ClientCredential(authOptions.ClientSecret), tokenCache, null); var account = (await client.GetAccountsAsync()).FirstOrDefault(); var result = await client.AcquireTokenSilentAsync(new[] { $"{authOptions.ApiIdentifier}/read_values" }, account); return(result.IdToken); } catch (MsalUiRequiredException) { throw new ReauthenticationRequiredException(); } }
public async Task AuthenticateRequestAsync(HttpRequestMessage request) { var httpContext = _httpContextAccessor.HttpContext; //Get the access token used to call this API string token = await httpContext.GetTokenAsync("access_token"); //We are passing an *assertion* to Azure AD about the current user //Here we specify that assertion's type, that is a JWT Bearer token string assertionType = "urn:ietf:params:oauth:grant-type:jwt-bearer"; //User name is needed here only for ADAL, it is not passed to AAD //ADAL uses it to find a token in the cache if available var user = httpContext.User; string userName = user.FindFirstValue(ClaimTypes.Upn) ?? user.FindFirstValue(ClaimTypes.Email); //_logger.LogInformation("UPN: " + user.FindFirstValue(ClaimTypes.Upn) + ", Email: " + user.FindFirstValue(ClaimTypes.Email)); var userAssertion = new UserAssertion(token, assertionType, userName); //Construct the token cache var cache = new DistributedTokenCache(user, _distributedCache, _loggerFactory, _dataProtectionProvider); var authContext = new AuthenticationContext(_authority, true, cache); var clientCredential = new ClientCredential(_clientId, _clientSecret); //Acquire access token var result = await authContext.AcquireTokenAsync("https://graph.microsoft.com", clientCredential, userAssertion); //Set the authentication header request.Headers.Authorization = new AuthenticationHeaderValue(result.AccessTokenType, result.AccessToken); }
/// <summary> /// Gets an access token from the authority using app only authentication. /// </summary> /// <param name="authority">Address of the authority to issue the token.</param> /// <param name="resource">Identifier of the target resource that is the recipient of the requested token.</param> /// <returns>An instance of <see cref="AuthenticationToken"/> that represented the access token.</returns> /// <exception cref="ArgumentException"> /// <paramref name="authority"/> is empty or null. /// or /// <paramref name="resource"/> is empty or null. /// </exception> public async Task <AuthenticationResult> GetAppOnlyTokenAsync(string authority, string resource) { AuthenticationContext authContext; DistributedTokenCache tokenCache; authority.AssertNotEmpty(nameof(authority)); resource.AssertNotEmpty(nameof(resource)); try { if (service.Cache.IsEnabled) { tokenCache = new DistributedTokenCache(service, resource, $"AppOnly::{resource}"); authContext = new AuthenticationContext(authority, tokenCache); } else { authContext = new AuthenticationContext(authority); } return(await authContext.AcquireTokenAsync( resource, new ClientCredential( service.Configuration.ApplicationId, service.Configuration.ApplicationSecret))); } finally { authContext = null; tokenCache = null; } }
/// <summary> /// Gets an access token from the authority using app + user authentication. /// </summary> /// <param name="authority">Address of the authority to issue the token.</param> /// <param name="resource">Identifier of the target resource that is the recipient of the requested token.</param> /// <returns>An instance of <see cref="AuthenticationToken"/> that represented the access token.</returns> /// <exception cref="ArgumentException"> /// <paramref name="authority"/> is empty or null. /// or /// <paramref name="resource"/> is empty or null. /// </exception> public async Task <AuthenticationToken> GetAppPlusUserTokenAsync(string authority, string resource) { AuthenticationContext authContext; AuthenticationResult authResult; DistributedTokenCache tokenCache; authority.AssertNotEmpty(nameof(authority)); resource.AssertNotEmpty(nameof(resource)); try { if (this.service.Cache.IsEnabled) { tokenCache = new DistributedTokenCache(this.service, resource); authContext = new AuthenticationContext(authority, tokenCache); } else { authContext = new AuthenticationContext(authority); } try { authResult = await authContext.AcquireTokenAsync( resource, new ClientCredential( this.service.Configuration.ApplicationId, this.service.Configuration.ApplicationSecret), new UserAssertion(UserAssertionToken, AssertionType)); } catch (AdalServiceException ex) { if (ex.ErrorCode.Equals("AADSTS70002", StringComparison.CurrentCultureIgnoreCase)) { await this.service.Cache.DeleteAsync(CacheDatabaseType.Authentication); authResult = await authContext.AcquireTokenAsync( resource, new ClientCredential( this.service.Configuration.ApplicationId, this.service.Configuration.ApplicationSecret), new UserAssertion(UserAssertionToken, AssertionType)); } else { throw; } } return(new AuthenticationToken(authResult.AccessToken, authResult.ExpiresOn)); } finally { authContext = null; authResult = null; tokenCache = null; } }
private static OpenIdConnectEvents CreateOpenIdConnectEventHandlers(B2CAuthenticationOptions authOptions, B2CPolicies policies, IDistributedCache distributedCache) { return(new OpenIdConnectEvents { OnRedirectToIdentityProvider = context => SetIssuerAddressAsync(context, policies.SignInOrSignUpPolicy), OnRedirectToIdentityProviderForSignOut = context => SetIssuerAddressForSignOutAsync(context, policies.SignInOrSignUpPolicy), OnAuthorizationCodeReceived = async context => { try { var principal = context.Principal; var userTokenCache = new DistributedTokenCache(distributedCache, principal.FindFirst(Constants.ObjectIdClaimType).Value).GetMSALCache(); var client = new ConfidentialClientApplication(authOptions.ClientId, authOptions.GetAuthority(principal.FindFirst(Constants.AcrClaimType).Value), "https://app", // it's not really needed new ClientCredential(authOptions.ClientSecret), userTokenCache, null); var result = await client.AcquireTokenByAuthorizationCodeAsync(context.TokenEndpointRequest.Code, new[] { $"{authOptions.ApiIdentifier}/read_values" }); context.HandleCodeRedemption(result.AccessToken, result.IdToken); } catch (Exception ex) { context.Fail(ex); } }, OnAuthenticationFailed = context => { context.Fail(context.Exception); return Task.FromResult(0); }, OnMessageReceived = context => { if (!string.IsNullOrEmpty(context.ProtocolMessage.Error) && !string.IsNullOrEmpty(context.ProtocolMessage.ErrorDescription)) { if (context.ProtocolMessage.ErrorDescription.StartsWith("AADB2C90091")) // cancel profile editing { context.HandleResponse(); context.Response.Redirect("/"); } else if (context.ProtocolMessage.ErrorDescription.StartsWith("AADB2C90118")) // forgot password { context.HandleResponse(); context.Response.Redirect("/Account/ResetPassword"); } } return Task.FromResult(0); } }); }
/// <summary> /// Gets an access token from the authority. /// </summary> /// <param name="authority">Address of the authority to issue the token.</param> /// <param name="resource">Identifier of the target resource that is the recipent of the requested token.</param> /// <param name="thumbprint">Thumbprint for the certificate to be used for authentication.</param> /// <returns>An instance of <see cref="AuthenticationResult"/> that represents the access token.</returns> /// <remarks> /// See https://github.com/Azure/azure-content/blob/master/articles/key-vault/key-vault-use-from-web-application.md /// for additional details regarding using this approach for obtaining an access token. /// </remarks> public async Task <AuthenticationResult> GetAppOnlyTokenAsync(string authority, string resource, string thumbprint) { AuthenticationContext authContext; DistributedTokenCache tokenCache; if (string.IsNullOrEmpty(authority)) { throw new ArgumentNullException(nameof(authority)); } if (string.IsNullOrEmpty(resource)) { throw new ArgumentNullException(nameof(resource)); } if (string.IsNullOrEmpty(thumbprint)) { throw new ArgumentNullException(thumbprint); } try { // If the Redis Cache connection string is not populated then utilize the constructor // that only requires the authority. That constructor will utilize a in-memory caching // feature that is built-in into ADAL. if (string.IsNullOrEmpty(Settings.RedisConnection)) { authContext = new AuthenticationContext(authority); } else { tokenCache = new DistributedTokenCache(resource); authContext = new AuthenticationContext(authority, tokenCache); } return(await authContext.AcquireTokenAsync( resource, new ClientAssertionCertificate( Settings.ApplicationId, FindCertificateByThumbprint(thumbprint)))); } finally { authContext = null; tokenCache = null; } }
/// <summary> /// Gets an access token from the authority. /// </summary> /// <param name="authority">Address of the authority to issue the token.</param> /// <param name="resource">Identifier of the target resource that is the recipient of the requested token.</param> /// <param name="credential">The application credential to use for token acquisition.</param> /// <param name="token">Assertion token representing the user.</param> /// <returns>An instance of <see cref="AuthenticationResult"/> that represented the access token.</returns> /// <exception cref="System.ArgumentException"> /// <paramref name="authority"/> is empty or null. /// or /// <paramref name="resource"/> is empty or null. /// or /// <paramref name="token"/> is empty or null. /// </exception> /// <exception cref="System.ArgumentNullException"> /// <paramref name="credential"/> is null. /// </exception> public async Task <AuthenticationResult> GetAccessTokenAsync(string authority, string resource, ApplicationCredential credential, string token) { AuthenticationContext authContext; AuthenticationResult authResult; DistributedTokenCache tokenCache; ISecureClientSecret secret; authority.AssertNotEmpty(nameof(authority)); resource.AssertNotEmpty(nameof(authority)); credential.AssertNotNull(nameof(credential)); token.AssertNotEmpty(nameof(token)); try { if (credential.UseCache) { tokenCache = new DistributedTokenCache(provider, resource); authContext = new AuthenticationContext(authority, tokenCache); } else { authContext = new AuthenticationContext(authority); } secret = new SecureClientSecret(credential.ApplicationSecret); authResult = await authContext.AcquireTokenAsync( resource, new ClientCredential( credential.ApplicationId, secret), new UserAssertion(token, AssertionType)).ConfigureAwait(false); return(authResult); } finally { authContext = null; tokenCache = null; secret = null; } }
/// <summary> /// Gets an access token from the authority. /// </summary> /// <param name="authority">Address of the authority to issue the token.</param> /// <param name="resource">Identifier of the target resource that is the recipient of the requested token.</param> /// <param name="credential">The application credential to use for token acquisition.</param> /// <returns>An instance of <see cref="AuthenticationResult"/> that represented the access token.</returns> /// <exception cref="System.ArgumentException"> /// <paramref name="authority"/> is empty or null. /// or /// <paramref name="resource"/> is empty or null. /// </exception> /// <exception cref="System.ArgumentNullException"> /// <paramref name="credential"/> is null. /// </exception> public async Task <AuthenticationResult> GetAccessTokenAsync(string authority, string resource, ApplicationCredential credential) { AuthenticationContext authContext; AuthenticationResult authResult; DistributedTokenCache tokenCache; Microsoft.IdentityModel.Clients.ActiveDirectory.ISecureClientSecret secret; authority.AssertNotEmpty(nameof(authority)); resource.AssertNotEmpty(nameof(resource)); credential.AssertNotNull(nameof(credential)); try { if (credential.UseCache) { tokenCache = new DistributedTokenCache(provider, resource, $"AppOnly::{authority}::{resource}"); authContext = new AuthenticationContext(authority, tokenCache); } else { authContext = new AuthenticationContext(authority); } secret = new SecureClientSecret(credential.ApplicationSecret); authResult = await authContext.AcquireTokenAsync( resource, new ClientCredential( credential.ApplicationId, secret)).ConfigureAwait(false); return(authResult); } finally { authContext = null; authResult = null; secret = null; tokenCache = null; } }
/// <summary> /// Gets an access token from the authority. /// </summary> /// <param name="authority">Address of the authority to issue the token.</param> /// <param name="resource">Identifier of the target resource that is the recipent of the requested token.</param> /// <returns>An instnace of <see cref="AuthenticationResult"/> that represented the access token.</returns> /// <exception cref="ArgumentNullException"> /// authority /// or /// resource /// </exception> public async Task <AuthenticationResult> GetAppPlusUserTokenAsync(string authority, string resource) { AuthenticationContext authContext; DistributedTokenCache tokenCache; if (string.IsNullOrEmpty(authority)) { throw new ArgumentNullException(nameof(authority)); } if (string.IsNullOrEmpty(resource)) { throw new ArgumentNullException(nameof(resource)); } try { // If the Redis Cache connection string is not populated then utilize the constructor // that only requires the authority. That constructor will utilize a in-memory caching // feature that is built-in into ADAL. if (string.IsNullOrEmpty(Settings.RedisConnection)) { authContext = new AuthenticationContext(authority); } else { tokenCache = new DistributedTokenCache(resource); authContext = new AuthenticationContext(authority, tokenCache); } return(await authContext.AcquireTokenAsync( resource, new ClientCredential( Settings.ApplicationId, Settings.ApplicationSecret), new UserAssertion(UserAssertionToken, "urn:ietf:params:oauth:grant-type:jwt-bearer"))); } finally { authContext = null; tokenCache = null; } }
/// <summary> /// Asynchronously obtains an Azure AD token for the specified resource. /// </summary> /// <param name="authority">Authority used to obtain the token.</param> /// <param name="resource">Identifier of the target resource that is the recipient of the requested token.</param> /// <returns></returns> /// <exception cref="ArgumentNullException"> /// authority /// or /// resource /// </exception> /// <remarks>This function obtains a token for the specified resource on behalf the current authenticated user.</remarks> public static async Task <AuthenticationResult> GetAADTokenAsync(string authority, string resource) { AuthenticationContext authContext; DistributedTokenCache tokenCache; if (string.IsNullOrEmpty(authority)) { throw new ArgumentNullException(nameof(authority)); } if (string.IsNullOrEmpty(resource)) { throw new ArgumentNullException(nameof(resource)); } try { if (string.IsNullOrEmpty(AppConfig.RedisConnection)) { authContext = new AuthenticationContext(authority); } else { tokenCache = new DistributedTokenCache(resource); authContext = new AuthenticationContext(authority, tokenCache); } return(await authContext.AcquireTokenAsync( resource, new ClientCredential( AppConfig.ApplicationId, AppConfig.ApplicationSecret), new UserAssertion(UserAssertionToken, "urn:ietf:params:oauth:grant-type:jwt-bearer"))); } finally { authContext = null; tokenCache = null; } }
/// <summary> /// Gets an access token utilizing an authorization code. /// </summary> /// <param name="authority">Address of the authority to issue the token.</param> /// <param name="code">Authorization code received from the service authorization endpoint.</param> /// <param name="resource">Identifier of the target resource that is the recipient of the requested token.</param> /// <param name="redirectUri">Redirect URI used for obtain the authorization code.</param> /// <returns>An instance of <see cref="AuthenticationToken"/> that represented the access token.</returns> /// <exception cref="ArgumentException"> /// authority /// or /// code /// or /// resource /// </exception> /// <exception cref="ArgumentNullException"> /// redirectUri /// </exception> public async Task <AuthenticationToken> GetTokenByAuthorizationCodeAsync(string authority, string code, string resource, Uri redirectUri) { AuthenticationContext authContext; AuthenticationResult authResult; DistributedTokenCache tokenCache; authority.AssertNotEmpty(nameof(authority)); code.AssertNotEmpty(nameof(code)); redirectUri.AssertNotNull(nameof(redirectUri)); resource.AssertNotEmpty(nameof(resource)); try { if (this.service.Cache.IsEnabled) { tokenCache = new DistributedTokenCache(this.service, resource); authContext = new AuthenticationContext(authority, tokenCache); } else { authContext = new AuthenticationContext(authority); } authResult = await authContext.AcquireTokenByAuthorizationCodeAsync( code, redirectUri, new ClientCredential( this.service.Configuration.ApplicationId, this.service.Configuration.ApplicationSecret), resource); return(new AuthenticationToken(authResult.AccessToken, authResult.ExpiresOn)); } finally { authContext = null; tokenCache = null; } }
public ActionResult Logout() { string userObjectId = User.GetObjectIdentifierValue(); //Get an instance of the token cache for the current user request IDistributedCache distributedCache = HttpContext.RequestServices.GetRequiredService <IDistributedCache>(); var cache = new DistributedTokenCache(User, distributedCache); AuthenticationContext authContext = new AuthenticationContext(Startup._authority, cache); authContext.TokenCache.Clear(); //Explicitly delete the cookie(this is an IE compatability thing) Response.Cookies.Delete("thing_faceter_AUTH"); // Let Azure AD sign-out return(SignOut( new AuthenticationProperties { RedirectUri = _environmentOptions.Post_Logout_Redirect_Uri }, CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme )); }