// TokenValidated event private Task TokenValidated(Microsoft.AspNetCore.Authentication.JwtBearer.TokenValidatedContext context) { /* --------------------- * // Replace this with your logic to validate the issuer/tenant * --------------------- * // Retriever caller data from the incoming principal * string issuer = context.SecurityToken.Issuer; * string subject = context.SecurityToken.Subject; * string tenantID = context.Ticket.Principal.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; * * // Build a dictionary of approved tenants * IEnumerable<string> approvedTenantIds = new List<string> * { * "<Your tenantID>", * "9188040d-6c67-4c5b-b112-36a304b66dad" // MSA Tenant * }; * * if (!approvedTenantIds.Contains(tenantID)) * throw new SecurityTokenValidationException(); * --------------------- */ // Store the token in the token cache return(Task.FromResult(0)); }
/// <summary> /// This method contains the logic that validates the user's tenant and normalizes claims. /// </summary> /// <param name="context">The validated token context</param> /// <returns>A task</returns> public override async Task TokenValidated(TokenValidatedContext context) { var principal = context.Ticket.Principal; var tenantManager = context.HttpContext.RequestServices.GetService<TenantManager>(); var userManager = context.HttpContext.RequestServices.GetService<UserManager>(); var issuerValue = principal.GetIssuerValue(); var tenant = await tenantManager.FindByIssuerValueAsync(issuerValue); // the caller comes from an admin-consented, recorded issuer if (tenant == null) { _logger.TokenValidationFailed(principal.GetObjectIdentifierValue(), issuerValue); // the caller was not from a trusted issuer - throw to block the authentication flow throw new SecurityTokenValidationException(); } var identity = principal.Identities.First(); // Adding new Claim for survey_userid var registeredUser = await userManager.FindByObjectIdentifier(principal.GetObjectIdentifierValue()); identity.AddClaim(new Claim(SurveyClaimTypes.SurveyUserIdClaimType, registeredUser.Id.ToString())); identity.AddClaim(new Claim(SurveyClaimTypes.SurveyTenantIdClaimType, registeredUser.TenantId.ToString())); // Adding new Claim for Email var email = principal.FindFirst(ClaimTypes.Upn)?.Value; if (!string.IsNullOrWhiteSpace(email)) { identity.AddClaim(new Claim(ClaimTypes.Email, email)); } _logger.TokenValidationSucceeded(principal.GetObjectIdentifierValue(), issuerValue); }
// TokenValidated event private Task TokenValidated(Microsoft.AspNetCore.Authentication.JwtBearer.TokenValidatedContext context) { //Replace this with your logic to validate the issuer/tenant // Store the token in the token cache return(Task.FromResult(0)); }
// TokenValidated event private Task TokenValidatedAsync(Microsoft.AspNetCore.Authentication.JwtBearer.TokenValidatedContext context) { // Check if tenant is allowed string tenantID = context.Principal.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; if (!_azureOptions.TenantId.Equals(tenantID, StringComparison.InvariantCultureIgnoreCase) && !_azureOptions.AllowedTenants.Any(x => x.Equals(tenantID, StringComparison.InvariantCultureIgnoreCase))) { return(Task.FromException(new SecurityTokenException("The tenant is not allowed."))); } return(Task.FromResult(0)); }
async Task OnTokenValidated(JwtBearer.TokenValidatedContext tokenValidatedContext) { var passed = false; var identity = (ClaimsIdentity)tokenValidatedContext.Principal.Identity; // See if there's a UPN, and if so, use that object id var upn = identity.Claims.FirstOrDefault(c => c.Type == "upn")?.Value; if (upn != null) { var oid = identity.Claims.FirstOrDefault(c => c.Type == "oid")?.Value; // get the user var context = new AuthenticationContext($"{_azureOptions.AADInstance}{_azureOptions.TenantId}", null); // No token caching var credential = new ClientCredential(_azureOptions.ClientId, _azureOptions.ClientSecret); var incomingToken = ((JwtSecurityToken)tokenValidatedContext.SecurityToken).RawData; var result = await context.AcquireTokenAsync(graphResourceId, credential, new UserAssertion(incomingToken)); var url = $"{adminOptions.Value.GraphInstance}{_azureOptions.TenantId}/users/{oid}?api-version=1.6"; GraphUser user = null; using (var client = new HttpClient()) { client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", result.AccessToken); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); var resp = await client.GetAsync(url).ConfigureAwait(false); if (resp.IsSuccessStatusCode) { user = JsonConvert.DeserializeObject <GraphUser>(await resp.Content.ReadAsStringAsync().ConfigureAwait(false)); } } if (user?.SignServiceConfigured == true) { passed = true; identity.AddClaim(new Claim("keyVaultUrl", user.KeyVaultUrl)); identity.AddClaim(new Claim("keyVaultCertificateName", user.KeyVaultCertificateName)); identity.AddClaim(new Claim("timestampUrl", user.TimestampUrl)); identity.AddClaim(new Claim("access_token", incomingToken)); } } if (!passed) { // If we get here, it's an unknown value tokenValidatedContext.Fail("User is not configured"); } telemetryClient.Context.User.AuthenticatedUserId = upn; }
/// <summary> /// In a Web API, adds to the MSAL.NET cache, the account of the user for which a bearer token was received when the Web API was called. /// An access token and a refresh token are added to the cache, so that they can then be used to acquire another token on-behalf-of the /// same user in order to call to downstream APIs. /// </summary> /// <param name="tokenValidationContext">Token validation context passed to the handler of the OnTokenValidated event /// for the JwtBearer middleware</param> /// <param name="scopes">[Optional] scopes to pre-request for a downstream API</param> /// <example> /// From the configuration of the Authentication of the ASP.NET Core Web API (for example in the Startup.cs file) /// <code>JwtBearerOptions option;</code> /// /// Subscribe to the token validated event: /// <code> /// options.Events = new JwtBearerEvents(); /// options.Events.OnTokenValidated = async context => /// { /// var tokenAcquisition = context.HttpContext.RequestServices.GetRequiredService<ITokenAcquisition>(); /// tokenAcquisition.AddAccountToCacheFromJwt(context); /// }; /// </code> /// </example> public void AddAccountToCacheFromJwt(JwtBearer.TokenValidatedContext tokenValidatedContext, IEnumerable <string> scopes) { if (tokenValidatedContext == null) { throw new ArgumentNullException(nameof(tokenValidatedContext)); } AddAccountToCacheFromJwt(scopes, tokenValidatedContext.SecurityToken as JwtSecurityToken, tokenValidatedContext.Properties, tokenValidatedContext.Principal, tokenValidatedContext.HttpContext); }
private Task OnTokenValidated(Microsoft.AspNetCore.Authentication.JwtBearer.TokenValidatedContext context) { // Example of how to validate for Microsoft Account + specific Azure AD tenant // Replace this with your logic to validate the issuer/tenant // Retriever caller data from the incoming principal string issuer = context.SecurityToken.Issuer; string tenantID = context.Principal.FindFirst("http://schemas.microsoft.com/identity/claims/tenantid").Value; // Build a dictionary of approved tenants IEnumerable <string> approvedTenantIds = new List <string> { Configuration["AzureAd:Tenant"], //{tenantid} }; if (!approvedTenantIds.Contains(tenantID)) { throw new SecurityTokenValidationException(); } return(Task.FromResult(0)); }
/// <summary> /// Searches the 'Authorization' header for a 'Bearer' token. If the 'Bearer' token is found, it is validated using <see cref="TokenValidationParameters"/> set in the options. /// </summary> /// <returns></returns> protected override async Task <AuthenticateResult> HandleAuthenticateAsync() { string token = null; try { // Give application opportunity to find from a different location, adjust, or reject token var messageReceivedContext = new MessageReceivedContext(Context, Scheme, Options); // event can set the token await Events.MessageReceived(messageReceivedContext); if (messageReceivedContext.Result != null) { return(messageReceivedContext.Result); } // If application retrieved token from somewhere else, use that. token = messageReceivedContext.Token; if (string.IsNullOrEmpty(token)) { string authorization = Request.Headers["Authorization"]; // If no authorization header found, nothing to process further if (string.IsNullOrEmpty(authorization)) { return(AuthenticateResult.NoResult()); } if (authorization.StartsWith("Bearer ", StringComparison.OrdinalIgnoreCase)) { token = authorization.Substring("Bearer ".Length).Trim(); } // If no token found, no further work possible if (string.IsNullOrEmpty(token)) { return(AuthenticateResult.NoResult()); } } if (_configuration == null && Options.ConfigurationManager != null) { _configuration = await Options.ConfigurationManager.GetConfigurationAsync(Context.RequestAborted); } var validationParameters = Options.TokenValidationParameters.Clone(); if (_configuration != null) { var issuers = new[] { _configuration.Issuer }; validationParameters.ValidIssuers = validationParameters.ValidIssuers?.Concat(issuers) ?? issuers; validationParameters.IssuerSigningKeys = validationParameters.IssuerSigningKeys?.Concat(_configuration.SigningKeys) ?? _configuration.SigningKeys; } List <Exception> validationFailures = null; SecurityToken validatedToken; foreach (var validator in Options.SecurityTokenValidators) { if (validator.CanReadToken(token)) { ClaimsPrincipal principal; try { principal = validator.ValidateToken(token, validationParameters, out validatedToken); } catch (Exception ex) { Logger.TokenValidationFailed(token, ex); // Refresh the configuration for exceptions that may be caused by key rollovers. The user can also request a refresh in the event. if (Options.RefreshOnIssuerKeyNotFound && Options.ConfigurationManager != null && ex is SecurityTokenSignatureKeyNotFoundException) { Options.ConfigurationManager.RequestRefresh(); } if (validationFailures == null) { validationFailures = new List <Exception>(1); } validationFailures.Add(ex); continue; } Logger.TokenValidationSucceeded(); var tokenValidatedContext = new TokenValidatedContext(Context, Scheme, Options) { Principal = principal, SecurityToken = validatedToken }; await Events.TokenValidated(tokenValidatedContext); if (tokenValidatedContext.Result != null) { return(tokenValidatedContext.Result); } if (Options.SaveToken) { tokenValidatedContext.Properties.StoreTokens(new[] { new AuthenticationToken { Name = "access_token", Value = token } }); } tokenValidatedContext.Success(); return(tokenValidatedContext.Result); } } if (validationFailures != null) { var authenticationFailedContext = new AuthenticationFailedContext(Context, Scheme, Options) { Exception = (validationFailures.Count == 1) ? validationFailures[0] : new AggregateException(validationFailures) }; await Events.AuthenticationFailed(authenticationFailedContext); if (authenticationFailedContext.Result != null) { return(authenticationFailedContext.Result); } return(AuthenticateResult.Fail(authenticationFailedContext.Exception)); } return(AuthenticateResult.Fail("No SecurityTokenValidator available for token: " + token ?? "[null]")); } catch (Exception ex) { Logger.ErrorProcessingMessage(ex); var authenticationFailedContext = new AuthenticationFailedContext(Context, Scheme, Options) { Exception = ex }; await Events.AuthenticationFailed(authenticationFailedContext); if (authenticationFailedContext.Result != null) { return(authenticationFailedContext.Result); } throw; } }
/// <summary> /// Invoked after the security token has passed validation and a ClaimsIdentity has been generated. /// </summary> public virtual Task TokenValidated(TokenValidatedContext context) => OnTokenValidated(context);
public virtual Task TokenValidated(TokenValidatedContext context) => OnTokenValidated(context);
private Task JwtBearerTokenValidated(Microsoft.AspNetCore.Authentication.JwtBearer.TokenValidatedContext arg) { _logger.LogDebug("JwtBearerTokenValidated!"); return(Task.FromResult(0)); }
// TokenValidated event private Task TokenValidated(Microsoft.AspNetCore.Authentication.JwtBearer.TokenValidatedContext context) { // Store the token in the token cache return(Task.FromResult(0)); }
private static Task OnTokenValidated(TokenValidatedContext arg) => Task.CompletedTask;
private static Task OnTokenValidated(TokenValidatedContext arg) { Console.WriteLine(arg); return(Task.FromResult(0)); }