Я использую Angular v6 с шаблоном asp.net core webapi.
Я хочу отправить Xsrf Token в угловое приложение вместе с Identity Authorization
моя проблема начинается, когда пользователь входит в систему. если в HttpContext.User нет пользователя
с токеном проблем нет, но когда пользователь входит в систему и я заново генерирую токен, все мои почтовые запросы завершаются с кодом состояния 400 (из-за неверного Xsrf-токена)
Вот Сервис моей конфигурации:
services.Configure<ApiSettings>(options => Configuration.GetSection("ApiSettings").Bind(options));
services.AddAuthentication(options =>
{
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
options.Audience = "Any";
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidIssuer = "http://localhost:44330/",
ValidAudience = "http://localhost:44330/",
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("VeryStrongKey#123"))
};
});
services.AddIdentity<User, Role>();
services.AddSpaStaticFiles(configuration =>
{
configuration.RootPath = "/Ui";
});
services.AddAntiforgery(x => { x.HeaderName = "X-XSRF-TOKEN";x.Cookie.Name = "XSRF-TOKEN"; });
services.AddMvc(options =>
{
options.Filters.Add(new AutoValidateAntiforgeryTokenAttribute());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
var builder = new ContainerBuilder();
services.AddScoped<IAntiForgeryCookieService, AntiForgeryCookieService>();
services.AddScoped<ITokenStoreService, TokenStoreService>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
builder.Populate(services);
builder.RegisterModule(new ManagementService.Service.DiRegister());
return new AutofacServiceProvider(builder.Build());
и моя конфигурация приложения:
app.UseStaticFiles();
app.UseSpaStaticFiles();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
loggerFactory.AddConsole(this.Configuration.GetSection("Logging"));
loggerFactory.AddDebug();
app.UseAuthentication();
app.UseMvc();
app.UseSpa(spa =>
{
spa.Options.SourcePath = "Ui";
if (env.IsDevelopment())
{
spa.UseAngularCliServer(npmScript: "start");
}
});
вот как я генерирую заявки пользователя после успешного входа в систему:
public async Task<(string AccessToken, List<Claim> claims)> createAccessTokenAsync(User user,List<string> roles)
{
var claims = new List<Claim>
{
// Unique Id for all Jwt tokes
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString(), ClaimValueTypes.String, "http://localhost:44330/"),
// Issuer
new Claim(JwtRegisteredClaimNames.Iss, "http://localhost:44330/", ClaimValueTypes.String, "http://localhost:44330/"),
// Issued at
new Claim(JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds().ToString(), ClaimValueTypes.Integer64, "http://localhost:44330/"),
new Claim(ClaimTypes.NameIdentifier, user.Id.ToString(), ClaimValueTypes.String, "http://localhost:44330/"),
new Claim(ClaimTypes.Name, user.UserName, ClaimValueTypes.String, "http://localhost:44330/"),
new Claim("DisplayName", user.Firstname + " " + user.LastName, ClaimValueTypes.String, "http://localhost:44330/"),
// new Claim(ClaimTypes.SerialNumber, user.SerialNumber, ClaimValueTypes.String, "http://localhost:44330/"),
new Claim(ClaimTypes.UserData, user.Id.ToString(), ClaimValueTypes.String, "http://localhost:44330/")
};
// add roles
//var roles = await _rolesService.FindUserRolesAsync(user.Id);
foreach (var role in roles)
{
claims.Add(new Claim(ClaimTypes.Role, role, ClaimValueTypes.String, "http://localhost:44330/"));
}
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("VeryStrongKey#123"));
var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var now = DateTime.UtcNow;
var token = new JwtSecurityToken(
issuer: "http://localhost:44330/",
audience: "http://localhost:44330/",
claims: claims,
notBefore: now,
expires: now.AddMinutes(20),
signingCredentials: creds);
return (new JwtSecurityTokenHandler().WriteToken(token), claims);
}
и регенерация токена после создания заявки:
public string RegenerateAntiForgeryCookies(ClaimsPrincipal claims)
{
var httpContext = _contextAccessor.HttpContext;
httpContext.User = claims;
// httpContext.SignInAsync(claims);
var tokens = _antiforgery.GetAndStoreTokens(httpContext);
DeleteAntiForgeryCookies();
httpContext.Response.Cookies.Append(
key: XsrfTokenKey,
value: tokens.RequestToken,
options: new CookieOptions
{
HttpOnly = false // Now JavaScript is able to read the cookie
});
return tokens.RequestToken;
}
Я уверен, что клиентское приложение отправит токен:
и я использовал antiforgery.ValidateRequestAsync (HttpContext); для получения точной ошибки: