Переопределение OnTokenValidated JwtBearerEvents с пользовательской функцией .NET Core 2 - PullRequest
0 голосов
/ 08 июня 2018

В моем проекте API я обрабатываю аутентификацию с помощью JwtBearer (пользователи входят в систему с помощью Azure).Когда API вызывается, токен проверяется с определенным экземпляром Azure, и все это прекрасно работает.

При успешной проверке токена зарегистрированный пользователь вставляется в нашу собственную базу данных с соответствующими ролями.Теперь это делается следующим образом:

// Add authentication (Azure AD)
            services
                .AddAuthentication(sharedOptions =>
                {
                    sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                    sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; 
                    sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 
                })
                .AddJwtBearer(options =>
                {
                    options.Audience = this.Configuration["AzureAd:ClientId"];
                    options.Authority = $"{this.Configuration["AzureAd:Instance"]}{this.Configuration["AzureAd:TenantId"]}";

                    options.Events = new JwtBearerEvents()
                    {
                        OnTokenValidated = context =>
                        {
                            // Check if the user has an OID claim
                            if (!context.Principal.HasClaim(c => c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier"))
                            {
                                context.Fail($"The claim 'oid' is not present in the token.");
                            }

                            ClaimsPrincipal userPrincipal = context.Principal;

                            // Check is user exists, if not then insert the user in our own database
                            CheckUser cu = new CheckUser(
                                context.HttpContext.RequestServices.GetRequiredService<DBContext>(),
                                context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>(),
                                userPrincipal);

                            cu.CreateUser();

                            return Task.CompletedTask;
                        },
                    };
                });

Это работает нормально, но это не самый красивый / правильный способ сделать это.Я бы сказал, что должен использовать Dependency Injection / Overriding OnTokenValidated событие и интегрировать там логику '1007 *', чтобы класс startup оставался незагроможденным.

К сожалению, мои знания о DI отсутствуют, и яЯ не совсем уверен, что лучший способ это сделать правильно.Поэтому я немного осмотрелся и нашел сообщение, которое точно описывает мою проблему:

Проблемы с обработкой OnTokenValidated делегатом, назначенным в startup.cs

После прочтения этого постаЯ попытался немного изменить его с моей собственной логикой, в результате я получил следующее:

При запуске:

        services.AddScoped<UserValidation>();

        services
            .AddAuthentication(sharedOptions =>
            {
                sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
                sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; 
            })
            .AddJwtBearer(options =>
            {
                options.Audience = this.Configuration["AzureAd:ClientId"];
                options.Authority = $"{this.Configuration["AzureAd:Instance"]}{this.Configuration["AzureAd:TenantId"]}";

                options.EventsType = typeof(UserValidation);
            });

Пользовательские JwtBearerEventsкласс:

public class UserValidation : JwtBearerEvents
    {
        private string UserID { get; set; }

        private string UserEmail { get; set; }

        private string UserName { get; set; }

        public override async Task TokenValidated(TokenValidatedContext context)
        {
            try
            {
                TRSContext context2 = context.HttpContext.RequestServices.GetRequiredService<TRSContext>();
                UserManager<ApplicationUser> userManager = context.HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>();

                ClaimsPrincipal userPrincipal = context.Principal;

                this.UserID = userPrincipal.Claims.First(c => c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier").Value;

                if (userPrincipal.HasClaim(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"))
                {
                    this.UserEmail = userPrincipal.Claims.First(c => c.Type == "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress").Value;
                }

                if (userPrincipal.HasClaim(c => c.Type == "name"))
                {
                    this.UserName = userPrincipal.Claims.First(c => c.Type == "name").Value;
                }

                var checkUser = userManager.FindByIdAsync(this.UserID).Result;
                if (checkUser == null)
                {
                    checkUser = new ApplicationUser
                    {
                        Id = this.UserID,
                        Email = this.UserEmail,
                        UserName = this.UserEmail,
                    };

                    var result = userManager.CreateAsync(checkUser).Result;

                    // Assign Roles
                    if (result.Succeeded)
                    {
                        return;  
                    }
                    else
                    {
                        throw new Exception(result.Errors.First().Description);
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
        }
    }

Однако по какой-то причине это не работает.Нет ошибки, и UserValidation никогда не срабатывает (пытался установить точку отладки, но он никогда не срабатывает), и не добавляет новых пользователей (это происходит при использовании старого кода).

Кто-нибудь знаетчто я делаю не так здесь или, может быть, есть лучшие идеи, как справиться с этим?

...