Cannot access [Authorize] controllers with cookie authentication - asp.net-core

I'm using .NET Core 3.1 and Cookie authentication to login.
I saw the cookie generated as the picture below, but I still cannot access [Authorize] controllers.
This is my code in Startup.cs
ConfigureServices(IServiceCollection services)
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.Lax;
});
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.Cookie.Name = "SRLoginCookie";
options.Cookie.HttpOnly = true;
options.LoginPath = new PathString("/users/login");
options.ExpireTimeSpan = TimeSpan.FromDays(1);
options.SlidingExpiration = false;
});
services.PostConfigure<CookieAuthenticationOptions>(IdentityConstants.ApplicationScheme,
options =>
{
options.LoginPath = "/users/login";
});
Configure(IApplicationBuilder app)
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
Login code
[HttpPost]
[Route("login")]
[AllowAnonymous]
public async Task<ActionResult> Login([FromForm]LoginRequest model)
{
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Email, model.Email));
ClaimsPrincipal principal = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
principal);
//if (HttpContext.User.Identity.IsAuthenticated)
return RedirectToAction("Index", "Home");
}
The cookie was generated, but can't access home/index as you see. What is my problem? Many thanks for help!

I found the solution after posting this question for a while.
Just need [Authorize(AuthenticationSchemes = CookieAuthenticationDefaults.AuthenticationScheme)] instead of [Authorize], everthing solved.

Try this:
builder.Services
.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
};
options.Events = new JwtBearerEvents()
{
OnMessageReceived = context =>
{
// get token from cookie
if (context.Request.Cookies.ContainsKey("SRLoginCookie"))
{
context.Token = context.Request.Cookies["SRLoginCookie"];
}
return Task.CompletedTask;
}
};
});

Related

.Net Core 3.1 - Angular10 Authentication and Antiforgery

I implemented a simple app in .Net Core 3.1. I am using JWT token as Authentication and added Antiforgery like this in ConfigureServices()
services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options => {
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Environment.GetEnvironmentVariable("JWT_SEED"))),
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
context.Token = context.Request.Cookies["JWT"];
return Task.CompletedTask;
}
};
});
services.AddAuthorization(options =>
options.AddPolicy("ValidAccessToken", policy =>
{
policy.AuthenticationSchemes.Add(JwtBearerDefaults.AuthenticationScheme);
policy.RequireAuthenticatedUser();
})
);
services.AddAntiforgery(options => {
options.HeaderName = "X-XSRF-TOKEN";
options.SuppressXFrameOptionsHeader = false;
});
Then, in Configure() I have:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IAntiforgery antiforgery)
{
app.UseMiddleware<ExceptionMiddleware>();
app.UseCors(options => options
.WithOrigins("https://abc.random.com")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.Use(next => context => {
string path = context.Request.Path.Value;
if (path != null && path.ToLower().Contains("/api")) {
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-TOKEN", tokens.RequestToken,
new CookieOptions() {
HttpOnly = false,
Secure = true
});
}
return next(context);
});
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
I also have a method to refresh the antiforgery token
[HttpGet("refreshAntiforgery")]
public IActionResult RefreshAntiforgery() {
var antiforgeryTokens = _antiforgery.GetAndStoreTokens(HttpContext);
HttpContext.Response.Cookies.Append(
"XSRF-TOKEN",
antiforgeryTokens.RequestToken,
new CookieOptions
{
HttpOnly = false,
Secure = true
}
);
return NoContent();
}
In my Angular app I registered in app.module.ts
HttpClientXsrfModule.withOptions({
cookieName: 'XSRF-TOKEN',
headerName: 'X-XSRF-TOKEN'
}),
and in the services I want to use the antiforgery token (I also have the interceptor to add credentials for all requests and also have URLs starting with // to avoid relative URLs)
updatePassword(client: Client): Observable<any> {
let xsrfToken = this.xsrfTokenExtractor.getToken() as string;
let headers = new HttpHeaders()
.set('X-XSRF-TOKEN', xsrfToken);
return this.http.put<Client>(
environment.baseUrls.client +
environment.relativeUrls.updatePassword,
user,
{
headers: headers,
withCredentials: true
}
);
}
The problem is that XSRF-TOKEN coming from .net core app is being set as HttpOnly despite I set the cookie as HttpOnly = false
cookie from browser
Any idea why HttpOnly is being set in XSRF-TOKEN? (I have tried different solutions like cookie policies or check Configure() order, clear cookies from browser, but nothing changes the value)

JWT - Always unauthorized

I have a very simple code for the user to login as following:
[HttpPost]
[Route("login")]
public async Task<IActionResult> Login([FromBody] LoginModel model)
{
var user = await userManager.FindByEmailAsync(model.Email);
if (user != null && await userManager.CheckPasswordAsync(user, model.Password))
{
var userRoles = await userManager.GetRolesAsync(user);
var authClaims = new List<Claim>
{
new Claim(ClaimTypes.Name, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};
foreach (var userRole in userRoles)
{
authClaims.Add(new Claim(ClaimTypes.Role, userRole));
}
var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["JWT:Secret"]));
var token = new JwtSecurityToken(
issuer: _configuration["JWT:ValidIssuer"],
audience: _configuration["JWT:ValidAudience"],
expires: DateTime.Now.AddHours(3),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expiration = token.ValidTo
});
}
return Unauthorized();
}
This sends me the token as expected
When I use the Token to send a request to a simple controller I get 401-Unauthorized
[Authorize]
[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
[HttpGet]
[Route("getme")]
public async Task<IActionResult> Get()
{
return Ok("Good");
}
}
This is my Startup.cs
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("ConnStr")));
// For Identity
services.AddIdentity<ApplicationUser, IdentityRole>(o =>
{
// configure identity options
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = 6;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// Adding Authentication
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
// Adding Jwt Bearer
.AddJwtBearer(options =>
{
options.SaveToken = true;
options.RequireHttpsMetadata = false;
options.TokenValidationParameters = new TokenValidationParameters()
{
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = Configuration["JWT:ValidAudience"],
ValidIssuer = Configuration["JWT:ValidIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["JWT:Secret"]))
};
});
and the following is my appsettings
I can verify the token at https://jwt.io/
For some reason when I send a request to TestController it always sends back an Unauthorized response. Any idea what am I doing wrong?
If this helps anyone, The issue was in my Startup file under Configure section I had UseAuthentication after UseAuthorization which cause the issue. The correct order as following fixed the issue
app.UseAuthentication();
app.UseRouting();
app.UseAuthorization();
app.UseHttpsRedirection();

With JWT token and policy set, I get unauthorized 401

I follow the tutorial link below.
https://fullstackmark.com/post/13/jwt-authentication-with-aspnet-core-2-web-api-angular-5-net-core-identity-and-facebook-login
I am trying to understand how it works and I want to use role-based authentication using this token. so I made another policy in the Startup.cs file as below.
And I tried to use it like [Authorize(Policy = "admin")] the controller but every time I try I get unauthenticated using postman.
What am I missing? how to make roles-based authentication based on the tutorial?
Configure
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.WithOrigins("http://localhost:4200", "http://localhost:44318")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));
// Configure JwtIssuerOptions
services.Configure<JwtIssuerOptions>(options =>
{
options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
});
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],
ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],
ValidateIssuerSigningKey = true,
IssuerSigningKey = _signingKey,
RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(configureOptions =>
{
configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
});
// api user claim policy
services.AddAuthorization(options =>
{
options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
});
services.AddAuthorization(options =>
options.AddPolicy("admin", policy => policy.RequireRole("admin"))
);
var builder = services.AddIdentityCore<AppUser>(o =>
{
// configure identity options
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = 6;
});
builder = new IdentityBuilder(builder.UserType, typeof(IdentityRole), builder.Services);
builder.AddEntityFrameworkStores<CDSPORTALContext>().AddDefaultTokenProviders().AddRoles<IdentityRole>();
//.AddRoles<IdentityRole>()
services.AddControllers();
services.AddAutoMapper(typeof(Startup));
services.AddSingleton<IJwtFactory, JwtFactory>();
services.TryAddTransient<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IRegionRepository, RegionRepository>();
services.AddScoped<IRegionService, RegionService>();
services.AddScoped<IEmailHelper, EmailHelper>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseCors("CorsPolicy");
app.UseExceptionHandler(
builder =>
{
builder.Run(
async context =>
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
var error = context.Features.Get<IExceptionHandlerFeature>();
if (error != null)
{
context.Response.AddApplicationError(error.Error.Message);
await context.Response.WriteAsync(error.Error.Message).ConfigureAwait(false);
}
});
});
app.UseRouting();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "Client";
spa.UseAngularCliServer(npmScript: "start");
});
}
}
Auth Controller
// POST api/auth/login
[HttpPost("login")]
public async Task<IActionResult> Post([FromBody]CredentialsViewModel credentials)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var identity = await GetClaimsIdentity(credentials.UserName, credentials.Password);
if (identity == null)
{
//return null;
return BadRequest(Error.AddErrorToModelState("login_failure", "Invalid username or password.", ModelState));
}
var id = identity.Claims.Single(c => c.Type == "id").Value;
var user = await _userManager.FindByIdAsync(id);
IList<string> role = await _userManager.GetRolesAsync(user);
var jwt = await Tokens.GenerateJwt(identity, role[0], _jwtFactory, credentials.UserName, _jwtOptions, new JsonSerializerSettings { Formatting = Formatting.Indented });
return new OkObjectResult(jwt);
}
I tried with all method and none of them working
[Authorize(Policy = "ApiUser")]
[HttpGet("getPolicy")]
public string GetPolicy()
{
return "policyWorking";
}
[Authorize(Roles = "admin")]
[HttpGet("getAdmin")]
public string GetAdmin()
{
return "adminWorking";
}
[Authorize ]
[HttpGet("getAuthorize")]
public string GetAuthorize()
{
return "normal authorize Working";
}
Decoded Token
"jti": "840d507d-b2d0-454b-bd1f-007890d3e669",
"iat": 1587699300,
"rol": "api_access",
"id": "1ac370e2-f5e9-4404-b017-8a3c087e2196",
"nbf": 1587699299,
"exp": 1587706499
I forgot to add this to appsetting.
"JwtIssuerOptions": {
"Issuer": "webApi",
"Audience": "http://localhost:4200/"
}

How to sign in ASP.NET Core Identity User, using OpenIdConnect Authentication?

I'm using ASP.NET Identity to authenticate my users and I want to be able to do this via Azure AD as well. All users will be in the DB beforehand, so all I need to do is sign them in and set their cookies, if the AzureAD login was successful. The problem is that when I implement the new external authentication and validate that they exist in my DB, they are not signed in.
So after successful remote login, if in my controller I check for User.Identity.IsAuthenticated it returns true, but _signInManager.IsSignedIn(User), it returns false. I have tried to follow the MS guidelines and documentation, but I assume there is something wrong with my config.
Here's the startup:
services.AddMvc(options => options.EnableEndpointRouting = false)
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
services.AddRouting(options =>
{
options.LowercaseQueryStrings = true;
options.LowercaseUrls = true;
});
services.Configure<CookiePolicyOptions>(options =>
{
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("<my_db_connection_string_here>")));
services.AddDefaultIdentity<ApplicationUser>()
.AddRoles<IdentityRole>()
.AddRoleManager<RoleManager<IdentityRole>>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddUserManager<UserManager<ApplicationUser>>();
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie()
.AddOpenIdConnect(options =>
{
Configuration.GetSection("OpenIdConnect").Bind(options);
options.TokenValidationParameters.ValidateIssuer = false;
options.Events = new OpenIdConnectEvents
{
OnAuthorizationCodeReceived = async ctx =>
{
var request = ctx.HttpContext.Request;
var currentUri = UriHelper.BuildAbsolute(request.Scheme, request.Host, request.PathBase, request.Path);
var credential = new ClientCredential(ctx.Options.ClientId, ctx.Options.ClientSecret);
var distributedCache = ctx.HttpContext.RequestServices.GetRequiredService<IDistributedCache>();
string userId = ctx.Principal.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier").Value;
var authContext = new AuthenticationContext(ctx.Options.Authority);
var result = await authContext.AcquireTokenByAuthorizationCodeAsync(
ctx.ProtocolMessage.Code, new Uri(currentUri), credential, ctx.Options.Resource);
ctx.HandleCodeRedemption(result.AccessToken, result.IdToken);
}
};
});
var builder = services.AddIdentityCore<ApplicationUser>(options =>
{
options.Password.RequireDigit = true;
options.Password.RequiredLength = 6;
options.Password.RequireLowercase = false;
options.Password.RequireUppercase = false;
options.Password.RequireNonAlphanumeric = false;
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
options.User.RequireUniqueEmail = true;
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddLogging(options =>
{
options.AddConfiguration(Configuration.GetSection("Logging"))
.AddConsole();
});
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
IdentityModelEventSource.ShowPII = true;
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
var builder = new ConfigurationBuilder()
.SetBasePath(env.ContentRootPath)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
And in my controller:
[AllowAnonymous]
public IActionResult AzureLogin()
{
if (User.Identity.IsAuthenticated)
{
return RedirectToAction(nameof(HandleLogin)):
}
return Challenge(new AuthenticationProperties
{
RedirectUri = Url.Action(nameof(HandleLogin))
});
}
[Authorize]
public async Task<IActionResult> HandleLogin()
{
var isAuth = User.Identity.IsAuthenticated; // true
var isSigned = _signInmanager.IsSignedIn(User); // false
return ....
}
You could try to set AutomaticAuthenticate cookie to true:
services.Configure<IdentityOptions>(options => {
// other configs
options.Cookies.ApplicationCookie.AutomaticAuthenticate = true;
});
Here's how I managed to do it:
Since I'm authorizing the user via ASP.NET Identity, I changed the default authentication method in the authentication options to options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme; and in the OpenIdConnectOptions OnAuthorizationCodeRecieved event, I validate and sign in the Identity User via the SignInManager.SignInAsync() method

HttpContext.User null with authenticated user?

So I'm working on a .net core 2 project which where we want to create a basic platform which we can use for our future projects. For the login we use Identity. We have it all setup, the user can succesfully login and the cookie gets set. For some reason once we call HttpContext.User this results in a null. I'm pretty sure it does find an identity, yet this identity is empty. We have checked the cookie and it is perfectly fine, it has it's token. We did add token authentication, but that should not interfere with the cookie system when it sets the cookie.
Below is the Startup.cs
public IConfiguration Configuration { get; }
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<MyIdentityDbContext>(options => options
.UseSqlServer("Data Source=PATH;Initial Catalog=DB;Persist Security Info=True;User ID=ID;Password=*******"));
services.AddSingleton<IJwtFactory, JwtFactory>();
services.AddAuthentication(options =>
{
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie();
services.AddIdentity<User, IdentityRole>(options =>
{
options.SignIn.RequireConfirmedEmail = true;
options.User.RequireUniqueEmail = false;
options.Tokens.PasswordResetTokenProvider = TokenOptions.DefaultEmailProvider;
})
.AddEntityFrameworkStores<MyIdentityDbContext>()
.AddDefaultTokenProviders();
services.Configure<IISOptions>(options =>
{
options.ForwardClientCertificate = false;
});
var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));
services.Configure<JwtIssuerOptions>(options =>
{
options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
});
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],
ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],
ValidateIssuerSigningKey = true,
IssuerSigningKey = _signingKey,
RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
services
.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(cfg =>
{
cfg.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
cfg.TokenValidationParameters = tokenValidationParameters;
cfg.SaveToken = true;
});
services.Configure<IdentityOptions>(options =>
{
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = true;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = true;
options.Password.RequiredUniqueChars = 6;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 5;
options.Lockout.AllowedForNewUsers = true;
// User settings
options.User.RequireUniqueEmail = true;
});
services.ConfigureApplicationCookie(options =>
{
// Cookie settings
options.LoginPath = "/Account/Login"; // If the LoginPath is not set here, ASP.NET Core will default to /Account/Login
options.LogoutPath = "/Account/Logout"; // If the LogoutPath is not set here, ASP.NET Core will default to /Account/Logout
options.AccessDeniedPath = "/Account/AccessDenied"; // If the AccessDeniedPath is not set here, ASP.NET Core will default to /Account/AccessDenied
options.SlidingExpiration = true;
options.Cookie = new CookieBuilder
{
HttpOnly = true,
Name = "MyAuthToken",
Path = "/",
SameSite = SameSiteMode.Lax,
SecurePolicy = CookieSecurePolicy.SameAsRequest
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("EmployeeOnly", policy => policy.RequireClaim("Employee"));
options.AddPolicy("OwnerOnly", policy => policy.RequireClaim("Owner"));
options.AddPolicy("AdminOnly", policy => policy.RequireClaim("Admin"));
options.AddPolicy("ModeratorOnly", policy => policy.RequireClaim("Moderator"));
});
services.AddTransient<IEmailSender, EmailSender>();
services.Configure<AuthMessageSenderOptions>(Configuration);
services.AddMvc().AddJsonOptions(options => options.SerializerSettings.ContractResolver = new DefaultContractResolver());
}
Here is the code used in the controller to get the user:
User _user = await _userManager.GetUserAsync(HttpContext.User);
And the code we use to login the user:
var result = await _signInManager.PasswordSignInAsync(model.Email,
model.Password, true, false);
You wrote AddAuthentication two times, once for Cookie and once for JWT and override the defaults.
only use AddAuthentication once and add Cookie and JWT to it.
services.AddAuthentication(options =>
{
// set schema here
})
.AddCookie(config =>
{
//config cookie
})
.AddJwtBearer(config =>
{
//config jwt
});
Now that you have two authentication scheme, you must select which one you want to authenticate your request with
[Authorize(CookieAuthenticationDefaults.AuthenticationScheme)]
or
[Authorize(JwtBearerDefaults.AuthenticationScheme)]
or even both
[Authorize($"{CookieAuthenticationDefaults.AuthenticationScheme},{JwtBearerDefaults.AuthenticationScheme}")]