I try to secure up my API with a cookie token.
Everything is working fine, i try to sign in i generate a cookie the cookie is set by browser, and then i try to request /auth/info2. The cookie is send but i got an 401 error.
Can u give me a hint? How to solve this problem?
Currently my code looks like that:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
{
//options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))
options.UseInMemoryDatabase("som_tmp");
}
);
services.AddTransient<IEmailSender, EmailSender>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddIdentity<SomUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(o =>
{
o.Cookie = new CookieBuilder()
{
HttpOnly = false,
Name = "som_session"
};
});
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
services.AddAuthorization();
services.AddMvc();
services.AddOData();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ApplicationDbContext context, UserManager<SomUser> userManager, RoleManager<IdentityRole> roleManager)
{
var model = GetEdmModel(app.ApplicationServices);
app.UseDefaultFiles();
app.UseStaticFiles(new StaticFileOptions
{
ServeUnknownFileTypes = true
});
app.UseAuthentication();
app.UseMvc(routebuilder =>
{
routebuilder.Count().Filter().OrderBy().Expand().Select().MaxTop(null);
routebuilder.MapODataServiceRoute("oData", "oData", model);
});
DbInitializer.Initialize(context, userManager, roleManager);
}
Controller:
[Authorize]
[HttpGet("info2")]
public async Task<JsonResult> Get2()
{
return Json("Info2");
//return Json( await GetCurrentUser() );
}
[AllowAnonymous]
[HttpPost("login2")]
public async Task<JsonResult> Login2([FromBody] LoginDto loginDto)
{
var user = await _userManager.FindByNameAsync(loginDto.Username);
if (user == null)
{
user = await _userManager.FindByEmailAsync(loginDto.Username);
}
if (user != null)
{
var passwordHasher = new PasswordHasher<SomUser>();
if (passwordHasher.VerifyHashedPassword(user, user.PasswordHash, loginDto.Password) == PasswordVerificationResult.Success)
{
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Name, user.UserName));
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(identity));
return Json(true);
}
}
return Json(false);
}
i got it working with setting the DefaultScheme:
services.AddAuthentication(o =>
{
o.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
You will receive 401 atleast once since there a redirection to login involved.
second result should have 'true' as a output.
Related
actually am new in asp.net core 3.1 , i am trying to create user login and register with cookies
when i am try to get ClaimTypes.NameIdentifier always return null, can you help me please ?
controller code
public class AccountController : ControllerBase
{
private readonly ApiSiteDbContext _db;
private readonly UserManager<AppUser> _userManager;
private readonly SignInManager<AppUser> _signInManager;
private readonly RoleManager<AppRole> _roleManager;
public AccountController(ApiSiteDbContext db,
UserManager<AppUser> userManager,
SignInManager<AppUser> signInManager,
RoleManager<AppRole> roleManager)
{
_db = db;
_userManager = userManager;
_signInManager = signInManager;
_roleManager = roleManager;
}
[AllowAnonymous]
[HttpPost("Login")]
public async Task<IActionResult> Login(LoginModel loginModel)
{
var user = await _userManager.FindByEmailAsync(loginModel.Email);
// **** this is always return null *****
var id = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
if (id != null)
{
return BadRequest("User already logged !!");
}
var result = await _signInManager.PasswordSignInAsync(user, loginModel.Password, loginModel.RememberMe, true);
if (result.Succeeded)
{
if (await _roleManager.RoleExistsAsync("User"))
{
if (!await _userManager.IsInRoleAsync(user, "User"))
{
await _userManager.AddToRoleAsync(user, "User");
}
}
var roleName = await GetRoleNameByUserId(user.Id);
if (roleName != null)
{
AddCookies(user.UserName, user.Id, roleName, loginModel.RememberMe, user.Email);
}
return Ok();
}
else if (result.IsLockedOut)
{
return Unauthorized("Your account were locked");
}
return BadRequest("Wrong password!");
//return StatusCode(StatusCodes.Status204NoContent);
}
public async void AddCookies(string userName, string userId, string roleName, bool remember, string email)
{
var claim = new List<Claim>
{
new Claim(ClaimTypes.Name, userName),
new Claim(ClaimTypes.Email, email),
new Claim(ClaimTypes.NameIdentifier, userId),
new Claim(ClaimTypes.Role, roleName),
};
var claimIdentity = new ClaimsIdentity(claim, CookieAuthenticationDefaults.AuthenticationScheme);
if (remember)
{
var authProperties = new AuthenticationProperties
{
AllowRefresh = true,
IsPersistent = true,
ExpiresUtc = DateTime.UtcNow.AddDays(10)
};
await HttpContext.SignInAsync
(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimIdentity),
authProperties
);
}
else
{
var authProperties = new AuthenticationProperties
{
AllowRefresh = true,
IsPersistent = false,
ExpiresUtc = DateTime.UtcNow.AddMinutes(30)
};
await HttpContext.SignInAsync
(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimIdentity),
authProperties
);
}
}
}
and in Startup.cs
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
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.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = Context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddControllers();
//services.AddControllersWithViews();
services.AddDbContext<ApiSiteDbContext>();
services.AddIdentity<AppUser, AppRole>(option =>
{
option.Password.RequireDigit = true;
option.Password.RequiredLength = 6;
option.Password.RequiredUniqueChars = 0;
option.Password.RequireLowercase = true;
option.Password.RequireNonAlphanumeric = true;
option.Password.RequireUppercase = true;
option.SignIn.RequireConfirmedEmail = true;
option.Lockout.MaxFailedAccessAttempts = 5;
option.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(10);
}).AddEntityFrameworkStores<ApiSiteDbContext>()
.AddDefaultTokenProviders();
services.AddAuthentication(options =>
{
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(options =>
{
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
options.LogoutPath = "/api/Account/Logout";
//options.LoginPath = "/api/Account/Login";
//options.AccessDeniedPath = "/api/Account/accessDenied";
options.SlidingExpiration = true;
});
services.AddMvc(options => options.EnableEndpointRouting = false)
.SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Version_3_0);
services.AddCors();
}
// 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();
}
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors(x => x.WithOrigins("http://localhost:4200").AllowAnyHeader().AllowAnyMethod().AllowCredentials());
app.UseMvc();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
when i make this variable to check the NameIdentifier if return id or not before i use it in a different controller .
Make sure that the roleName variable is not a null or string empty, because adding cookies depends on this condition
following problem I can create a token but when I use it the authentication failed, I try to copy from an example but I had problems because
some methods are not "there". (like principal.SetScopes, but it seems to be exist in the Github repository and in other examples)
The only error I get is the failure of the AuthorizationFilter.
Here the method for creating the token
[HttpPost("~/connect/token"), Produces("application/json")]
public async Task<IActionResult> Exchange(OpenIdConnectRequest connectRequest)
{
if (connectRequest.IsPasswordGrantType())
{
var user = await _userManager.FindByNameAsync(connectRequest.Username);
if (user == null)
{
return Forbid(
authenticationSchemes: OpenIddictServerDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIdConnectConstants.Properties.Error] = OpenIddictConstants.Errors.InvalidGrant,
[OpenIdConnectConstants.Properties.ErrorDescription] = "The username/password couple is invalid."
}));
}
var result = await _signInManager.CheckPasswordSignInAsync(user, connectRequest.Password, lockoutOnFailure: true);
if (!result.Succeeded)
{
return Forbid(
authenticationSchemes: OpenIddictValidationDefaults.AuthenticationScheme,
properties: new AuthenticationProperties(new Dictionary<string, string>
{
[OpenIdConnectConstants.Properties.Error] = Errors.InvalidGrant,
[OpenIdConnectConstants.Properties.ErrorDescription] = "The username/password couple is invalid."
}));
}
var principal = await _signInManager.CreateUserPrincipalAsync(user);
//principal.SetScopes(new[]
//{
// Scopes.OpenId,
// Scopes.Email,
// Scopes.Profile,
// Scopes.Roles
//}.Intersect(connectRequest.GetScopes()));
//foreach (var claim in principal.Claims)
//{
// claim.SetDestinations(GetDestinations(claim, principal));
//}
var sign = SignIn(principal, OpenIddictServerDefaults.AuthenticationScheme);
return sign;
}
throw new Exception("Not supported");
}
Here is my startup
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DocumentiveContext>((provider, builder) =>
{
var configuration = provider.GetService<IConfiguration>();
builder.UseSqlServer(configuration.GetConnectionString("connectionString"));
builder.UseOpenIddict();
});
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
})
.AddEntityFrameworkStores<DocumentiveContext>()
.AddDefaultTokenProviders();
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToAccessDenied = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
services.Configure<IdentityOptions>(options =>
{
options.ClaimsIdentity.UserNameClaimType = Claims.Name;
options.ClaimsIdentity.UserIdClaimType = Claims.Subject;
options.ClaimsIdentity.RoleClaimType = Claims.Role;
});
services.AddAuthentication(options =>
options.DefaultScheme = OpenIddictValidationDefaults.AuthenticationScheme);
services.AddOpenIddict(builder =>
{
builder.AddCore(coreBuilder => coreBuilder.UseEntityFrameworkCore().UseDbContext<DocumentiveContext>());
builder.AddServer(serverBuilder =>
{
serverBuilder.UseMvc();
//serverBuilder.EnableTokenEndpoint("/connect/token");
serverBuilder.EnableAuthorizationEndpoint("/connect/authorize")
.EnableLogoutEndpoint("/connect/logout")
.EnableTokenEndpoint("/connect/token")
.EnableUserinfoEndpoint("/connect/userinfo")
.EnableUserinfoEndpoint("/connect/verify");
serverBuilder.AllowPasswordFlow();
serverBuilder.RegisterScopes(Scopes.Email, Scopes.Profile, Scopes.Roles, "demo_api");
serverBuilder.AddDevelopmentSigningCertificate();
serverBuilder.AcceptAnonymousClients();
serverBuilder.DisableHttpsRequirement();
});
builder.AddValidation(validationBuilder =>
{
});
});
services.AddMvc(options => options.EnableEndpointRouting = false);
services.AddGrpc();
services.AddTransient<IUserInformationService, UserInformationService>();
}
// 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();
}
app.UseRouting();
app.UseAuthentication();
app.UseStaticFiles();
app.UseSerilogRequestLogging();
app.UseAuthorization();
app.UseMvcWithDefaultRoute();
app.UseEndpoints(endpoints =>
{
endpoints.MapGrpcService<GreeterService>();
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");
});
});
}
}
Any idea?
After updating to the newest Version 3 of Openiddict, it works.
Also I needed to set the Authentication Scheme in the attribute.
[Authorize(AuthenticationSchemes = OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme)]
I have a WebAPI designed for beeing used as Authentication Server that has an endpoint for registering users, another one for login in users and another one to get the user profile.
Register works correctly and login works good also aparently.
My problem is the following: The user profile endpoint needs Authorization so I use the token that login endpoint returns and append it to the request as bearer token. Requests always return 401: Unauthorized even though I am using the token that login returned.
I test the services with postman and it doesnt return any error with token, only says that I'm unauthorized to make that request.
This are the responses in Postman:
Login request:
UserProfile request:
Here is the code:
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
//Inject AppSettings
services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings"));
services.AddMvc(option => option.EnableEndpointRouting = false).SetCompatibilityVersion(CompatibilityVersion.Latest);
services.AddDbContext<AuthenticationContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection")));
services.AddIdentity<ApplicationUser, IdentityRole>()
.AddEntityFrameworkStores<AuthenticationContext>();
services.AddCors();
// JWT Authentication
var key = Encoding.UTF8.GetBytes(Configuration["ApplicationSettings:JWT_Secret"].ToString());
var signingKey = new SymmetricSecurityKey(key);
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x => {
x.RequireHttpsMetadata = false;
x.SaveToken = false;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = signingKey,
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
};
});
}
// 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();
}
app.UseCors(builder =>
builder.WithOrigins(Configuration["ApplicationSettings:Client_URL"].ToString())
.AllowAnyHeader()
.AllowAnyMethod()
);
app.UseMvc();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
ApplicationUserController (register and login endpoints):
{
[Route("api/[controller]")]
[ApiController]
public class ApplicationUserController : ControllerBase
{
private UserManager<ApplicationUser> _userManager;
private SignInManager<ApplicationUser> _signInManager;
private readonly ApplicationSettings _appSettings;
public ApplicationUserController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser> signInManager, IOptions<ApplicationSettings> appSettings)
{
_userManager = userManager;
_signInManager = signInManager;
_appSettings = appSettings.Value;
}
[HttpPost]
[Route("Register")]
// POST: /api/ApplicationUser/Register
public async Task<object> PostApplicationUser(ApplicationUserModel model)
{
var applicationUser = new ApplicationUser()
{
UserName = model.UserName,
Email = model.Email,
FullName = model.FullName
};
try
{
var result = await _userManager.CreateAsync(applicationUser, model.Password);
return Ok(result);
}
catch(Exception ex)
{
throw ex;
}
}
[HttpPost]
[Route("Login")]
// POST: /api/ApplicationUser/Login
public async Task<IActionResult> Login(LoginModel model)
{
var user = await _userManager.FindByNameAsync(model.UserName);
if (user != null && await _userManager.CheckPasswordAsync(user, model.Password))
{
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new Claim[]
{
new Claim("UserId", user.Id.ToString())
}),
Expires = DateTime.UtcNow.AddDays(1),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_appSettings.JWT_Secret)), SecurityAlgorithms.HmacSha256Signature)
};
var tokenHandler = new JwtSecurityTokenHandler();
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
var token = tokenHandler.WriteToken(securityToken);
return Ok(new { token });
}
else
{
return BadRequest(new { message = "Username or password is incorrect" });
}
}
}
}
UserProfileController (getUserProfile endpoint):
{
[Route("api/[controller]")]
[ApiController]
public class UserProfileController : ControllerBase
{
private UserManager<ApplicationUser> _userManager;
public UserProfileController(UserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
[HttpGet]
[Authorize]
//GET : /api/UserProfile
public async Task<Object> GetUserProfile()
{
string userId = User.Claims.First(c => c.Type == "UserID").Value;
var user = await _userManager.FindByIdAsync(userId);
return new
{
user.FullName,
user.Email,
user.UserName
};
}
}
Thanks for your help and if you need some extra info just tell me
When I successfully signed in to the HTTP context and I'm redirected to the home controller, the Authorize Attribute of the HomeController redirects me to the login path, because I don't know. (Infinite loop)
The validate async method doesn't sign me out or reject the cookie (I checked it.)
But where's the problem?
I have the same authentication process in an ASP.NET Core 2.1 project and there it works perfectly.
I test it with a custom authorize attribute to check the context. In the context I've a principal and I'm authenticated.
But why redirect me the standard authorize attribute?
My configuration is:
HomeController.cs
public class HomeController : Controller
{
[Authorize]
public IActionResult Index()
{
return this.View("Index");
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/auth/login/";
options.ExpireTimeSpan = TimeSpan.FromDays(7);
options.Events.OnValidatePrincipal = ValidateAsync;
});
services.AddControllersWithViews();
services.AddAntiforgery();
services.AddDbContext<ApplicationDbContext>((serviceProvider, options) =>
{
options.UseSqlServer(this.Configuration.GetConnectionString("DefaultConnection"));
options.EnableSensitiveDataLogging();
});
}
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.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseAuthentication();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
public static async Task ValidateAsync(CookieValidatePrincipalContext context)
{
context = context ?? throw new ArgumentNullException(nameof(context));
String userId = context.Principal.Claims.FirstOrDefault(claim => claim.Type == ClaimTypes.NameIdentifier)?.Value;
if(userId == null)
{
context.RejectPrincipal();
await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return;
}
ApplicationDbContext dbContext = context.HttpContext.RequestServices.GetRequiredService<ApplicationDbContext>();
User user = await dbContext.Users.FindAsync(Guid.Parse(userId));
if(user == null)
{
context.RejectPrincipal();
await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return;
}
if(!user.StaySignedIn &&
user.LastLogin != null &&
(user.LastLogin.Subtract(TimeSpan.FromDays(1)) > DateTimeOffset.Now))
{
context.RejectPrincipal();
await context.HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
return;
}
}
AuthController.cs
[Route("/login")]
[Route("/auth/login")]
public async Task<IActionResult> Login([FromForm]LoginModel loginModel)
{
Claim nameIdentifier = new Claim(ClaimTypes.NameIdentifier, user.Id.ToString());
ClaimsIdentity userIdentity = new ClaimsIdentity(new List<Claim> { nameIdentifier }, CookieAuthenticationDefaults.AuthenticationScheme);
ClaimsPrincipal claimsPrincipal = new ClaimsPrincipal(userIdentity);
await this.HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, claimsPrincipal);
return this.RedirectToAction("Index", "Home");
}
I found the solution for my problem.
The order of
app.UseAuthorization();
app.UseAuthentication();
Must be changed and then it works.
The issue closed When using identity is not allowed to use the cookies.
It overrides some of the information.
Git Discussion
Cookie options tell the authentication middleware how the cookie works in the browser.In the Startup class, add this code in your ConfigureServices Method
services.AddAuthentication(options =>
{
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
}).AddCookie(options => { options.LoginPath = "/Login"; });
I am developing an application using ASP.Net MVC core 2.1 where I am continuously getting the following exception.
"InvalidOperationException: No authentication handler is registered for the scheme 'CookieSettings'. The registered schemes are: Identity.Application, Identity.External, Identity.TwoFactorRememberMe, Identity.TwoFactorUserId. Did you forget to call AddAuthentication().AddSomeAuthHandler?"
I went through articles did the necessary changes but exception remains the same. I am unable to figure out what to do next .
following is my startup.cs :
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
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.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddDbContext<Infrastructure.Data.ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>()
.AddEntityFrameworkStores<Infrastructure.Data.ApplicationDbContext>();
services.AddSingleton(Configuration);
//Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
//Add services
services.AddTransient<IContactManagement, ContactManagement>();
services.AddTransient<IRepository<Contact>, Repository<Contact>>();
services.AddTransient<IJobManagement, JobJobManagement>();
services.AddTransient<IRepository<Job>, Repository<Job>>();
services.AddTransient<IUnitManagement, UnitManagement>();
services.AddTransient<IRepository<Sensor>, Repository<Sensor>>();
services.AddTransient<IJobContactManagement, JobContactManagement>();
services.AddTransient<IRepository<JobContact>, Repository<JobContact>>();
services.AddTransient<IJobContactEventManagement, JobContactEventManagement>();
services.AddTransient<IRepository<JobContactEvent>, Repository<JobContactEvent>>();
services.AddTransient<IJobsensorManagement, JobsensorManagement>();
services.AddTransient<IRepository<JobSensor>, Repository<JobSensor>>();
services.AddTransient<IEventTypesManagement, EventTypesManagement>();
services.AddTransient<IRepository<EventType>, Repository<EventType>>();
services.AddTransient<IJobSensorLocationPlannedManagement, JobSensorLocationPlannedManagement>();
services.AddTransient<IRepository<JobSensorLocationPlanned>, Repository<JobSensorLocationPlanned>>();
services.AddTransient<IDataTypeManagement, DataTypeManagement>();
services.AddTransient<IRepository<DataType>, Repository<DataType>>();
services.AddTransient<IThresholdManegement, ThresholdManegement>();
services.AddTransient<IRepository<Threshold>, Repository<Threshold>>();
services.AddTransient<ISeverityTypeManagement, SeverityTypeManagement>();
services.AddTransient<IRepository<SeverityType>, Repository<SeverityType>>();
services.AddTransient<ISensorDataManagement, SensorDataManagement>();
services.AddTransient<IRepository<SensorData>, Repository<SensorData>>();
services.AddTransient<ISensorLocationManagement, SensorLocationManagement>();
services.AddTransient<IRepository<SensorLocation>, Repository<SensorLocation>>();
services.AddTransient<ISensorStatusTypeManagement, SensorStatusTypeManagement>();
services.AddTransient<IRepository<SensorStatusType>, Repository<SensorStatusType>>();
services.AddTransient<IRepository<SensorDataToday>, Repository<SensorDataToday>>();
services.AddTransient<ISensorDataTodayManagement, SensorDataTodayManagement>();
services.AddSession();
services.AddSession(options =>
{
options.IdleTimeout = TimeSpan.FromMinutes(20);
});
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.LoginPath = "/Account/Login/";
options.LogoutPath = "/Account/Logout/";
});
services.AddAuthentication(options =>
{
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
});
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseCookiePolicy();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
login/signin.cs:
public async Task<IActionResult> Login(LoginViewModel model, ApplicationUser applicationUser, string returnUrl = "/RealTimeChart/Index")
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
ApplicationUser signedUser = await _userManager.FindByEmailAsync(model.Email);
if (signedUser != null)
{
var result = await _signInManager.PasswordSignInAsync(signedUser.UserName, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
//Authorize login user
if (!string.IsNullOrEmpty(signedUser.UserName))
{
await AuthorizeUser(signedUser);
}
_logger.LogInformation(1, "User logged in.");
HttpContext.Session.SetString("UserName", model.Email);
int AccountTypeId = _contactManagement.GetContactDetailsByUserId(signedUser.Id).UserAccountTypeId;
HttpContext.Session.SetString("AccountTypeId", AccountTypeId.ToString());
return RedirectToLocal(returnUrl);
}
else
{
if (_userManager.SupportsUserLockout && await _userManager.GetLockoutEnabledAsync(signedUser))
{
await _userManager.AccessFailedAsync(signedUser);
}
}
if (result.RequiresTwoFactor)
{
return RedirectToAction(nameof(SendCode), new { ReturnUrl = returnUrl, RememberMe = model.RememberMe });
}
if (signedUser.LockoutEnd != null)
{
_logger.LogWarning(2, "User account locked out.");
return View("Lockout");
}
else
{
ViewBag.InvalidPassword = "Password is Invalid";
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
else
{
ViewBag.InvalidEmail = "Email is Invalid";
return View(model);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
i tried changing my login method to below but no success, your help is highly appreciated
List<Claim> userClaims = new List<Claim>
{
new Claim(applicationUser.Id, Convert.ToString(applicationUser.Id)),
new Claim(ClaimTypes.Name, applicationUser.UserName),
new Claim(ClaimTypes.Role, Convert.ToString(applicationUser.Id))
};
var identity = new ClaimsIdentity(userClaims, CookieAuthenticationDefaults.AuthenticationScheme);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme,new ClaimsPrincipal(identity));
You should add the following instructions in the ConsigureServices method in class Startup.cs. You can add this at the beginning of the method:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(o =>
{
o.Cookie.Name = options.CookieName;
o.Cookie.Domain = options.CookieDomain;
o.SlidingExpiration = true;
o.ExpireTimeSpan = options.CookieLifetime;
o.TicketDataFormat = ticketFormat;
o.CookieManager = new CustomChunkingCookieManager();
});
This code let you to register the authentication handler for cookies authentication.
I suggest you this read this or this
Apparently, if you use services.AddIdentityCore(), you should use
signInManager.CheckPasswordSignInAsync() as opposed to signInManager.PasswordSignInAsync() because signInManager.PasswordSignInAsync() can only be used with cookies.