SSO FormsAuthentication - 2 Applications - 1 x Web

2019-08-17 01:16发布

问题:

I have read many posts and while I have gleaned all the information I need I cannot get this to work. So I am hopeful someone can point me in the right direction. Or if you have a working dummy project(s) even better. All the examples I have see do not specifically deal with my requirement 2.

I have an existing WebForms (W1) application that uses FormsAuthentication. As part of migrating this to MVC we want to create an MVC (M1) application "alongside" it and implement new functionality there. (It is currently out of scope to port the entire W1 application to MVC.) Existing FormsAuthentication is to be maintained and used for both sites.

Both applications will run on the same IIS but under different subdomains as:

  • w1.mydomain.com
  • m1.mydomain.com

Expectations

  1. Users will log in to W1 and once authenticated access M1 urls as well as W1 urls
  2. M1 application needs to "know" which user is logged in
  3. Logging out either via W1 or M1 will log the user out for the other application

Implemented Solution

Login:

  • Share the authentication cookie at domain level viz mydomain.com
  • On successful login in W1 redirect to M1 to set the user auth cookie
  • Redirect back from M1 to W1

Logout:

  • W1/M1 Call FormsAuthentication.SignOut(); and then redirect to the the other side to do the same

Configurations

W1

web.config

<machineKey decryption="AES" validation="HMACSHA256" decryptionKey="AutoGenerate" validationKey="AutoGenerate" />
<authentication mode="Forms">
  <forms loginUrl="~/account/login" timeout="120" defaultUrl="~/" domain=".mydomain.com" />
</authentication>
<compilation targetFramework="4.6.1"></compilation>
<!-- requestValidationMode needs to remain -->
<httpRuntime targetFramework="4.6.1" requestValidationMode="2.0" 
             maxRequestLength="20480" executionTimeout="300" />

login control on /account/login

<asp:Login ID="idLogin" runat="server" ViewStateMode="Disabled"  DestinationPageUrl="~/sso/BounceLogin.aspx" >

Code behind for BounceLogin.aspx:

public partial class BounceLogin : Page
{
    protected void Page_Load(object aSender, EventArgs aArgs)
    {
        Response.Redirect("https://m1.mydomain.com/sso/login");
    }
}

M1

web.config

<machineKey decryption="AES" validation="HMACSHA256" decryptionKey="AutoGenerate" validationKey="AutoGenerate" />
<compilation debug="true" targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1" />
<authentication mode="Forms">
  <forms loginUrl="https://w1.mydomain.com/account/login" timeout="120" domain=".mydomain.com" />
</authentication>

SSO Controller:

public class SsoController : Controller
{
    [Authorize]
    // GET: Secure
    public ActionResult Index()
    {
        return View();
    }

    public ActionResult Status()
    {
            return View(new ViewModel
            {
                TheUser = User
            });
    }

    public ActionResult Logout()
    {
        FormsAuthentication.SignOut();
        return Redirect("https://w1.mydomain.com/");
    }

    public ActionResult Login()
    {
        FormsAuthentication.SetAuthCookie("test@mydomain.com", false);
        return Redirect("https://w1.mydomain.com/sso/BounceLoginReturn");
    }
}

Interactions

So here is what happens when I log in with my test user: test@mydomain.com. (I have omitted the username passing to M1 to keep the code simpler).

A. w1.mydomain.com/account/login - Perform Successful Login and redirect to m1.mydomain.com/sso/login

B. m1.mydomain.com/sso/login - Sets cookie for user test@mydomain.com and redirects to w1.mydomain.com/BounceLoginReturn

Problem

When I return to w1.mydomain.com/BounceLoginReturn W1 still thinks I am not logged in and redirects me to w1.mydomain.com/account/login. (If I open M1 in another browser tab it tells me I am logged in as user@test.com)

I have checked and both w1.mydomain.com and m1.mydomain.com have the same cookie value set for the domain .mydomain.com.

So what am I doing wrong here to make W1 think I am not logged in bearing in mind I originally logged in via the asp:Login control it contains?

回答1:

If anyone else has this issue it turns out the solution was simple. My code above was functionally correct. I did however need to use hard coded keys:

<machineKey decryption="AES" validation="HMACSHA256" decryptionKey="{Hard Coded Key Here}" validationKey="{Hard Coded Key Here}" />

There are heaps of sites out there to generate these, but the easiest way is using IIS itself:

and then use "Generate Keys" on the right hand side.