Single sign-on with Forms Authentication
(Note: Updates after first post are in red - Dec 2004)
Every now and then I see people asking for some way to achieve single sign-on using Forms Authentication so you may reuse the Forms ticket with along several sites. It happens that you can have this functionality (not provided out of the box) with just a few tweaks.
Downloads
You can download the code sample for the SSO Forms Authentication from here. The example code is provided as source code that you can use "as is" or customize it for your own applications.
SSO Sample
The sample that you can download form the above link, has two sites. The one named “FormsAuth2” is the entry point site that will call the login page located on the “FormsAuth” site. After the authentication process, the Forms ticket will be reused from the first site “FormsAuth2” with all the user name and roles info inside it. After diving into the details, let me say that these two sites are structured in two areas (public and private) in order to clearly differentiate between the publicly accessible areas and restricted areas that require authenticated access and
Configuration
The configuration showed on the following figure is a sample of how you can set the Forms Authentication attributes with security in mind. You should follow these hints for SSO Forms Auth. First of all, you should have the same settings (see forms element attributes) that are listed below on every site that you want to adhere to SSO.<machineKey validationKey="AutoGenerate,IsolateApps" decryptionKey= "AutoGenerate,IsolateApps" validation="SHA1"/> |
The "IsolateApps" means that a different key will be AutoGenerated for *each* application. You can either remove the isolateApps option (for apps on the same machine) or insert a specific key value for it to use (for apps on different boxes). This last option is the one that is used on following the config sample.
<configuration> <system.web> <authentication mode="Forms"> <forms loginUrl="Secure\login.aspx" protection="All" requireSSL="true" timeout="10" name="FormsAuthCookie" path="/FormsAuth" slidingExpiration="true" /> </authorization> <location path="Secure" > <system.web> <authorization> <deny users="?" /> </authorization> </system.web> </location> </configuration> |
Principal Creation
After gathering the user credentials you will perform the authentication process and after that you will retrieve the user roles if you want to use the .NET role authorization pattern. This implies the creation of an Identity and a Principal object that will contain this data. So on the login page server side and after the auth process you will get the Forms ticket and save there your roles info and may be any other user profile related data (beware of size constrains, less than 4KB).
// Do auth with your preferred auth method |
Principal Retrieving
On each AuthenticateRequest event of every SSO “federated” site you may retrieve your saved user info and create your Principal object and load them onto the User object of the current HttpContext instance. This is accomplished on the following figure.if (Context.Request.IsAuthenticated) {FormsIdentity ident = (FormsIdentity)Context.User.Identity; // retrieve roles from the authentication ticket userdata field string[] arrRoles = ident.Ticket.UserData.Split(new char[] {'|'}); |
Multiple Domain Scenarios
For Domain wide authentication scenarios, you can set domain-wide cookie only for second level domain, or for third level domain if second level domain contains three or less characters. It means that you cannot set cookie for domain "com" or "co.uk", but can for "example.com" or "example.co.uk". You can find a good example of this here.