Authorized API is not working even when passing a JWT bearer token - api

The loginWithJWT() method works fine, the user login normally and the token is created.
enter image description here
but when I try to access the GetAllCountry() method that is [Authorized] after passing the token . An unauthorized response is fired.
enter image description here
This is the JWT description :
enter image description here
Not sure what I have missed.
here is my start up class :
namespace HotelListing
{
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
Log.Logger = new LoggerConfiguration()
.ReadFrom.Configuration(configuration)
.CreateLogger();
}
public void ConfigureServices(IServiceCollection services)
{
// Db conn string
services.AddDbContext<ApplicationDbContext>
(options => options.UseSqlServer(Configuration.GetConnectionString("sqlServerConnection")));
//Identity
services.AddAuthentication();
services.AddIdentity<MyIdentityUser, IdentityRole>(options =>
{
options.User.RequireUniqueEmail = true;
}).AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
//enabling JWT
services.AddAuthentication(option =>
{
option.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
option.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(opt =>
{
opt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = (Configuration.GetSection("Jwt")).GetSection("Issuer").Value,
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Environment.GetEnvironmentVariable("SecretTokenKeyValue")))
};
});
// Mapper
services.AddAutoMapper(typeof(ApplicationMapper));
//DI interfaces and classes
services.AddScoped<ICountryServices, CountrySevices>();
services.AddScoped<IHotelServices, HotelServices>();
services.AddScoped<IUserAuthenticationManager, UserAuthenticationManager>();
//Swagger config
services.AddSwaggerGen(c =>
{
c.SwaggerDoc("v1", new OpenApiInfo { Title = "HotelListing", Version = "v1" });
});
//Adding Controllers + JSON self refrencing config
services.AddControllers().AddNewtonsoftJson(opt =>
opt.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseSwagger();
app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "HotelListing v1"));
}
app.UseHttpsRedirection();
app.UseCors("AllowAll");
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
here is my UserAuthenticationManager Class:
namespace HotelListing.Services
{
public class UserAuthenticationManager : IUserAuthenticationManager
{
private MyIdentityUser _user;
private UserManager<MyIdentityUser> _userManager;
private IConfiguration _configuration;
public UserAuthenticationManager(UserManager<MyIdentityUser> userManager, IConfiguration configuration)
{
_userManager = userManager;
_configuration= configuration;
}
public async Task<bool> ValidateUser(LoginUserDto userDto)
{
_user = await _userManager.FindByNameAsync(userDto.Email);
if (_user != null && await _userManager.CheckPasswordAsync(_user, userDto.Password))
return true;
else
return false;
}
public async Task<string> CreateToken()
{
var signingCredentials = GetSigningCredentials();
var claims = await GetClaims();
var tokenOptions = GenerateTokenOptions(signingCredentials, claims);
return new JwtSecurityTokenHandler().WriteToken(tokenOptions);
}
private SigningCredentials GetSigningCredentials()
{
var key = Environment.GetEnvironmentVariable("SecretTokenKeyValue");
var secret = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(key));
return new SigningCredentials(secret, SecurityAlgorithms.HmacSha256);
}
private async Task<List<Claim>> GetClaims()
{
var claimList = new List<Claim>
{
new Claim(ClaimTypes.Name, _user.UserName)
};
var roles = await _userManager.GetRolesAsync(_user);
foreach(var role in roles){
claimList.Add(new Claim(ClaimTypes.Role, role));
}
return claimList;
}
private JwtSecurityToken GenerateTokenOptions(SigningCredentials signingCrenditals, List<Claim> claimList)
{
var jwtSettings = _configuration.GetSection("Jwt");
var token = new JwtSecurityToken(
issuer: jwtSettings.GetSection("Issuer").Value,
claims: claimList,
expires: DateTime.Now.AddMinutes(Convert.ToDouble(jwtSettings.GetSection("lifetime").Value)),
signingCredentials: signingCrenditals);
return token;
}
}
}
here is my UserApiController:
namespace HotelListing.APIs
{
[Route("api/[controller]")]
[ApiController]
public class UserApiController : ControllerBase
{
private UserManager<MyIdentityUser> _userManager { get; }
private IUserAuthenticationManager _userAuthenticationManager { get; }
private IMapper _mapper { get; }
public UserApiController(UserManager<MyIdentityUser> userManager,
IUserAuthenticationManager userAuthenticationManager,
IMapper mapper)
{
_userManager = userManager;
_userAuthenticationManager = userAuthenticationManager;
_mapper = mapper;
}
[HttpPost]
[Route("register")]
public async Task<IActionResult> Register([FromBody] UserDTO userDTO)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
var user = _mapper.Map<MyIdentityUser>(userDTO);
user.UserName = userDTO.Email;
var result = await _userManager.CreateAsync(user, userDTO.Password);
if (!result.Succeeded)
{
foreach(var error in result.Errors)
{
ModelState.AddModelError(error.Code, error.Description);
}
return BadRequest(ModelState);
}
await _userManager.AddToRolesAsync(user, userDTO.roles);
return Accepted();
}catch(Exception ex)
{
return StatusCode(500, ex.Message + "Internal server error");
}
}
[HttpPost]
[Route("loginWithJWT")]
public async Task<IActionResult> LoginWithJWT([FromBody] LoginUserDto userDTO)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
var result = await _userAuthenticationManager.ValidateUser(userDTO);
if (result != true)
{
return Unauthorized(userDTO);
}
return Accepted(new { Token = await _userAuthenticationManager.CreateToken()});
}
catch (Exception ex)
{
return Problem($"Something went wrong in {nameof(LoginWithJWT)} error is {ex.Message}", statusCode:500);
}
}
}
}
Iam trying to access the authorized GetAllCountries() method in CountryApi class:
namespace HotelListing.APIs
{
[Route("api/[controller]")]
[ApiController]
public class CountryApiController : ControllerBase
{
private ICountryServices _countryServices { get; }
private IMapper _mapper { get; }
public CountryApiController(ICountryServices countryServices, IMapper mapper)
{
_countryServices = countryServices;
_mapper = mapper;
}
**// GET: api/<CountryApiController>
[HttpGet]
[Authorize]
public async Task<IActionResult> GetAllCountries()
{
try{
var countries = await _countryServices.GetAllCountriesAsync();
return Ok(_mapper.Map<List<CountryDTO>>(countries));
}
catch(Exception ex)
{
return StatusCode(500, ex.Message + "Internal server error");
}
}**
// GET: api/<CountryApiController>/id
[HttpGet("{id:int}")]
public async Task<IActionResult> GetCountryById(int id)
{
try
{
var country = await _countryServices.GetCountryByIdAsync(id);
return Ok(_mapper.Map<CountryDTO>(country));
}
catch (Exception ex)
{
return StatusCode(500, ex.Message + "Internal server error");
}
}
}
}

Related

Blazor server side authentication require all-browser tabs

I used an authentication for a blazor server side app
I created a login page and used authorized pages.I authenticated at login page.These worked properly but, when I opened a new tab app we have to authenticate again.It is interesting that in first page I yet authenticated. I want to login all non private tabs on browser.
Codes are below
startup:
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthenticationCore();
services.AddAuthorizationCore();
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
services.AddScoped<ProtectedSessionStorage>();
services.AddSingleton<UserAccountService>();
services.AddScoped<AuthenticationStateProvider, AuthStateProvider>();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/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.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
AuthStateProvider:
public class AuthStateProvider : AuthenticationStateProvider
{
private readonly ProtectedSessionStorage sessionStorage;
private ClaimsPrincipal anonymous = new ClaimsPrincipal(new ClaimsIdentity());
public AuthStateProvider(ProtectedSessionStorage sessionStorage)
{
this.sessionStorage = sessionStorage;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
try
{
var userSessionStorageResult = await sessionStorage.GetAsync<UserSession>("UserSession");
var userSession = userSessionStorageResult.Success ? userSessionStorageResult.Value : null;
if (userSession == null)
{
return await Task.FromResult(new AuthenticationState(anonymous));
}
var claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
{
new Claim(ClaimTypes.Name,userSession.Username),
new Claim(ClaimTypes.Role,userSession.Role)
}, "CustomAuth"));
return await Task.FromResult(new AuthenticationState(claimsPrincipal));
}
catch (Exception ex)
{
return await Task.FromResult(new AuthenticationState(anonymous));
}
}
public async Task UpdateAuthenticationState(UserSession userSession)
{
ClaimsPrincipal claimsPrincipal;
if (userSession != null)
{
await sessionStorage.SetAsync("UserSession", userSession);
claimsPrincipal = new ClaimsPrincipal(new ClaimsIdentity(new List<Claim>
{
new Claim(ClaimTypes.Name,userSession.Username),
new Claim(ClaimTypes.Role,userSession.Role)
}));
}
else
{
await sessionStorage.DeleteAsync("UserSession");
claimsPrincipal = anonymous;
}
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(claimsPrincipal)));
}
}
Login.Razor:
private class Model
{
public string Username { get; set; }
public string Password { get; set; }
}
private Model model = new Model();
private async Task Authenticate()
{
var userAccount = userAccountService.GetByUserName(model.Username);
if (userAccount == null || userAccount.Password != model.Password)
{
await js.InvokeVoidAsync("alert", "Invalid User Name or Password");
return;
}
var customAuthStateProvider = (AuthStateProvider)authStateProvider;
await customAuthStateProvider.UpdateAuthenticationState(new UserSession
{
Username = userAccount.Username,
Role=userAccount.Role
});
navManager.NavigateTo("/", true);
}
Counter.Razor:
#page "/counter"
#attribute [Authorize(Roles = "admin,user")]
<h1>Counter</h1>
<p>Current count: #currentCount</p>
<button class="btn btn-primary" #onclick="IncrementCount">Click me</button>
#code {
private int currentCount = 0;
private void IncrementCount()
{
currentCount++;
}
}

How to get identity values from google external provider in ASP.NET Core Web API

[ApiController]
[Route("[controller]")]
public class AuthController : ControllerBase
{
private readonly SignInManager<IdentityUser> _signInManager;
public AuthController(SignInManager<IdentityUser> signInManager)
{
_signInManager = signInManager ?? throw new ArgumentNullException(nameof(signInManager));
}
[HttpGet("token")]
public ChallengeResult Token()
{
var properties = new GoogleChallengeProperties
{
RedirectUri = "/auth/retrieve",
AllowRefresh = true,
};
return Challenge(properties, "Google");
}
[HttpGet("[action]")]
public async Task Retrieve()
{
var token = await HttpContext.GetTokenAsync("access_token");
var externalLoginInfoAsync = await _signInManager.GetExternalLoginInfoAsync();
var identityName = User?.Identity?.Name;
var authenticateResult = await HttpContext.AuthenticateAsync();
}
}
I direct the user to /auth/token, where he is redirected to the Google Oauth Page, if successful, he is redirected to /auth/retrieve, where I expect the user data, but token, externalLoginInfoAsync, identityName, authenticateResult is null
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseNpgsql(Configuration.GetConnectionString("Default")));
services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddAuthentication()
.AddCookie()
.AddGoogle(options =>
{
options.Scope.Add("https://www.googleapis.com/auth/gmail.settings.basic");
options.AccessType = "offline";
options.SaveTokens = true;
options.SignInScheme = IdentityConstants.ExternalScheme;
options.Events.OnCreatingTicket = ctx =>
{
var identityName = ctx.Identity.Name;
return Task.CompletedTask;
};
options.ClientId = "SMTH_VALUE";
options.ClientSecret = "SMTH_VALUE";
});
services.AddControllers();
}
I debug the google provider and found the user values in the Events - identityName is not null.
How i can get this value in the controller?
You could refer the following code to configure Google authentication in Startup.ConfigureServices method:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthentication()
.AddGoogle(opt =>
{
opt.ClientId = "620831551062-rcvu44q4rhr5d8ossu3m0163jqbjdji0.apps.googleusercontent.com";
opt.ClientSecret = "GXFN0cHBbUlZ6nYLD7a7-cT8";
opt.SignInScheme = IdentityConstants.ExternalScheme;
});
services.AddControllersWithViews();
services.AddRazorPages();
}
Then, use the following sample to login using Google and get user information:
[Authorize]
public class AccountController : Controller
{
private UserManager<ApplicationUser> userManager;
private SignInManager<ApplicationUser> signInManager;
public AccountController(UserManager<ApplicationUser> userMgr, SignInManager<ApplicationUser> signinMgr)
{
userManager = userMgr;
signInManager = signinMgr;
}
// other methods
public IActionResult AccessDenied()
{
return View();
}
[AllowAnonymous]
public IActionResult GoogleLogin()
{
string redirectUrl = Url.Action("GoogleResponse", "Account");
var properties = signInManager.ConfigureExternalAuthenticationProperties("Google", redirectUrl);
return new ChallengeResult("Google", properties);
}
public IActionResult Login()
{
return View();
}
[AllowAnonymous]
public async Task<IActionResult> GoogleResponse()
{
ExternalLoginInfo info = await signInManager.GetExternalLoginInfoAsync();
if (info == null)
return RedirectToAction(nameof(Login));
var result = await signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, false);
string[] userInfo = { info.Principal.FindFirst(ClaimTypes.Name).Value, info.Principal.FindFirst(ClaimTypes.Email).Value };
if (result.Succeeded)
return View(userInfo);
else
{
ApplicationUser user = new ApplicationUser
{
Email = info.Principal.FindFirst(ClaimTypes.Email).Value,
UserName = info.Principal.FindFirst(ClaimTypes.Email).Value
};
IdentityResult identResult = await userManager.CreateAsync(user);
if (identResult.Succeeded)
{
identResult = await userManager.AddLoginAsync(user, info);
if (identResult.Succeeded)
{
await signInManager.SignInAsync(user, false);
return View(userInfo);
}
}
return AccessDenied();
}
}
}
The result like this:
More detail information, see How to integrate Google login feature in ASP.NET Core Identity and Google external login setup in ASP.NET Core

How to delete cookie on browser close

I'm implementing asp.net core project and I authenticate the user via ldap by using Novell.Directory.Ldap.NETStandard. Now my problem is How can I delete cookie after the user close the browser. I want whenever the user close the browser and opens the system again, he confronts with login page. here below is what I've tried in startup for setting cookie:
services.AddScoped<Ldap.IAuthenticationService, LdapAuthenticationService>();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(15);
options.LoginPath = "/Account/Login";
options.SlidingExpiration = true;
});
And here is my AccountController:
public class AccountController : Controller {
private readonly Ldap.IAuthenticationService _authenticationService;
private readonly IHttpContextAccessor _httpContext;
public AccountController(Ldap.IAuthenticationService authenticationService,IHttpContextAccessor context)
{
_httpContext = context;
_authenticationService = authenticationService;
}
public IActionResult Login()
{
return View();
}
[HttpPost]
// [ChildActionOnly]
public async Task<IActionResult> Login(LoginModel model)
{
LdapEntry result1 = null;
var result = _authenticationService.ValidateUser1("mm.fr", model.UserName, model.Password);
if (result.Equals(true))
{
result1 = _authenticationService.GetLdapUserDetail("mm.fr", model.UserName, model.Password);
ViewBag.Username = result1.GetAttribute("CN").StringValue;
Index(result1.GetAttribute("CN").StringValue);
if (result != null)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, model.UserName),
new Claim(ClaimTypes.Role, "Administrator"),
};
var claimsIdentity = new ClaimsIdentity(
claims, CookieAuthenticationDefaults.AuthenticationScheme);
var authProperties = new AuthenticationProperties
{
};
await HttpContext.SignInAsync(
CookieAuthenticationDefaults.AuthenticationScheme,
new ClaimsPrincipal(claimsIdentity),
authProperties);
}
}
else
{
this.TempData["ErrorMessage"] = "Password is incorrect";
}
return RedirectToAction(nameof(MainDashboardController.Index), "MainDashboard");
}
public IActionResult Index(string str)
{
_httpContext.HttpContext.Session.SetString("mystr", str);
return View();
}
}
Here below is what I wrote in Startup:
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.AddControllersWithViews();
services.AddDbContext<CSDDashboardContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("CSDDashboardContext")));
//Notice this is NOT the same class... Assuming this is a valid DBContext. You need to add this class as well.
//services.AddDbContext<CSSDDashboardContext>(options =>
// options.UseSqlServer(Configuration.GetConnectionString("CSDDashboardContext")));
//*---------------------------New Active Directory--------------------------------
services.AddScoped<IAuthenticationService, LdapAuthenticationService>();
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(options =>
{
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(15);
options.LoginPath = "/Account/Login";
options.SlidingExpiration = true;
});
services.AddSession();
services.AddSingleton<MySharedDataViewComponent>();
services.AddHttpContextAccessor();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseSession();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
function deleteCookie(name) {
setCookie(name,"",-1);
}
function setCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}
$(window).unload(function() {
deleteCookie('Your cookie to delete name');
});

Blazor server-side custom login using Identity lose logged state after restart

I implemented own solution to make login without page refresh. However can't figure out why I am losing logged-in state on application restart (new debug run).
Startup
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<DatabaseContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")), ServiceLifetime.Transient);
services.AddIdentity<User, Role>(options =>
{ // options...
}).AddEntityFrameworkStores<DatabaseContext>().AddDefaultTokenProviders();
services.AddDataProtection().PersistKeysToFileSystem(new DirectoryInfo("/keys")).SetApplicationName("App").SetDefaultKeyLifetime(TimeSpan.FromDays(90));
services.AddRazorPages();
services.AddServerSideBlazor().AddCircuitOptions(options =>
{
options.DetailedErrors = true;
});
services.AddSession();
services.AddSignalR();
services.AddBlazoredLocalStorage();
services.AddHttpClient();
services.Configure<CookiePolicyOptions>(options =>
{
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie();
services.AddAuthorization(options =>
{ // options...
});
// Add application services.
services.AddScoped<AuthenticationStateProvider, IdentityAuthenticationStateProvider>();
// .. services
services.AddMvc(options =>
{
options.OutputFormatters.Add(new XmlSerializerOutputFormatter());
}).AddSessionStateTempDataProvider();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseSession();
app.UseStaticFiles();
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
AuthorizeController
[HttpPost("Login")]
[AllowAnonymous]
public async Task<IActionResult> Login(LoginViewModel model)
{
if (ModelState.IsValid)
{
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
Microsoft.AspNetCore.Identity.SignInResult result = await signInMgr.PasswordSignInAsync(model.LEmail, model.LPassword, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
return Ok();
return BadRequest(string.Join(", ", ModelState.Values.SelectMany(x => x.Errors).Select(x => x.ErrorMessage)));
}
return BadRequest();
}
[HttpGet("UserInfo")]
public UserInfo UserInfo()
{
return new UserInfo
{
IsAuthenticated = User.Identity.IsAuthenticated,
UserName = User.Identity.Name,
ExposedClaims = User.Claims.ToDictionary(c => c.Type, c => c.Value)
};
}
I believe problem is in my AuthenticationStateProvider implementation
public class IdentityAuthenticationStateProvider : RevalidatingServerAuthenticationStateProvider
{
readonly AuthorizeService authorizeSvc;
readonly IServiceScopeFactory scopeFactory;
readonly IdentityOptions options;
UserInfo userInfoCache;
protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(30);
public IdentityAuthenticationStateProvider(AuthorizeService authorizeService, ILoggerFactory loggerFactory, IServiceScopeFactory serviceScopeFactory, IOptions<IdentityOptions> optionsAccessor) : base(loggerFactory)
{
authorizeSvc = authorizeService;
scopeFactory = serviceScopeFactory;
options = optionsAccessor.Value;
}
public async Task LoginAsync(LoginViewModel model)
{
await authorizeSvc.LoginAsync(model);
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
public async Task RegisterAsync(RegisterViewModel register)
{
await authorizeSvc.RegisterAsync(register);
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
public async Task LogoutAsync()
{
await authorizeSvc.LogoutAsync();
userInfoCache = null;
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
async Task<UserInfo> GetUserInfoAsync()
{
if (userInfoCache != null && userInfoCache.IsAuthenticated)
return userInfoCache;
userInfoCache = await authorizeSvc.GetUserInfo();
return userInfoCache;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
ClaimsIdentity identity = new ClaimsIdentity();
try
{
UserInfo userInfo = await GetUserInfoAsync();
if (userInfo.IsAuthenticated)
{
IEnumerable<Claim> claims = new[] { new Claim(ClaimTypes.Name, userInfoCache.UserName) }.Concat(userInfoCache.ExposedClaims.Select(c => new Claim(c.Key, c.Value)));
identity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
}
}
catch (HttpRequestException ex)
{
Console.WriteLine("Request failed:" + ex.ToString());
}
return new AuthenticationState(new ClaimsPrincipal(identity));
}
protected override async Task<bool> ValidateAuthenticationStateAsync(AuthenticationState authenticationState, CancellationToken cancellationToken)
{
// Get the user manager from a new scope to ensure it fetches fresh data
IServiceScope scope = scopeFactory.CreateScope();
try
{
UserManager<User> userManager = scope.ServiceProvider.GetRequiredService<UserManager<User>>();
return await ValidateSecurityStampAsync(userManager, authenticationState.User);
}
finally
{
if (scope is IAsyncDisposable asyncDisposable)
await asyncDisposable.DisposeAsync();
else
scope.Dispose();
}
}
async Task<bool> ValidateSecurityStampAsync(UserManager<User> userManager, ClaimsPrincipal principal)
{
User user = await userManager.GetUserAsync(principal);
if (user is null)
return false;
else if (!userManager.SupportsUserSecurityStamp)
return true;
string principalStamp = principal.FindFirstValue(options.ClaimsIdentity.SecurityStampClaimType);
string userStamp = await userManager.GetSecurityStampAsync(user);
return principalStamp == userStamp;
}
}
AuthorizeService just calls httprequests like
public async Task<UserInfo> GetUserInfo()
{
HttpContext context = contextAccessor.HttpContext;
HttpClient client = clientFactory.CreateClient();
client.BaseAddress = new Uri($"{context.Request.Scheme}://{context.Request.Host}");
string json = await client.GetStringAsync("api/Authorize/UserInfo");
return Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfo>(json);
}
I noticed in Chrome developer tools that cookies is unchanged after login. This is probably main issue. Any idea how to fix it?
Thanks
AuthorizeService has to pass cookies. For server-side on prerendering pass cookies from HttpContext, at runtime pass cookies from javascript via IJSRuntime injection.
Implemntation looks like for custom AuthenticationStateProvider
async Task<string> GetCookiesAsync()
{
try
{
return $".AspNetCore.Identity.Application={await jsRuntime.InvokeAsync<string>("getLoginCookies")}";
}
catch
{
return $".AspNetCore.Identity.Application={httpContextAccessor.HttpContext.Request.Cookies[".AspNetCore.Identity.Application"]}";
}
}
public async Task<UserInfo> GetUserInfoAsync()
{
if (userInfoCache != null && userInfoCache.IsAuthenticated)
return userInfoCache;
userInfoCache = await authorizeSvc.GetUserInfo(await GetCookiesAsync());
return userInfoCache;
}
AuthorizeService
public async Task<UserInfo> GetUserInfo(string cookie)
{
string json = await CreateClient(cookie).GetStringAsync("api/Authorize/UserInfo");
return Newtonsoft.Json.JsonConvert.DeserializeObject<UserInfo>(json);
}
HttpClient CreateClient(string cookie = null)
{
HttpContext context = contextAccessor.HttpContext;
HttpClient client = clientFactory.CreateClient();
client.BaseAddress = new Uri($"{context.Request.Scheme}://{context.Request.Host}");
if(!string.IsNullOrEmpty(cookie))
client.DefaultRequestHeaders.Add("Cookie", cookie);
return client;
}
There is also need to mention need to do following steps for following actions
Login/Register
SignIn
GetUserInfo (including cookies)
Write cookie via javascript
Logout
Remove cookie via javascript
SignOut

Authourize tag does'nt maintain session state properly In Asp.net Core Identity ..

using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using HMS_Context;
using Microsoft.EntityFrameworkCore;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http.Features;
using HMS_Service.Services.MasterService;
using HMS_Service.Services.PatientVisitService;
using HMS_Service.UserManagementService;
using HMS_Service.Services.PatientRegistrationService;
using HMS_Service.Services.BloodCampService;
using HMS_Service.Services.AccountService;
using System;
using Microsoft.AspNetCore.Identity;
using HMS_Presentation.Services;
using HMS_Service.Services.InventoryManagementService;
using HMS_Service.Services.SystemManagementService;
using HMS_Service.Services.UserManagementService;
using HMS_Service.Services.LabManagementService;
using HMS_Service.CacheSetting.AppSettings;
using HMS_Service.Services.BarCodeService;
namespace HMS_Presentation
{
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.AddTransient<IAppSettings, AppSettings>();
services.AddMemoryCache();
services.AddOptions();
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
services.AddDbContext<_DbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<HMS_POCO.UserManagement.ApplicationUser, HMS_POCO.UserManagement.ApplicationRole>(
option => {
option.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
option.Lockout.MaxFailedAccessAttempts = 5;
option.Lockout.AllowedForNewUsers = false;
})
.AddEntityFrameworkStores<HMS_Context._DbContext>()
.AddDefaultTokenProviders();
/*Cache Functionality Start*/
/*Cache Functionality End*/
services.AddAuthorization(options =>
{
options.AddPolicy("Administrator", policy => policy.RequireRole("Admin","Superior"));
options.AddPolicy("Doctors", policy => policy.RequireRole("Receptionist","Doctor", "Superior"));
options.AddPolicy("Nurses", policy => policy.RequireRole("Nurse", "Superior"));
options.AddPolicy("Labortory", policy => policy.RequireRole("LabTech", "Superior"));
options.AddPolicy("Accountants", policy => policy.RequireRole("Accountant", "Superior"));
options.AddPolicy("Receptionist", policy => policy.RequireRole("Receptionist", "Superior"));
options.AddPolicy("RecpDoct", policy => policy.RequireRole("Receptionist","Doctor", "Superior"));
options.AddPolicy("RMO", policy => policy.RequireRole("RMO", "Superior"));
options.AddPolicy("RD", policy => policy.RequireRole("RMO", "Doctor","Superior"));
// Access DNL(Doctor,Nurse ,Lab)
options.AddPolicy("AccessDNL", policy => policy.RequireRole("Doctor", "Nurse", "LabTech", "Superior"));
});
services.ConfigureApplicationCookie(options =>
{
options.Cookie.Name = "YourAppCookieName";
options.LoginPath = "/UserAccount/Login";
options.LogoutPath = "/UserAccount/Logout";
options.AccessDeniedPath = "/UserAccount/AccessDenied";
options.ReturnUrlParameter = CookieAuthenticationDefaults.ReturnUrlParameter;
});
services.AddDistributedMemoryCache();
services.AddSession(options=>options.Cookie.HttpOnly=true);
services.AddMvc().AddSessionStateTempDataProvider();
services.AddTransient<IEmailSender, EmailSender>();
services.Configure<FormOptions>(x => {
x.ValueLengthLimit = int.MaxValue;
x.MultipartBodyLengthLimit = long.MaxValue;
x.BufferBodyLengthLimit = long.MaxValue;
x.MemoryBufferThreshold = int.MaxValue;
x.ValueCountLimit = int.MaxValue;
});
}
// 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.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
}
app.UseSession();
app.UseStaticFiles();
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
**User Account Controller**
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using HMS_Presentation.Services;
using Microsoft.Extensions.Logging;
using Microsoft.AspNetCore.Authentication;
using HMS_Presentation.Models.AccountViewModels;
using Microsoft.AspNetCore.Mvc.Rendering;
using System.Security.Claims;
using HMS_Service.UserManagementService;
using Microsoft.AspNetCore.Http;
using HMS_Service.Services.UserManagementService;
using HMS_POCO.UserManagement;
namespace HMS_Presentation.Controllers
{
[Authorize(Policy = "Administrator")]
[Route("[controller]/[action]")]
public class UserAccountController : Controller
{
private readonly UserManager<HMS_POCO.UserManagement.ApplicationUser> _userManager;
private readonly SignInManager<HMS_POCO.UserManagement.ApplicationUser> _signInManager;
private readonly IEmailSender _emailSender;
private readonly ILogger _logger;
private readonly RoleManager<HMS_POCO.UserManagement.ApplicationRole> _roleManager;
//Extra Addition
private readonly EmployeeService _employeeService;
private readonly UserAccessLogService _userAccessLogService;
public UserAccountController(
UserManager<HMS_POCO.UserManagement.ApplicationUser> userManager,
SignInManager<HMS_POCO.UserManagement.ApplicationUser> signInManager,
IEmailSender emailSender,
ILogger<UserAccountController> logger,
RoleManager<HMS_POCO.UserManagement.ApplicationRole> roleManager,
EmployeeService employeeService, UserAccessLogService userAccessLogService)
{
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_logger = logger;
_roleManager = roleManager;
_employeeService = employeeService;
_userAccessLogService = userAccessLogService;
}
[TempData]
public string ErrorMessage { get; set; }
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> Login(string returnUrl = null)
{
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
ViewData["ReturnUrl"] = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
USER_ACCESS_LOG be = new USER_ACCESS_LOG();
be.AccessTime = DateTime.Now.ToString();
be.UserName = model.Email;
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
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: true);
if (result.Succeeded)
{
var lookupUser = _userManager.Users.Where(c => c.UserName == model.Email).FirstOrDefault();
HttpContext.Session.SetInt32("UserId", lookupUser.EmpId);
_logger.LogInformation("User logged in.");
be.AccessedStatus = true;
_userAccessLogService.Add(be);
return RedirectToLocal(returnUrl);
}
if (result.RequiresTwoFactor)
{
var lookupUser = _userManager.Users.Where(c => c.UserName == model.Email).FirstOrDefault();
HttpContext.Session.SetInt32("UserId", lookupUser.EmpId);
return RedirectToAction(nameof(LoginWith2fa), new { returnUrl, model.RememberMe });
}
if (result.IsLockedOut)
{
_logger.LogWarning("User account locked out.");
return RedirectToAction(nameof(Lockout));
}
else
{
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
be.AccessedStatus = false;
_userAccessLogService.Add(be);
return View(model);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> LoginWith2fa(bool rememberMe, string returnUrl = null)
{
// Ensure the user has gone through the username & password screen first
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
throw new ApplicationException($"Unable to load two-factor authentication user.");
}
var model = new LoginWith2faViewModel { RememberMe = rememberMe };
ViewData["ReturnUrl"] = returnUrl;
return View(model);
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> LoginWith2fa(LoginWith2faViewModel model, bool rememberMe, string returnUrl = null)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
}
var authenticatorCode = model.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty);
var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, model.RememberMachine);
if (result.Succeeded)
{
_logger.LogInformation("User with ID {UserId} logged in with 2fa.", user.Id);
return RedirectToLocal(returnUrl);
}
else if (result.IsLockedOut)
{
_logger.LogWarning("User with ID {UserId} account locked out.", user.Id);
return RedirectToAction(nameof(Lockout));
}
else
{
_logger.LogWarning("Invalid authenticator code entered for user with ID {UserId}.", user.Id);
ModelState.AddModelError(string.Empty, "Invalid authenticator code.");
return View();
}
}
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> LoginWithRecoveryCode(string returnUrl = null)
{
// Ensure the user has gone through the username & password screen first
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
throw new ApplicationException($"Unable to load two-factor authentication user.");
}
ViewData["ReturnUrl"] = returnUrl;
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> LoginWithRecoveryCode(LoginWithRecoveryCodeViewModel model, string returnUrl = null)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _signInManager.GetTwoFactorAuthenticationUserAsync();
if (user == null)
{
throw new ApplicationException($"Unable to load two-factor authentication user.");
}
var recoveryCode = model.RecoveryCode.Replace(" ", string.Empty);
var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode);
if (result.Succeeded)
{
_logger.LogInformation("User with ID {UserId} logged in with a recovery code.", user.Id);
return RedirectToLocal(returnUrl);
}
if (result.IsLockedOut)
{
_logger.LogWarning("User with ID {UserId} account locked out.", user.Id);
return RedirectToAction(nameof(Lockout));
}
else
{
_logger.LogWarning("Invalid recovery code entered for user with ID {UserId}", user.Id);
ModelState.AddModelError(string.Empty, "Invalid recovery code entered.");
return View();
}
}
[HttpGet]
[AllowAnonymous]
public IActionResult Lockout()
{
return View();
}
[HttpGet]
public IActionResult Register(string returnUrl = null)
{
ViewData["RoleName"] = new SelectList(_roleManager.Roles, "Id", "Name");
ViewData["EmployeeName"] = new SelectList(_employeeService.GetUnRegisteredEmployee(), "Id", "FirstName");
ViewData["ReturnUrl"] = returnUrl;
return View();
}
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
var user = new HMS_POCO.UserManagement.ApplicationUser { UserName = model.Email, Email = model.Email, EmpId=model.EmployeeId};
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
IdentityRole res = await _roleManager.FindByIdAsync(model.RoleId);
await _userManager.AddToRoleAsync(user, res.Name);
_logger.LogInformation("User created a new account with password.");
return RedirectToLocal(returnUrl);
}
AddErrors(result);
}
ViewData["RoleName"] = new SelectList(_roleManager.Roles, "Id", "Name");
ViewData["EmployeeName"] = new SelectList(_employeeService.GetAll(), "Id", "FirstName");
return View(model);
}
[AllowAnonymous]
public async Task<IActionResult> Logout()
{
HttpContext.Session.Clear();
await _signInManager.SignOutAsync();
_logger.LogInformation("User logged out.");
return RedirectToAction(nameof(HomeController.Index), "Home");
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public IActionResult ExternalLogin(string provider, string returnUrl = null)
{
// Request a redirect to the external login provider.
var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl });
var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
return Challenge(properties, provider);
}
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{
if (remoteError != null)
{
ErrorMessage = $"Error from external provider: {remoteError}";
return RedirectToAction(nameof(Login));
}
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
return RedirectToAction(nameof(Login));
}
// Sign in the user with this external login provider if the user already has a login.
var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true);
if (result.Succeeded)
{
_logger.LogInformation("User logged in with {Name} provider.", info.LoginProvider);
return RedirectToLocal(returnUrl);
}
if (result.IsLockedOut)
{
return RedirectToAction(nameof(Lockout));
}
else
{
// If the user does not have an account, then ask the user to create an account.
ViewData["ReturnUrl"] = returnUrl;
ViewData["LoginProvider"] = info.LoginProvider;
var email = info.Principal.FindFirstValue(ClaimTypes.Email);
return View("ExternalLogin", new ExternalLoginViewModel { Email = email });
}
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ExternalLoginConfirmation(ExternalLoginViewModel model, string returnUrl = null)
{
if (ModelState.IsValid)
{
// Get the information about the user from the external login provider
var info = await _signInManager.GetExternalLoginInfoAsync();
if (info == null)
{
throw new ApplicationException("Error loading external login information during confirmation.");
}
var user = new HMS_POCO.UserManagement.ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user);
if (result.Succeeded)
{
result = await _userManager.AddLoginAsync(user, info);
if (result.Succeeded)
{
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider);
return RedirectToLocal(returnUrl);
}
}
AddErrors(result);
}
ViewData["ReturnUrl"] = returnUrl;
return View(nameof(ExternalLogin), model);
}
[HttpGet]
[AllowAnonymous]
public async Task<IActionResult> ConfirmEmail(string userId, string code)
{
if (userId == null || code == null)
{
return RedirectToAction(nameof(HomeController.Index), "Home");
}
var user = await _userManager.FindByIdAsync(userId);
if (user == null)
{
throw new ApplicationException($"Unable to load user with ID '{userId}'.");
}
var result = await _userManager.ConfirmEmailAsync(user, code);
return View(result.Succeeded ? "ConfirmEmail" : "Error");
}
[HttpGet]
[AllowAnonymous]
public IActionResult ForgotPassword()
{
return View();
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
if (ModelState.IsValid)
{
var user = await _userManager.FindByEmailAsync(model.Email);
if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
{
// Don't reveal that the user does not exist or is not confirmed
return RedirectToAction(nameof(ForgotPasswordConfirmation));
}
// For more information on how to enable account confirmation and password reset please
// visit https://go.microsoft.com/fwlink/?LinkID=532713
var code = await _userManager.GeneratePasswordResetTokenAsync(user);
var callbackUrl = Url.ResetPasswordCallbackLink(user.Id, code, Request.Scheme);
await _emailSender.SendEmailAsync(model.Email, "Reset Password",
$"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>");
return RedirectToAction(nameof(ForgotPasswordConfirmation));
}
// If we got this far, something failed, redisplay form
return View(model);
}
[HttpGet]
[AllowAnonymous]
public IActionResult ForgotPasswordConfirmation()
{
return View();
}
[HttpGet]
[AllowAnonymous]
public IActionResult ResetPassword(string code = null)
{
if (code == null)
{
throw new ApplicationException("A code must be supplied for password reset.");
}
var model = new ResetPasswordViewModel { Code = code };
return View(model);
}
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return View(model);
}
var user = await _userManager.FindByEmailAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return RedirectToAction(nameof(ResetPasswordConfirmation));
}
var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password);
if (result.Succeeded)
{
return RedirectToAction(nameof(ResetPasswordConfirmation));
}
AddErrors(result);
return View();
}
[HttpGet]
[AllowAnonymous]
public IActionResult ResetPasswordConfirmation()
{
return View();
}
[HttpGet]
public IActionResult AccessDenied()
{
return View();
}
#region Helpers
private void AddErrors(IdentityResult result)
{
foreach (var error in result.Errors)
{
ModelState.AddModelError(string.Empty, error.Description);
}
}
private IActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction(nameof(HomeController.Index), "Home");
}
}
#endregion
}
}
This is my code of Startup.cs file. and User Account Controller The authorize tag Does not maintain the session state properly .. Even after passing the session time the application starts without email and password required . How to fix it . i am using .NET CORE and visual studio 2017 and when i logout and then run the application it works Fine and take email and password. but without logout the account and close the tab and then run the application issue appears ...
Use IsPersistent=true in default signin method mentioned below:
var result = await _signInManager.PasswordSignInAsync(user, model.LoginPassword, true, false);
Here the third parameter is IsPersistent, which should be true for persistent login.