private async Task <AuthenticationTicket> CreateTicketAsync(OpenIdConnectRequest request, UserEntity user) { var principal = await _signInManager.CreateUserPrincipalAsync(user); var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); ticket.SetAccessTokenLifetime(TimeSpan.FromDays(7)); // Explicitly specify which claims should be included in the access token foreach (var claim in ticket.Principal.Claims) { // Never include the security stamp (it's a secret value) if (claim.Type == _identityOptions.Value.ClaimsIdentity.SecurityStampClaimType) { continue; } // TODO: If there are any other private/secret claims on the user that should // not be exposed publicly, handle them here! // The token is encoded but not encrypted, so it is effectively plaintext. claim.SetDestinations(OpenIdConnectConstants.Destinations.AccessToken); } return(ticket); }
private AuthenticationTicket CreateApplicationTicket(OpenIdConnectRequest request, Applications application) { // Create a new ClaimsIdentity containing the claims that // will be used to create an id_token, a token or a code. var identity = new ClaimsIdentity( OpenIdConnectServerDefaults.AuthenticationScheme, OpenIdConnectConstants.Claims.Name, OpenIdConnectConstants.Claims.Role); // Use the client_id as the subject identifier. identity.AddClaim(OpenIdConnectConstants.Claims.Subject, application.ClientId, OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); identity.AddClaim(OpenIdConnectConstants.Claims.Name, application.DisplayName, OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); identity.AddClaim("grant_type", request.GrantType, OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); ticket.SetAccessTokenLifetime(TimeSpan.FromHours(48)); return(ticket); }
private async Task <AuthenticationTicket> CreateTicketAsync(OpenIdConnectRequest request, ApplicationUser user) { // Create a new ClaimsPrincipal containing the claims that // will be used to create an id_token, a token or a code. var principal = await _signInManager.CreateUserPrincipalAsync(user); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket(principal, new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); // Set the list of scopes granted to the client application. ticket.SetScopes(new[] { OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.Email, OpenIdConnectConstants.Scopes.Profile, OpenIddictConstants.Scopes.Roles }.Intersect(request.GetScopes())); ticket.SetResources("resource-server"); // Note: by default, claims are NOT automatically included in the access and identity tokens. // To allow OpenIddict to serialize them, you must attach them a destination, that specifies // whether they should be included in access tokens, in identity tokens or in both. foreach (var claim in ticket.Principal.Claims) { // Never include the security stamp in the access and identity tokens, as it's a secret value. if (claim.Type == _identityOptions.Value.ClaimsIdentity.SecurityStampClaimType) { continue; } var destinations = new List <string> { OpenIdConnectConstants.Destinations.AccessToken }; // Only add the iterated claim to the id_token if the corresponding scope was granted to the client application. // The other claims will only be added to the access_token, which is encrypted when using the default format. if ((claim.Type == OpenIdConnectConstants.Claims.Name && ticket.HasScope(OpenIdConnectConstants.Scopes.Profile)) || (claim.Type == OpenIdConnectConstants.Claims.Email && ticket.HasScope(OpenIdConnectConstants.Scopes.Email)) || (claim.Type == OpenIdConnectConstants.Claims.Role && ticket.HasScope(OpenIddictConstants.Claims.Roles))) { destinations.Add(OpenIdConnectConstants.Destinations.IdentityToken); } claim.SetDestinations(destinations); } ticket.SetAccessTokenLifetime(TimeSpan.FromHours(8)); return(ticket); }
public void SetAccessTokenLifetime_AddsLifetime(string lifetime) { // Arrange var ticket = new AuthenticationTicket( new ClaimsIdentity(), new AuthenticationProperties()); // Act ticket.SetAccessTokenLifetime(lifetime != null ? (TimeSpan?)TimeSpan.ParseExact(lifetime, "c", CultureInfo.InvariantCulture) : null); // Assert Assert.Equal(lifetime, ticket.GetProperty(OpenIdConnectConstants.Properties.AccessTokenLifetime)); }
private async Task <AuthenticationTicket> CreateTicketAsync(OpenIdConnectRequest request, ApplicationUser user, AuthenticationProperties properties = null) { var principal = await _signInManager.CreateUserPrincipalAsync(user); var ticket = new AuthenticationTicket(principal, properties, OpenIdConnectServerDefaults.AuthenticationScheme); if (request.IsPasswordGrantType()) { ticket.SetScopes(new[] { OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.Email, OpenIdConnectConstants.Scopes.Profile, OpenIdConnectConstants.Scopes.OfflineAccess, OpenIddictConstants.Scopes.Roles, }.Intersect(request.GetScopes())); } ticket.SetResources(_appConfig.Jwt.Audiences); foreach (Claim claim in ticket.Principal.Claims.Where(x => x.Type != _identityOptions.Value.ClaimsIdentity.SecurityStampClaimType)) { List <string> destinations = new List <string> { OpenIdConnectConstants.Destinations.AccessToken }; if (claim.Type == OpenIdConnectConstants.Claims.Name && ticket.HasScope(OpenIdConnectConstants.Scopes.Profile) || claim.Type == OpenIdConnectConstants.Claims.Email && ticket.HasScope(OpenIdConnectConstants.Scopes.Email) || claim.Type == OpenIdConnectConstants.Claims.Role && ticket.HasScope(OpenIddictConstants.Claims.Roles)) { destinations.Add(OpenIdConnectConstants.Destinations.IdentityToken); } claim.SetDestinations(destinations); } ticket.SetAccessTokenLifetime(TimeSpan.FromHours(5)); return(ticket); }
// Source: https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server public static void AddAuthenticationServer(this IServiceCollection services) { var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(SecretKey)); services.AddAuthentication().AddOpenIdConnectServer(options => { options.AccessTokenHandler = new JwtSecurityTokenHandler(); options.SigningCredentials.AddKey(signingKey); options.AllowInsecureHttp = true; options.TokenEndpointPath = "/token"; options.Provider.OnValidateTokenRequest = context => { context.Validate(); return(Task.CompletedTask); }; options.Provider.OnHandleTokenRequest = context => { if (context.Request.Password != "dotnetify") { context.Reject( error: OpenIdConnectConstants.Errors.InvalidGrant, description: "Invalid user credentials."); return(Task.CompletedTask); } var identity = new ClaimsIdentity(context.Scheme.Name, OpenIdConnectConstants.Claims.Name, OpenIdConnectConstants.Claims.Role); identity.AddClaim(OpenIdConnectConstants.Claims.Name, context.Request.Username); identity.AddClaim(OpenIdConnectConstants.Claims.Subject, context.Request.Username); identity.AddClaim(ClaimTypes.Name, context.Request.Username, OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); if (context.Request.Username == "admin") { identity.AddClaim(ClaimTypes.Role, "admin", OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); } var ticket = new AuthenticationTicket( new ClaimsPrincipal(identity), new AuthenticationProperties(), context.Scheme.Name); ticket.SetAccessTokenLifetime(System.TimeSpan.FromSeconds(30)); ticket.SetScopes( OpenIdConnectConstants.Scopes.Profile, OpenIdConnectConstants.Scopes.OfflineAccess); context.Validate(ticket); return(Task.CompletedTask); }; }); }
public async Task <IActionResult> Token(OpenIdConnectRequest requestModel) { if (!requestModel.IsPasswordGrantType()) { // Return bad request if the request is not for password grant type return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.UnsupportedGrantType, ErrorDescription = "The specified grant type is not supported." })); } var user = await userManager.FindByNameAsync(requestModel.Username); if (user == null) { // Return bad request if the user doesn't exist return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, ErrorDescription = "Invalid username or password" })); } // Check that the user can sign in and is not locked out. // If two-factor authentication is supported, it would also be appropriate to check that 2FA is enabled for the user if (!await signInManager.CanSignInAsync(user) || (userManager.SupportsUserLockout && await userManager.IsLockedOutAsync(user))) { // Return bad request is the user can't sign in return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, ErrorDescription = "The specified user cannot sign in." })); } if (!await userManager.CheckPasswordAsync(user, requestModel.Password)) { // Return bad request if the password is invalid return(BadRequest(new OpenIdConnectResponse { Error = OpenIdConnectConstants.Errors.InvalidGrant, ErrorDescription = "Invalid username or password" })); } // The user is now validated, so reset lockout counts, if necessary if (userManager.SupportsUserLockout) { await userManager.ResetAccessFailedCountAsync(user); } // Create the principal var principal = await signInManager.CreateUserPrincipalAsync(user); // Claims will not be associated with specific destinations by default, so we must indicate whether they should // be included or not in access and identity tokens. foreach (var claim in principal.Claims) { // For this sample, just include all claims in all token types. // In reality, claims' destinations would probably differ by token type and depending on the scopes requested. claim.SetDestinations(OpenIdConnectConstants.Destinations.AccessToken, OpenIdConnectConstants.Destinations.IdentityToken); } // Create a new authentication ticket for the user's principal var ticket = new AuthenticationTicket( principal, new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); // Include resources and scopes, as appropriate var scope = new[] { OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.Email, OpenIdConnectConstants.Scopes.Profile, OpenIdConnectConstants.Scopes.OfflineAccess, OpenIddictConstants.Scopes.Roles }.Intersect(requestModel.GetScopes()); ticket.SetScopes(scope); ticket.SetAccessTokenLifetime(new TimeSpan(3, 0, 0)); ticket.SetAuthorizationCodeLifetime(new TimeSpan(3, 0, 0)); // Sign in the user return(SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme)); }
private async Task <AuthenticationTicket> CreateTicketAsync( OpenIdConnectRequest request, ApplicationUser user, AuthenticationProperties properties = null) { // Create a new ClaimsPrincipal containing the claims that // will be used to create an id_token, a token or a code. var principal = await _signInManager.CreateUserPrincipalAsync(user); // Create a new authentication ticket holding the user identity. var ticket = new AuthenticationTicket(principal, properties ?? new AuthenticationProperties(), OpenIdConnectServerDefaults.AuthenticationScheme); // Set the list of scopes granted to the client application. // Note: the offline_access scope must be granted // to allow OpenIddict to return a refresh token. var roleNames = await _userManager.GetRolesAsync(user); var identity = ticket.Principal.Identity as ClaimsIdentity; if (!request.IsAuthorizationCodeGrantType()) { var scopes = new List <string> { OpenIdConnectConstants.Scopes.OpenId, OpenIdConnectConstants.Scopes.Email, OpenIdConnectConstants.Scopes.Profile, OpenIdConnectConstants.Scopes.OfflineAccess, OpenIddictConstants.Scopes.Roles }.Intersect(request.GetScopes()).ToList(); ticket.SetScopes(scopes); } // Note: by default, claims are NOT automatically included in the access and identity tokens. // To allow OpenIddict to serialize them, you must attach them a destination, that specifies // whether they should be included in access tokens, in identity tokens or in both. foreach (var claim in ticket.Principal.Claims) { // Never include the security stamp in the access and identity tokens, as it's a secret value. if (claim.Type == _identityOptions.Value.ClaimsIdentity.SecurityStampClaimType) { continue; } // Only add the iterated claim to the id_token if the corresponding scope was granted to the client application. // The other claims will only be added to the access_token, which is encrypted when using the default format. if ((claim.Type == OpenIdConnectConstants.Claims.Name && ticket.HasScope(OpenIdConnectConstants.Scopes.Profile)) || (claim.Type == OpenIdConnectConstants.Claims.Email && ticket.HasScope(OpenIdConnectConstants.Scopes.Email)) || (claim.Type == OpenIdConnectConstants.Claims.Role && ticket.HasScope(OpenIddictConstants.Claims.Roles))) { var type = claim.Type; claim.SetDestinations(OpenIdConnectConstants.Destinations.IdentityToken, OpenIdConnectConstants.Destinations.AccessToken); } else { claim.SetDestinations(OpenIdConnectConstants.Destinations.AccessToken); } } if (_appOptions.TokenGeneration.Audiences.Any()) { foreach (var audience in _appOptions.TokenGeneration.Audiences) { ticket.SetAudiences(audience); } } if (_appOptions.TokenGeneration.Resources.Any()) { foreach (var resource in _appOptions.TokenGeneration.Resources) { ticket.SetResources(resource); } } if (_appOptions.TokenGeneration.IncludeUserIdClaim) { AddUserIdClaim(ticket, user); } ticket.SetAccessTokenLifetime(TimeSpan.FromSeconds(_appOptions.TokenGeneration.AccessTokenLifetime)); ticket.SetIdentityTokenLifetime(TimeSpan.FromSeconds(_appOptions.TokenGeneration.IdentityTokenLifetime)); ticket.SetRefreshTokenLifetime(TimeSpan.FromSeconds(_appOptions.TokenGeneration.RefreshTokenLifetime)); return(ticket); }