I am trying to use JwtBearerAuthentication in Asp core 2.0 and I've encountered two main issues.
The Configure method of startup is like this:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseWebpackDevMiddleware(new WebpackDevMiddlewareOptions
{
HotModuleReplacement = true
});
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseTestSensitiveConfiguration(null);
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
routes.MapSpaFallbackRoute(
name: "spa-fallback",
defaults: new { controller = "Home", action = "Index" });
});
}
and the ConfigureServices like bellow:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver())
.AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
services.AddDbContext<FGWAContext>(options => options.UseSqlServer(connection));
services.AddIdentity<User, Role>()
.AddEntityFrameworkStores<FGWAContext>()
.AddDefaultTokenProviders();
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = false;
options.Password.RequiredLength = 4;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
options.Password.RequireLowercase = false;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
// User settings
options.User.RequireUniqueEmail = true;
});
//// If you want to tweak Identity cookies, they're no longer part of IdentityOptions.
//services.ConfigureApplicationCookie(options => options.LoginPath = "/Account/LogIn");
//services.AddAuthentication();
//// If you don't want the cookie to be automatically authenticated and assigned to HttpContext.User,
//// remove the CookieAuthenticationDefaults.AuthenticationScheme parameter passed to AddAuthentication.
//services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
// .AddCookie(options =>
// {
// options.LoginPath = "/Account/LogIn";
// options.LogoutPath = "/Account/LogOff";
// });
//services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
// .AddJwtBearer(jwtBearerOptions =>
// {
// //jwtBearerOptions.Events.OnChallenge = context =>
// //{
// // context.Response.Headers["Location"] = context.Request.Path.Value;
// // context.Response.StatusCode = 401;
// // return Task.CompletedTask;
// //};
// jwtBearerOptions.TokenValidationParameters = new TokenValidationParameters
// {
// ValidateIssuerSigningKey = true,
// IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("your secret goes here")),
// ValidateIssuer = true,
// ValidIssuer = "The name of the issuer",
// ValidateAudience = true,
// ValidAudience = "The name of the audience",
// ValidateLifetime = true, //validate the expiration and not before values in the token
// ClockSkew = TimeSpan.FromMinutes(5) //5 minute tolerance for the expiration date
// };
// });
// Enable Dual Authentication
services.AddAuthentication()
.AddCookie(cfg => cfg.SlidingExpiration = true)
.AddJwtBearer(cfg =>
{
cfg.RequireHttpsMetadata = false;
cfg.SaveToken = true;
cfg.TokenValidationParameters = new TokenValidationParameters()
{
ValidIssuer = Configuration["Tokens:Issuer"],
ValidAudience = Configuration["Tokens:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Tokens:Key"]))
};
});
services.AddTransient<IModelsService, ModelsService>();
services.AddTransient<IRestaurantService, RestaurantService>();
}
and the two main issues:
1- It does not work! I call the method to generate token http://localhost:59699/api/accountapi/login
the the answer is something like this:
{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmb29kdGVzdGdldHVzckBnbWFpbC5jb20iLCJqdGkiOiIyZGQ0MDhkNy02NDE4LTQ2MGItYTUxYi1hNTYzN2Q0YWYyYzgiLCJpYXQiOiIxMC8xMi8yMDE3IDM6NDA6MDYgQU0iLCJuYmYiOjE1MDc3Nzk2MDYsImV4cCI6MTUwNzc3OTkwNiwiaXNzIjoiRXhhbXBsZUlzc3VlciIsImF1ZCI6IkV4YW1wbGVBdWRpZW5jZSJ9.of-kTEIG8bOoPfyCQjuP7s6Zm32yFFPlW_T61OT8Hqs","expires_in":300}
then I call the protected resource this way:
but the protected resource is not accessible.
2- After failure to authenticate, it redirects the request to login page. How can I disable this auto challenge behavior?
before you start answering I have to tell that, I have tried https://wildermuth.com/2017/08/19/Two-AuthorizationSchemes-in-ASP-NET-Core-2 to craete the authentication and this https://learn.microsoft.com/en-us/aspnet/core/migration/1x-to-2x/identity-2x too; and also this ASP.NET Core 2.0 disable automatic challenge to disable auto challenge, but non of them worked.
Update
The desired config is to use jwtbearerauthentication on webapi calls and for the others use cookie. Then while using the former I want to return not authorized (401) response on a not authorized request while for the later one I want a redirection.