Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        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);
                    }
                };
            });
        }