public async ValueTask <string> CreateJwtTokenAsync(TUser user, string displayName = null) { if (user.Id == default) { user = await _userManager.FindAsync(user); } if (user is null || user.Id == default) { throw new Exception("user not found"); } if (!_identityOptions.AllowMultipleLogins) { if (_jwtIdentityDb.AccessTokens.ToArray().Any(token => token.UserId == user.Id)) { throw new Exception("this user has logged in before"); } } var accessToken = new AccessToken() { Id = Guid.NewGuid(), ExpiresTime = DateTime.Now.Add(_identityOptions.ValidityTime), UserId = user.Id, LastLoginTime = DateTime.Now, LastLoginIp = _context.Connection.RemoteIpAddress.ToString(), LastLoginUserAgent = _context.Request.Headers["User-Agent"][0] }; accessToken = (await _jwtIdentityDb.AddAsync(accessToken)).Entity; await _jwtIdentityDb.SaveChangesAsync(); //return accessToken.Id.ToString(); var keyProvider = new KeyProvider(_identityOptions.SecretKey, KeySize._256); var issuer = _identityOptions.Issuer ?? ""; var claims = new List <Claim> { new Claim(ClaimTypes.NameIdentifier, user.UserName, ClaimValueTypes.String, issuer), new Claim(JwtRegisteredClaimNames.Jti, accessToken.Id.ToString(), ClaimValueTypes.String, issuer), new Claim(JwtRegisteredClaimNames.Iss, issuer, ClaimValueTypes.String, issuer), new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.Now.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64, issuer), }; if (displayName != null) { claims.Add(new Claim(ClaimTypes.Name, displayName, ClaimTypes.Name, issuer)); } claims.AddRange(_jwtIdentityDb.UserRoles .Where(ur => ur.UserId == user.Id) .Select(ur => new Claim(ClaimTypes.Role, ur.Role.Name))); var key = new SymmetricSecurityKey(keyProvider.GetNextKey(256)); var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var now = DateTime.Now; var encryptingCredentials = new EncryptingCredentials(new SymmetricSecurityKey(keyProvider.Key.ToArray()), SecurityAlgorithms.Aes256KW, SecurityAlgorithms.Aes256CbcHmacSha512); var descriptor = new SecurityTokenDescriptor { Audience = _identityOptions.Audience, EncryptingCredentials = _identityOptions.UseEncryption ? encryptingCredentials : null, Expires = now.Add(_identityOptions.ValidityTime), IssuedAt = now, Issuer = issuer, NotBefore = now, SigningCredentials = creds, Subject = new ClaimsIdentity(claims), }; var tokenHandler = new JwtSecurityTokenHandler(); var securityToken = tokenHandler.CreateToken(descriptor); var tokenStr = new JwtSecurityTokenHandler().WriteToken(securityToken); keyProvider.Dispose(); return(tokenStr); }
public static void AddJwtIdentity <TDbContext, TUser>( this IServiceCollection services, JwtIdentityOptions jwtOptions, CryptographyOptions cryptographyOptions) where TDbContext : IdentityDbContext <TUser> where TUser : UserBase { services.AddDbContext <IdentityDbContext <TUser>, TDbContext>(); services.AddScoped <IHasher, Hasher>(s => new Hasher(SHA256.Create())); services.AddScoped <IUserManager <TUser>, UserManager <TUser> >(); services.AddScoped <IJwtAuthManager <TUser>, JwtAuthManager <TUser> >(); services.AddHttpContextAccessor(); services.TryAddSingleton(p => jwtOptions); services.AddAuthentication(options => { options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(config => { config.RequireHttpsMetadata = false; config.SaveToken = true; var keyProvider = new KeyProvider(jwtOptions.SecretKey, cryptographyOptions.KeySize); config.TokenValidationParameters = new TokenValidationParameters { ValidIssuer = jwtOptions.Issuer, ValidateIssuer = false, ValidAudience = jwtOptions.Audience, ValidateAudience = false, IssuerSigningKey = new SymmetricSecurityKey(keyProvider.GetNextKey(256)), ValidateIssuerSigningKey = true, ValidateLifetime = true, ClockSkew = TimeSpan.Zero, TokenDecryptionKey = jwtOptions.UseEncryption ? new SymmetricSecurityKey(keyProvider.Key.ToArray()) : null }; config.Events = new JwtBearerEvents { OnAuthenticationFailed = context => { var logger = context.HttpContext.RequestServices .GetRequiredService <ILoggerFactory>().CreateLogger(nameof(JwtBearerEvents)); logger.LogError("Authentication failed.", context.Exception); return(Task.CompletedTask); }, OnTokenValidated = context => { var tokenValidatorService = context.HttpContext.RequestServices .GetRequiredService <IJwtAuthManager <TUser> >(); return(tokenValidatorService.ValidateAsync(context).AsTask()); }, OnMessageReceived = context => { return(Task.CompletedTask); }, OnChallenge = context => { var logger = context.HttpContext.RequestServices .GetRequiredService <ILoggerFactory>().CreateLogger(nameof(JwtBearerEvents)); logger.LogError("OnChallenge error", context.Error, context.ErrorDescription); return(Task.CompletedTask); } }; }); }