I'm trying to create my own login authentication, it wasn't working so I create this quick test...
[HttpGet]
public IActionResult Index()
{
try
{
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
identity.AddClaim(new Claim(ClaimTypes.Name, "Test Name"));
var principal = new ClaimsPrincipal(identity);
SignIn(principal, CookieAuthenticationDefaults.AuthenticationScheme);
var isAuthenticated = User.Identity.IsAuthenticated; //-- THIS IS ALWAY FALSE... BUI JUST LOGGED IN?!?!?!?
return View();
}
catch(Exception ex)
{
_logger.LogError(ex, "Error:");
return StatusCode(500);
}
}
So you can see I call SignIn
then on the next line I check if the user is now authenticated but its always returns false, also the User.Identity
looks empty. Does anyone know what i'm doing wrong here?
In my Startup / ConfigureServices i have:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme).AddCookie(
CookieAuthenticationDefaults.AuthenticationScheme,
options =>
{
options.LoginPath = "/Admin/Index";
});
And in Startup / Configure
app.UseAuthentication();
app.UseCookiePolicy(new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.Strict,
});
SignIn(principal, CookieAuthenticationDefaults.AuthenticationScheme);
This is a no-op. SignIn
is a convenience method for creating an instance of a SignInResult
and would usually be returned from an action. This follows the command pattern, but your example just creates the command and never executes it.
What you really want is the following:
await HttpContext.SignInAsync(principal);
You can provide the the scheme if you want to, but you've set CookieAuthenticationDefaults.AuthenticationScheme
as the default in ConfigureServices
so this will be assumed.
However, even with this change, User.Identity.IsAuthenticated
will still be false
until another request is made. Typically, you'd do something like this:
await HttpContext.SignInAsync(principal);
return RedirectToAction(...);
With your setup, calling SignInAsync
ends up creating a cookie that stores the authentication information. It doesn't update the current User
. On the next request, caused by the redirect, the cookie is read by your ASP.NET Core app and the User
is populated correctly.
I see your Index
method missing Authorize
attribute. Please add Authorize
attribute as follows:
[Authorize]
[HttpGet]
public IActionResult Index()
{
....
}
Then in the Configure
method of the Startup
class the middlewares order should be as follows:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
......
app.UseStaticFiles();
app.UseCookiePolicy(new CookiePolicyOptions
{
MinimumSameSitePolicy = SameSiteMode.Strict,
});
app.UseAuthentication();
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
Now it should work for you.
Here is sourcecode fo SignIn
public virtual SignInResult SignIn(
ClaimsPrincipal principal,
string authenticationScheme)
=> new SignInResult(authenticationScheme, principal);
Above code simply returns an object SignInResult
, which does nothing action at that moment.
Here is sourcecode of SignInResult
: https://github.com/aspnet/Mvc/blob/master/src/Microsoft.AspNetCore.Mvc.Core/SignInResult.cs
Here is core code:
public class SignInResult : ActionResult
{
/// <inheritdoc />
public override async Task ExecuteResultAsync(ActionContext context)
{
...
await context.HttpContext.SignInAsync(AuthenticationScheme, Principal, Properties);
}
}
It is a return type ActionResult
and it's simply calling context.HttpContext.SignInAsync
, so ControllerBase.SignIn
is the sort of shortcut for HttpContext.SignInAsync()
.
BUT! Take a look the following ActionResult
:
public abstract class ActionResult : IActionResult
{
public virtual Task ExecuteResultAsync(ActionContext context)
{
this.ExecuteResult(context);
return Task.CompletedTask;
}
public virtual void ExecuteResult(ActionContext context)
{
}
}
So SignInResult
does nothing on the Sync
method, but only Async
.
What I can suggest is:
return SignIn(...)
, then the action will be proformed automatically, then you can check if its authorized in next request. HttpContext.SignInAsync()
, which is for your current code. SignInResult
implemented the async
function only, but does nothing in sync
method, so you can try to change your test action to async Task<IActionResult>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.