Kien Chu
Kien Chu

Reputation: 4895

ASP.NET Identity 3 cookie authentication not working as expected

The login code seems to work because PasswordSignInAsync return Succeed, but when I'm getting the user information on the next request by using User.GetUserName(), it always return me null. And also User.IsSignedIn() is also returning false.

public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
    ViewData["ReturnUrl"] = returnUrl;
    if (ModelState.IsValid)
    {
        var result = await _signInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, lockoutOnFailure: false);
        if (result.Succeeded)
        {
            // this code executed and the redirection works fine
            Logger.LogInformation(1, "User logged in.");
            return RedirectToLocal(returnUrl);
        }
        if (result.RequiresTwoFactor)
        {
            Logger.LogWarning(2, "RequiresTwoFactor");
        }
        if (result.IsLockedOut)
        {
            Logger.LogWarning(3, "User account locked out.");
        }

        ModelState.AddModelError(string.Empty, "Invalid login attempt.");
        return View(model);
    }

    return View(model);
}

In the next request, I could not get any information back.

Logger.LogWarning(User.Identity.Name ?? "User.Identity.Name is null"); // null
Logger.LogWarning(User.GetUserName() ?? "User.GetUserName() is null"); // null
Logger.LogWarning(User.IsSignedIn() ? "User is signed in" : "User is not signed in"); // not signed in

My Startup.cs

app.UseIdentity();

services.AddIdentity<CustomAccount, CustomRole>(options =>
{
    options.Cookies.ApplicationCookie.ExpireTimeSpan = TimeSpan.FromHours(24);
})
.AddEntityFrameworkStores<ApplicationDbContext, long>()
.AddDefaultTokenProviders();

Note: I'm also using app.UseJwtBearerAuthentication in the same application, could it be an issue?

Upvotes: 3

Views: 524

Answers (1)

Kien Chu
Kien Chu

Reputation: 4895

To anyone who's struggle with this issue. Here's my working code

Load the cert

NOTE: I'm importing the certificate to my Azure and load it into my application using thumbprint value

public X509Certificate2 LoadCertificate()
{
    var certStore = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    certStore.Open(OpenFlags.ReadOnly);

    var certCollection = certStore
        .Certificates
        .Find(X509FindType.FindByThumbprint,
            "", // Generated by Azure
            false);

    if (certCollection.Count > 0)
    {
        var cert = certCollection[0];
        return cert;
    }

    certStore.Dispose();
    return null;
}

Wire up the identity server

var cert = LoadCertificate();

if (cert == null)
{
    services.AddIdentityServer()
        .AddTemporarySigningCredential()
        .AddAspNetIdentity<ApplicationUser>()
        .AddConfigurationStore(builder => builder.UseSqlServer(connectionString, options => options.MigrationsAssembly(migrationsAssembly)))
        .AddOperationalStore(builder => builder.UseSqlServer(connectionString, options => options.MigrationsAssembly(migrationsAssembly)));
}
else
{
    services.AddIdentityServer()
        .AddSigningCredential(cert)
        .AddAspNetIdentity<ApplicationUser>()
        .AddConfigurationStore(builder => builder.UseSqlServer(connectionString, options => options.MigrationsAssembly(migrationsAssembly)))
        .AddOperationalStore(builder => builder.UseSqlServer(connectionString, options => options.MigrationsAssembly(migrationsAssembly)));
}

Hope it helps.

Upvotes: 1

Related Questions