Чтение токена JWT из API в ASP.NET Core - PullRequest
1 голос
/ 12 марта 2019

Мои настройки: я создал и запустил решение WebAPI, которое выполняет аутентификацию имени пользователя и пароля по отношению к источнику (в настоящее время это БД). Это создает токен JWT и возвращает его запрашивающему приложению (приложению ASP.NET Core 2.2).

В большинстве решений говорится о защите открытых методов WebAPI, но мой подход заключается в том, чтобы выполнять аутентификацию только через WebAPI. Отдельные приложения должны принимать токен, чтобы они могли определять авторизацию.

Теперь вопрос: каков наилучший подход к чтению токена из WebAPI (который я уже сделал), его проверке и сохранению для любого / всех контроллеров, чтобы узнать, что есть аутентифицированный пользователь (через Authorize) атрибут), пока токен действителен?

Отладка этого больше, похоже, мой токен не добавляется в заголовки. Я вижу это сообщение отладки:

Ошибка авторизации для запроса в фильтре 'Microsoft.AspNet.Mvc.Filters.AuthorizeFilter'

Обновление кода2 - код, который получает JWT:

        var client = _httpClientFactory.CreateClient();
        client.BaseAddress = new Uri(_configuration.GetSection("SecurityApi:Url").Value);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

        //login
        Task<HttpResponseMessage> response = ValidateUserAsync(client, username, password);
        Task<Core.Identity.TokenViewModel> tokenResult = response.Result.Content.ReadAsAsync<Core.Identity.TokenViewModel>();

        if (!response.Result.IsSuccessStatusCode)
        {
            if (tokenResult != null && tokenResult.Result != null)
            {
                ModelState.AddModelError("", tokenResult.Result.ReasonPhrase);
            }
            else
            {
                ModelState.AddModelError("", AppStrings.InvalidLoginError);
            }
            return View();
        }

        JwtSecurityToken token = new JwtSecurityToken(tokenResult.Result.Token);
        int userId;

        if (int.TryParse(token.Claims.First(s => s.Type == JwtRegisteredClaimNames.NameId).Value, out userId))
        {
            //load app claims
            Core.Identity.UserInfo userInfo = Core.Identity.UserLogin.GetUser(_identityCtx, userId);
            Core.Identity.UserStore uStore = new Core.Identity.UserStore(_identityCtx);
            IList<Claim> claims = uStore.GetClaimsAsync(userInfo, new System.Threading.CancellationToken(false)).Result;
            claims.Add(new Claim(Core.Identity.PowerFleetClaims.PowerFleetBaseClaim, Core.Identity.PowerFleetClaims.BaseUri));

            ClaimsIdentity claimsIdentity = new ClaimsIdentity(claims, JwtBearerDefaults.AuthenticationScheme);
            ClaimsPrincipal principal = new ClaimsPrincipal(claimsIdentity);

            //complete
            AuthenticationProperties authProperties = new AuthenticationProperties();
            authProperties.ExpiresUtc = token.ValidTo;
            authProperties.AllowRefresh = false;
            authProperties.IsPersistent = true;

            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(JwtBearerDefaults.AuthenticationScheme, tokenResult.Result.Token);
            //var stuff = HttpContext.SignInAsync(JwtBearerDefaults.AuthenticationScheme, principal, authProperties);
        }
        else
        {
            ModelState.AddModelError("", AppStrings.InvalidLoginError);
            return View();
        }

        return RedirectToAction("Index", "Home");

Запуск:

private void ConfigureIdentityServices(IServiceCollection services)
    {
        services.ConfigureApplicationCookie(options => options.LoginPath = "/Login");

        //authentication token
        services.AddAuthentication(opt =>
        {
            opt.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            opt.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddCookie(opt =>
        {
            opt.LoginPath = "/Login";
            opt.LogoutPath = "/Login/Logoff";
            opt.Cookie.Name = Configuration.GetSection("SecurityApi:CookieName").Value;
        }).AddJwtBearer(options =>
        {
            options.SaveToken = true;
            options.RequireHttpsMetadata = false;

            options.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidateAudience = true,
                ValidAudience = Configuration.GetSection("SecurityApi:Issuer").Value,
                ValidateIssuer = true,
                ValidIssuer = Configuration.GetSection("SecurityApi:Issuer").Value,
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("SecurityApi:Key").Value)),
                ValidateLifetime = true
            };
        });

        Core.Startup authStart = new Core.Startup(this.Configuration);
        authStart.ConfigureAuthorizationServices(services);
    }

Auth:

public void ConfigureAuthorizationServices(IServiceCollection services)
    {
        services.AddDbContext<Identity.IdentityContext>(options => options.UseSqlServer(Configuration.GetConnectionString("SecurityConn")));
        services.AddScoped<DbContext, Identity.IdentityContext>(f =>
        {
            return f.GetService<Identity.IdentityContext>();
        });

        services.AddIdentityCore<Identity.UserInfo>().AddEntityFrameworkStores<Identity.IdentityContext>().AddRoles<Identity.Role>();
        services.AddTransient<IUserClaimStore<Core.Identity.UserInfo>, Core.Identity.UserStore>();
        services.AddTransient<IUserRoleStore<Core.Identity.UserInfo>, Core.Identity.UserStore>();
        services.AddTransient<IRoleStore<Core.Identity.Role>, Core.Identity.RoleStore>();

        services.AddAuthorization(auth =>
        {
            auth.AddPolicy(JwtBearerDefaults.AuthenticationScheme, new AuthorizationPolicyBuilder().AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme).RequireAuthenticatedUser().Build());
            auth.AddPolicy(PFBaseClaim, policy => policy.RequireClaim(Identity.PFClaims.BaseUri));
        });
    }

1 Ответ

0 голосов
/ 27 марта 2019

В конце концов, мой подход состоял в том, чтобы использовать безопасный cookie-файл и базовое требование для подтверждения подлинности пользователя.

private void ConfigureAuthentication (службы IServiceCollection) { services.ConfigureApplicationCookie (options => options.LoginPath = "/ Login");

        //authentication token
        services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(opt =>
        {
            opt.LoginPath = "/Login";
            opt.AccessDeniedPath = "/Login";
            opt.LogoutPath = "/Login/Logoff";
            opt.Cookie.Name = Configuration.GetSection("SecurityApi:CookieName").Value;
        }).AddJwtBearer(options =>
        {
            options.SaveToken = true;

            options.TokenValidationParameters = new TokenValidationParameters()
            {
                ValidateAudience = true,
                ValidAudience = Configuration.GetSection("SecurityApi:Issuer").Value,
                ValidateIssuer = true,
                ValidIssuer = Configuration.GetSection("SecurityApi:Issuer").Value,
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration.GetSection("SecurityApi:Key").Value)),
                ValidateLifetime = true
            };
        });
    }

А при входе в систему:

            AuthenticationProperties authProperties = new AuthenticationProperties();
        authProperties.ExpiresUtc = token.ValidTo;
        authProperties.AllowRefresh = false;
        authProperties.IsPersistent = true;

        HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, userStore.CreateAsync(user).Result, authProperties);

        return RedirectToAction("Index", "Home");
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...