Аутентификация JWT.NET Core 2.2 не обновляет HttpContext

#c# #asp.net-core #jwt

#c# #asp.net-core #jwt

Вопрос:

Я просмотрел несколько похожих вопросов, но ни один из них мне не помог. У меня следующая ситуация:

Базовая аутентификация JWT в .NET Core 2.2, Startup.cs имеет следующие настройки:

Startup.cs

             public void ConfigureServices(IServiceCollection services)
            {
                ...

                var signingConfigurations = new SigningConfigurations();
                services.AddSingleton(signingConfigurations);
                var tokenConfigurations = new TokenConfigurations();
                new ConfigureFromConfigurationOptions<TokenConfigurations>(
                    Configuration.GetSection("TokenConfigurations"))
                        .Configure(tokenConfigurations);
                services.AddSingleton(tokenConfigurations);

                services.AddAuthentication(authOptions =>
                {
                    authOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                    authOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                }).AddJwtBearer(bearerOptions =>
                {
                    var paramsValidation = bearerOptions.TokenValidationParameters;
                    paramsValidation.IssuerSigningKey = signingConfigurations.Key;
                    paramsValidation.ValidAudience = tokenConfigurations.Audience;
                    paramsValidation.ValidIssuer = tokenConfigurations.Issuer;

                    // Validates a received token signature
                    paramsValidation.ValidateIssuerSigningKey = true;

                    // Verifies if a received token is still valid
                    paramsValidation.ValidateLifetime = true;

                    // Tolerance time for token expiration (used if there are timezone differences)
                    paramsValidation.ClockSkew = TimeSpan.Zero;
                });

                // Activates token usage on this project
                services.AddAuthorization(auth =>
                {
                    auth.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
                        .AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme)
                        .RequireAuthenticatedUser().Build());
                });
  

Затем, чтобы сгенерировать токен:

LoginController.cs

         if (validCredentials)
        {
            ClaimsIdentity declarations = new ClaimsIdentity(
                new GenericIdentity(userInDB.UserName, "Login"),
                new[] {
                    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")),
                    new Claim(JwtRegisteredClaimNames.UniqueName, userInDB.UserName),
                    new Claim("userid", userInDB.Id, ClaimValueTypes.String),
                    new Claim("username", userInDB.UserName, ClaimValueTypes.String),
                }
            );

            DateTime creationDate = DateTime.Now;
            DateTime expirationDate = creationDate  
                TimeSpan.FromSeconds(tokenConfigurations.Seconds);

            var handler = new JwtSecurityTokenHandler();
            var securityToken = handler.CreateToken(new SecurityTokenDescriptor
            {
                Issuer = tokenConfigurations.Issuer,
                Audience = tokenConfigurations.Audience,
                SigningCredentials = signingConfigurations.SigningCredentials,
                Subject = declarations,
                NotBefore = creationDate,
                Expires = expirationDate
            });
            var token = handler.WriteToken(securityToken);

            return new
            {
                authenticated = true,
                created = creationDate.ToString("yyyy-MM-dd HH:mm:ss"),
                expiration = expirationDate.ToString("yyyy-MM-dd HH:mm:ss"),
                accessToken = token,
                message = "OK"
            };
        }
  

Все, что я делал до сих пор, основано на этом пошаговом руководстве

Пока все хорошо. Если я добавляю [Authorize("Bearer")] на контроллере, к нему можно получить доступ, только если у меня есть bearer в заголовке запроса.

Но поскольку я внедрял структуру UserSession, чтобы перехватить любой запрос, пройти через HttpContext и заполнить объект UserSession, это просто не работает. Ответственный метод заключается в следующем:

ApplicationBuilderExtensions.cs

         public static IApplicationBuilder UseSessionConfiguration(
            this IApplicationBuilder builder)
        {
            return builder.UseMiddleware<SessionConfigurationMiddleware>();
        }

        public class SessionConfigurationMiddleware
        {
            private readonly RequestDelegate _next;

            public SessionConfigurationMiddleware(RequestDelegate next)
            {
                _next = next;
            }

            public async Task InvokeAsync(HttpContext context, IUserSession sessao)
            {
                if (context.User.Identities.Any(id => id.IsAuthenticated))
                {
                    sessao.UserId = context.User.Claims.FirstOrDefault(x => x.Type == "userid").Value;
                    sessao.Roles = context.User.Claims.Where(x => x.Type == "http://schemas.microsoft.com/ws/2008/06/identity/claims/role").Select(x => x.Value).ToList();
                    sessao.UserName = context.User.Claims.FirstOrDefault(x => x.Type == "username").Value;
                }

                // Call the next delegate/middleware in the pipeline
                await _next.Invoke(context);
            }
        }
  

Но, поскольку я удаляю эту часть кода (которая корректно вызывается после любого запроса), IsAuthenticated свойство HttpContext всегда равно false, фактически, все равно null или пусто в context.User , и я понятия не имею, почему.

Я неправильно настраиваю jwt?
Неверно ли промежуточное программное обеспечение?
Правильно ли я заполняю утверждения в jwt?
Почему [Authorize("Bearer")] работает корректно, если HttpContext значение заполнено неправильно?
Одни ли мы во вселенной?

Заранее спасибо.

Комментарии:

1. Ваше промежуточное программное обеспечение вызывается до или после приложения. Использовать аутентификацию () в startup.cs?

2. он вызывается после app. Используйте аутентификацию ();

3. @DiegoPenha вы нашли решение этой проблемы?