levkaster
levkaster

Reputation: 2730

ASP.NET identity auth session and cookie works only locally

I'm using ASP.NET Identity and it works perfectly locally with regular login and external login. For some reason when I publish my project and run it on remote server I have about 1 minuet of my authorization session. After 1 minute I'm redirected to my login page. (No error message)

My startup auth config:

public partial class Startup
    {
     public void ConfigureAuth(IAppBuilder app)
        {
            app.CreatePerOwinContext(ApplicationDbContext.Create);
            app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
            app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/Account/Login"),
                ExpireTimeSpan = TimeSpan.FromDays(2),
                Provider = new CookieAuthenticationProvider
                {
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, VisU>(
                        validateInterval: TimeSpan.FromMinutes(30),
                        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
                }
            });
            var googleOptions = new GoogleOAuth2AuthenticationOptions()
                   {
                       ClientId = "***",
                       ClientSecret = "***",
                       SignInAsAuthenticationType = DefaultAuthenticationTypes.ExternalCookie,
                       Provider = new GoogleOAuth2AuthenticationProvider()
                       {
                           OnAuthenticated = (context) =>
                       {
                           context.Identity.AddClaim(new Claim("urn:google:name", context.Identity.FindFirstValue(ClaimTypes.Name)));
                           context.Identity.AddClaim(new Claim("urn:google:email", context.Identity.FindFirstValue(ClaimTypes.Email)));
                           context.Identity.AddClaim(new Claim("urn:google:accesstoken", context.AccessToken, ClaimValueTypes.String, "Google"));
                           return Task.FromResult(0);
                       }
                   }
               };
               app.UseGoogleAuthentication(googleOptions);
}

My Account controller:

[AllowAnonymous]
public ActionResult Login(string returnUrl)
{
    ViewBag.ReturnUrl = returnUrl;
    return View();
}


[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<string> Login()
{
            var result = await SignInManager.PasswordSignInAsync(Request.Form["emailLogin"], Request.Form["passwordLogin"], true, shouldLockout: true);
            switch (result)
            {
                case SignInStatus.Success:
                    return ViewBag.ReturnUrl ?? "https://localhost:44300/Account";
                case SignInStatus.LockedOut:
                    return Resources.Multilang.ERRORLockedOut;
                case SignInStatus.Failure:
                    //Mail or password are incorrect
                    return Resources.Multilang.ERRORInvalidLogin;
                default:
                    return Resources.Multilang.ERRORInvalidLogin;
            }
  }

What could be a reason for this behavior?

("https://localhost:44300/" is changed to my domain name when published.)

Upvotes: 1

Views: 863

Answers (1)

Tommy
Tommy

Reputation: 39807

One of the most common causes of this issue is not setting the MachineKey element in your web.config. The MachineKey is what is used to encrypt and decrypt things such as your authorization cookie. When the MachineKey element is not set, IIS will make up a MachineKey for you.

Where this becomes an issues isif you are publishing your application to 3rd party web hosting such as Azure or GoDaddy. These providers typically have the web applications on more than one web server. Since the web server will makeup its own MachineKey if one is not set, each web server hosting your application will have its own MachineKey. The end result is that web server A issues and encrypts the authorization cookie. If the next request goes to web server B, it will not be able to decrypt and read the cookie, so it assumes you are not logged in.

Setting a MachineKey in your web.config ensures that each web server hosting your application can encrypt and decrypt the authorization cookie without issue.

Upvotes: 2

Related Questions