简体   繁体   中英

Single Sign On using ASP.NET Identity between 2 ASP.NET MVC projects

I have 2 web applications that both share the same main level domain as mentioned below so I can share cookies. Web.conifg in both the projects have same machine key and validation key. Since, I want to use Identity and NOT forms authenticaiton, I do not have an node in either of my web.config file. I am able to create the Auth cookie successully from SSO and can view the authorized pages in SSO but I am still redirected to SSO login when I try to access an authorized view in MVC project.

  1. sso.domain.com - MVC Project
  2. mvc.domain.com - MVC Project

I have a startup.cs file in my SSO and MVC project like below:

    public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
    }

    // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
    public void ConfigureAuth(IAppBuilder app)
    {
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        // Enable the application to use a cookie to store information for the signed in user
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            ExpireTimeSpan = TimeSpan.FromMinutes(3),                
            LoginPath = new PathString("/Login"),
            CookieName = "MyCookieName",
            CookieDomain = ".domain.com"               
        });

        app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);

        AntiForgeryConfig.UniqueClaimTypeIdentifier = ClaimTypes.NameIdentifier;
    }
}

Below is the code I have so far in the SSO project under the AccountController.cs. I call the IdentitySignin function below on validating the user against the database which creates the cookie:

        private void IdentitySignin(string userId, string name, string providerKey = null, bool isPersistent = false)
    {
        var claims = new List<Claim>();

        // create *required* claims
        claims.Add(new Claim(ClaimTypes.NameIdentifier, userId));
        claims.Add(new Claim(ClaimTypes.Name, name));            

        var identity = new ClaimsIdentity(claims, DefaultAuthenticationTypes.ApplicationCookie);


        //get the expiry minutes from config or use the default value of 30 minutes
        double expiryMinutes;
        expiryMinutes = double.TryParse(ConfigurationManager.AppSettings["AuthCookieExpiryMinutes"], out expiryMinutes) ? expiryMinutes : 30;

        // add to user here!
        AuthenticationManager.SignIn(new AuthenticationProperties()
        {
            AllowRefresh = true,
            IsPersistent = isPersistent,
            ExpiresUtc = DateTime.UtcNow.AddMinutes(expiryMinutes),
            IssuedUtc = DateTime.UtcNow                  
        }, identity);
    }

    private void IdentitySignout()
    {
        AuthenticationManager.SignOut(DefaultAuthenticationTypes.ApplicationCookie, DefaultAuthenticationTypes.ExternalCookie);
    }

    private IAuthenticationManager AuthenticationManager
    {
        get
        {
            return HttpContext.GetOwinContext().Authentication;
        }
    }

    private async Task<string> GetVerifiedUserIdAsync()
    {
        var result = await AuthenticationManager.AuthenticateAsync(
            DefaultAuthenticationTypes.ApplicationCookie);

        if (result != null && result.Identity != null
            && !String.IsNullOrEmpty(result.Identity.GetUserId()))
        {
            return result.Identity.GetUserId();
        }
        return null;
    }

Most likely, you haven't set a shared machine key. The auth cookie is encrypted, and unless both sites share the same machine key, one cannot decrypt what the other encrypted. Add the following to both project's Web.config:

<sytem.web>

    ...

    <machineKey validation="HMACSHA256" validationKey="[validationKey]"  decryptionKey="[decryptionKey]" compatibilityMode="Framework45" />

To generate the keys, in IIS, click on the server in the left pane, and then the Machine Key control panel item. Choose your validation method (above, I've used HMACSHA256). I don't recommend using the default of SHA1 as that's ridiculously easy to crack. Then, on the right "Actions" panel, click "Generate Keys". Copy the two text box values to the appropriate attributes of this config element, and make sure they are the same for all projects that need to share the auth cookie.

So, I figured out the reason why Single Sign On wasn't working between 2 MVC applications in-spite of both of them sharing the same machine and validation keys.

My SSO MVC application and the other MVC application were both using different version of OWIN and ASP.NET Identity DLLs. I used the Nuget to update the DLLS in one project but did not do the update in the other one.

I hope this helps someone who runs into this problem.

Just as an FYI, to share ASP.NET Identity Authentication between more than 1 application, make sure you have below things in EACH APP :

  1. Same Machine Keys and Validation Keys in the web.config file
  2. Same versions of OWIN and ASP.NET IDENTITY DLLs
  3. SAME COOKIE NAME AND COOKIE DOMAIN in the Startup.cs
  4. Both app needs to be on same domain to share the auth cookie

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM