Its a sample SSO application based on the proposed model. It's not just another "Hello world", it's a working application that implements SSO across three different sites under three different domains. The hard work is done, and the soft output is, you just need to extend a class for making an ASPX page a "Single Sign On" enabled one in your ASP.NET application. You, of course, have to set up an SSO site and configure your client applications to use the SSO site, that's all (merely a 10 minute work).
The SSO implementation is based on the following high level architecture:
Figure : The Single Sign On implementation model
There may be unlimited number of client sites (in our example, 3 sites) which could participate under a "Single Sign On" umbrella, with the help of a single "Single Sign On" server (call this the SSO site,
www.sso.com). As described in the previous article, the browser will not store an authentication cookie for each different client site in this model. Rather, it will store an authentication cookie for only the SSO site (
www.sso.com) which will be used by the other sites to implement Single Sign On.
In this model, each and every request to any client site (which takes part in the SSO model) will internally be redirected to the SSO site (
www.sso.com) for setting and checking the existence of the authentication cookie. If the cookie is found, the authenticated pages for the client sites (that are currently requested by the browser) are served to the browser, and if not found, the user is redirected to the login page of the corresponding site.
How it works
Initially, the browser doesn't have any authentication cookie stored for
www.sso.com. So, hitting any authenticated page in the browser for
www.domain1.com, or
www.domain2.com, or
www.domain3.com redirects the user to the login page (via an internal redirection to
www.sso.com for checking the existence of the authentication cookie). Once a user is logged onto a site, the authentication cookie for
www.sso.com is set in the browser with the logged in user information (most importantly, the user Token, which is valid only for the user's login session).
Now, if the user hits any authenticated page URL of
www.domain1.com, or
www.domain2.com or
www.domain3.com, the request is internally redirected to
www.sso.com in the user's browser and the browser sends the authentication cookie, which is already set.
www.sso.com finds the authentication cookie, extracts the user Token, and redirects to the originally requested URL in the browser with the user token, and the originally requested site validates the Token and serves the page that was originally requested by the user.
Once the user is logged onto any site under this SSO model, hitting any authenticated page on
www.domain1.com, or
www.domain2.com, or
www.domain3.com results in an internal redirection to
www.sso.com (for checking the authentication cookie and retrieving the user Token) and then serving the authentication page in the browser output.
OK, show me what you implemented
I have developed a sample Single Sign On application that incorporates three different sites (
www.domain1.com,
www.domain2.com, and
www.domain3.com) and an SSO server site (
www.sso.com). The sample SSO implementation code is available for download with this article. You just need to download and set up the sites as instructed in the next section. Once you are done with that, you can test the implementation in different scenarios.
The following section has step by step instructions to test the Single Sign On functionality in different scenarios, and each testing scenario has a Firebug network traffic information that depicts the total number of requests (including the lightweight redirect requests) and their length in size. The number of redirect requests and their length in size are marked within green for easy understandability.
Scenario1: Before authentication
Hit the following three URLs in the browser in three different tabs of the same browser window.
- www.domain1.com
- www.domain2.com
- www.domain3.com
Three different login screens will be presented in each different tabs, for each different site:
Traffic info
For presenting the login screen, in total, four requests are sent to the servers, among which three are redirect requests (marked in green). The redirect request sizes are very small (in terms of bytes), and are negligible even considering network latency.
Scenario 2: Authentication
Use one of any following credentials in any one of the login screens to log on. Let's log onto
www.domain1.com with
user1/123.
Available credentials:
- user1/123
- user2/123
- user3/123
After login, the following screen will be provided for
user1 onto
www.domain1.com.
Traffic info
For login, in total, three requests are sent to the servers, among which two are redirect requests (marked in green). The redirect request sizes are very small (in terms of bytes), and are negligible even considering network latency.
Scenario 3: After authentication
As
user1 has logged on to
www.domain1.com, he should be logged onto the other remaining sites:
www.domain2.com and
www.domain3.com at the same time, if those sites are browsed in the same window or in different tabs in the same window. Hitting an authenticated page in
www.domain2.com and
www.domain3.com should not present a login screen.
Let's just refresh the current page at
www.domain2.com and
www.domain3.com in their corresponding window (currently, the login screen is being shown in the browser):
You will see that instead of showing the login screen, the authenticated home page is being shown. So,
user1 is logged onto all three sites:
www.domain2.com,
www.domain2.com, and
www.domain3.com.
Each home page shows a "Go to Profile Page" link which you can click to navigate to another page. This demonstrates that clicking on hyperlinks and navigating to other pages in the application also works without any problem.
Traffic info
For browsing authenticated pages after login, in total, 3 requests are sent to the servers, among which 2 are redirect requests (marked in green). The redirect request sizes are also very small (in terms of bytes), and are negligible even considering network latency.
Scenario 4: Hit the authenticated page on a different session
As expected, the user's "Sign on" status should only be valid for the current session ID, and any authenticated page URL hit to any one of the three sites will be successful if the URL is hit in the same browser window or in a different tab of the same browser window. But, if a new browser window is opened, and an authenticated URL is hit there, it should not be successful and the request should be redirected to the login page (because that is a different browser session).
To test this, open a new browser window and hit any URL of the three sites that points to an authenticated page (you can copy and paste the existing URL addresses). This time, instead of showing the page output, you will see the request will be redirected to the login page as follows (assuming that you hit a URL of
www.domain3.com):
Traffic info
For hitting an authenticated page on a different session, in total, 4 requests are sent to the servers, among which 3 are redirect requests (marked in green). The redirect request sizes are very small (in terms of bytes), and are negligible even considering network latency.
Log out
To log out of the sites, click on the "Log out" link of the home page of
www.domain1.com. The system will log out
user1 from the site
www.domain1.com and will redirect to the login screen again:
Traffic info
For logging out, in total, 4 requests are sent to the servers, among which 3 are redirect requests (marked in green). The redirect request sizes are very small (in terms of bytes), and are negligible even considering network latency.
After log out
As
user1 is logged out of the site
www.domain1.com, he should be logged out from
www.domain2.com and
www.domain3.com at the same time. So, hitting any authenticated page URL of
www.domain2.com and
www.domain3.com should now redirect to their corresponding login screens.
To test this, refresh the current page of
www.domain2.com and
www.domain3.com. Instead of refreshing the page, the system will now redirect the requests to their login pages:
Traffic info
Same as login.
Great... this seems to be working! How do I set up the sites?
The sample SSO implementation has been developed using Visual Studio 2010, .NET 4.0 Framework, and tested in IIS 7 under a Windows Vista machine. However, it doesn't use any 4.0 framework specific technology or class library and hence, it can be converted to use for a lower level framework without much effort, if required.
Follow these steps to set up the example SSO implementation in your machine:
127.0.0.1 localhost
127.0.0.1 www.domain1.com
127.0.0.1 www.domain2.com
127.0.0.1 www.domain3.com
127.0.0.1 www.sso.com
If things are correctly done, you should be able to run the sites and test correctly as shown above. Otherwise, please verify if there is any thing missing or misconfigured by reviewing the steps from the start.
OK, how do I implement SSO for my sites?
Good question. The sample SSO implementation works fine. But, as a developer, you would likely be more interested in how to implement SSO in your ASP.NET sites using the things developed. While implementing the SSO model, I tried to make a pluggable component (
SSOLib.dll) so that it requires minimum programmatic change and configuration. Assuming that you have some existing ASP.NET applications, you need the following steps to implement "Single Sign On" across them:
- Add a reference to "SSOLib.dll", or add a reference to the "SSOLib" project to each ASP.NET application.
- Set up the SSO site (see previous steps).
- Configure your ASP.NET applications to use the SSO site. To do this, just add the following configurations in the web.confing of each ASP.NET application:
<!---->
<configSections>
<sectionGroup name="applicationSettings"
type="System.Configuration.ApplicationSettingsGroup, System,
Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="SSOLib.Properties.Settings"
type="System.Configuration.ClientSettingsSection, System,
Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089"
requirePermission="false" />
</sectionGroup>
</configSections>
<applicationSettings>
<SSOLib.Properties.Settings>
<setting name="SSOLib_Service_AuthService" serializeAs="String">
<value>http://www.sso.com/AuthService.asmx</value>
</setting>
</SSOLib.Properties.Settings>
</applicationSettings>
<appSettings>
<add key="SSO_SITE_URL"
value="http://www.sso.com/Authenticate.aspx?ReturnUrl={0}" />
<add key="LOGIN_URL" value="~/Login.aspx" />
<add key="DEFAULT_URL" value="~/Page.aspx" />
</appSettings>
<!---->
Note: Modify the configuration values according to the SSO site URL of your setup and your application specific needs.
Modify the code-behind classes (*.aspx.cs) of the login page and other private pages (pages which are accessible only to authenticated users) so that instead of extending System.Web.UI.Page
, they will extend the SSOLib.PrivatePage
class.
In addition to existing codes that perform the log out functionality, call the Logout()
method that is already available to the code-behind classes from the SSOLib.PrivatePage
base class. Also, instead of executing existing login functionality, call the Login()
method of SSOLib.PrivatePage
and execute other post-login codes if they exist already.
That's it! You should be done with your SSO implementation.
Hold on! My pages already extend a base class
OK, there is a high chance that you already have a base class which is extended by the code-behind classes in your ASP.NET applications. If that is so, integrating the
SSOLib.PrivatePage
may become even easier for you.
Let's say there is already a
BasePage
class which is extended by the code-behind classes of the authenticated page (pages which are accessible onto to the authenticated users) in one of your applications. In this case, instead of modifying the code-behind classes of all the ASPX pages, you might just need to modify the
BasePage
so that it extends
SSOLib.PrivatePage
, and you are done.
class BasePage : SSOLib.PrivatePage
{
...
}
Another alternative is to modify
SSOLib.PrivatePage
to extend the existing
BasePage
(you have the source code, you can do it) and modify all the existing
aspx.cs classes of the authenticated pages to extend
SSOLib.PrivatePage
as suggested. That is:
class PrivatePage : BasePage
{
...
}
If there is any conflicting code or method between the existing
BasePage
class and the
SSOLib.PrivatePage
class, you might need to modify some code in these two classes. It would be preferable not to change the code of
SSOLib.PrivatePage
unless any bug is discovered, and it would be better to change the existing
BasePage
code as required. But, feel free to change the code of
SSOLib.PrivatePage
if you really need to, it's all yours!
Hmm.. so who does all the SSO things? Where is the magic?
Good question. In the ideal case, using this example SSO model, you won't have to write a single line of Sign On oriented code to implement SSO in your ASP.NET applications (except some configuration and inheritance changes). How is this possible? Who is managing all the dirty SSO stuff?
SSOLib and the SSO site are the two magicians doing all the tricks. SSOLib is a DLL which is used by each client site to carry out the following things:
- Communicate to SSO site via a Web Service.
- Redirect to the SSO site or login page or serve the requested page.
The following diagram depicts the role of SSOLib in the SSO model:
The most important thing inside SSOLib is the
PrivatePage
class which is inherited by the code-behind pages of the authenticated classes. This class inherits the
System.Web.UI.Page
class, and overrides the
OnLoad()
method, as follows:
public class PrivatePage : Page
{
protected override void OnLoad(EventArgs e)
{
SetCachingPreferences();
LoadParameters();
if (IsPostBack)
{
HandlePostbackRequest();
base.OnLoad(e);
return;
}
if (SessionAPI.RequestRedirectFlag == false)
{
SessionAPI.ClearRedirectFlag();
base.OnLoad(e);
return;
}
if (string.IsNullOrEmpty(RequestId))
{
RedirectToSSOSite();
return;
}
else
{
ValidateUserStatusAndRedirect();
}
base.OnLoad(e);
}
}
Basically,
OnLoad()
is called whenever a
Page
object is loaded as a result of a URL hit in the browser, and the core SSO logic is implemented inside this method. All the codes is self descriptive and documented to depict what is going on.
More on the SSOLib functionality in the following sections.
What does www.sso.com do?
The SSO site has the following two important functionalities:
- User authentication and user retrieval Web Services which are accessed by the client sites via the SSOLib DLL to authenticate the user and to know the user's logged-in status on the SSO site. The following services are available:
- Setting and retrieving user authentication cookie using an ASPX page (Authenticate.aspx) which is redirected by SSOLib for setting / checking or removing the cookie based upon the type of request.
Following is the core functionality that is performed by Authenticate.aspx. The codes is self-descriptive and documented for easy understandability.
protected void Page_Load(object sender, EventArgs e)
{
LoadRequestParams();
if (Utility.StringEquals(Action, AppConstants.ParamValues.LOGOUT))
{
LogoutUser();
return;
}
else
{
if (Token != null)
{
SetAuthCookie();
}
else
{
HttpCookie AuthCookie =
Request.Cookies[AppConstants.Cookie.AUTH_COOKIE];
if (AuthCookie != null)
{
CheckCookie(AuthCookie, ReturnUrl);
}
else
{
MarkUserLoggedOut();
}
}
}
}
Looks pretty good. Did you have to handle any critical issues?
Another good question. The core SSO logic seems pretty straightforward. That is:
If current request is a PostBack,
If this is a PostBack in Login page (For Login)
Do Nothing
Else
Do not redirect to SSO site. Rather, invoke a web service at SSO site
to know user's logged in status, using the User *Token.
If user is not logged out
Proceed the normal PostBack operation.
Else
Redirect to login page
Else
If current request is not redirected from the SSO Site,
Redirect it to SSO site with setting ReturnUrl with
the current Request URL and parameters.
Else
Get user's Logged in status on SSO Site
by invoking a web service with user *Token
If user is logged out there,
Redirect to Login page
If current request is a page refresh,
Redirect to SSO site with ReturnUrl
Else
Redirect to the originally requested URL
End If
End If
*User token is a hash code of a GUID that identifies a user's login onto the SSO site uniquely. Each time a user is logged onto the SSO site, the token is generated at the SSO site, and this token
is used later to set the authentication cookie and to retrieve the user object by the client sites.
But there are some obvious issues that were needed to be handled to implement the SSO logic. These are marked in bold in the above logic:
Implement "
Redirect to login page" and "
Redirect to the originally requested URL"
SSOLib.PrivatePage
redirects to the SSO site, or redirects to the currently requested page at the client site, based upon the situation. But, there is a problem if
SSOLib.PrivatePage
redirects to a page of the current site. As each authenticated page extends the
SSOLib.PrivatePage
class, a redirect to a page in the current site from
SSOLib.PrivatePage
would redirect to itself again and again, and will cause an infinite redirect loop.
To solve this issue, an easy fix could be to add a request parameter (say,
Redirect=false
) to indicate that the request should not be redirected any further. But, this would allow the user to see the
Request
parameter and allow the user to "hack" the system by altering its value. So, instead of using a
Request
parameter, I used a Session variable to stop further redirection, before redirecting to any URL of the current site from
SSOLib.PrivatePage
. In
OnLoad
()
, I check the Session variable and reset it and return as follows:
if (SessionAPI.RequestRedirectFlag == false)
{
SessionAPI.ClearRedirectFlag();
return;
}
Detect whether "
Current request is not redirected from the SSO Site", and whether "
current request is a page refresh"
SSOLib.PrivatePage
redirects to the SSO site for setting or checking the authentication cookie. After the SSO site is done with its work, it redirects back to the calling site using the URL that is set in
ReturnUrl
.
This also creates a scenario where the client site might again redirect to the SSO site and the SSO site again redirects to client site and creates an infinite redirection loop. Unlike the previous situation, this time, a Session variable could not be used because the redirection is occurring from the SSO site, and the client site and the SSO site have different Session states. So, a
Request
parameter value should be used to prevent further redirect to the SSO site once the SSO site redirects to the client site.
But again, using a
Request
parameter to prevent redirection would allow the user to alter it and break the normal functionality. To work-around this, the
Request
parameter value is set with a hash of a GUID
(RequestId=Hash(New GUID)
), and this is appended from the SSO site before redirecting back to the client-site URL.
The redirect request executes the
OnLoad()
method of
SSOLib.PrivatePage
again, and this time, it finds the
RequestId
, and this indicates that this request is redirected back from the SSO site and hence this should not be redirected to the SSO site further.
But, what if the user alters the value of the
RequestId
in the query string and hits the URL, or the user just refreshes the current page?
As each different request is to be redirected to the SSO site (except the postback hits), in this case, this request should be redirected to the SSO site as usual. But, the request URL already contains a
RequestId
, and despite this, the request should be redirected to the SSO site. So, how should
SSOLib.PrivatePage
understand this?
There is only one way. A specific
RequestId
should be valid for each particular redirect from the SSO site only, and once the
RequestId
is received at the client site from the
Request
parameter, it should expire instantly so that even if the next URL hit contains the same
RequstId
, or if the next URL contains an invalid value, it redirects to the SSO site.
The following logic has been used to handle this scenario:
if (string.IsNullOrEmpty(RequestId))
{
RedirectToSSOSite();
return;
}
else
{
ValidateUserStatusAndRedirect();
}
UserStatus userStatus = AuthUtil.Instance.GetUserStauts(Token, RequestId);
if (!userStatus.UserLoggedIn)
{
RedirectToLoginPage();
return;
}
if (!userStatus.RequestIdValid)
{
RedirectToSSOSite();
return;
}
if (CurrentUser == null || CurrentUser.Token != Token)
{
CurrentUser = AuthUtil.Instance.GetUserByToken(Token);
if (CurrentUser.Token != Token || CurrentUser == null)
{
RedirectToSSOSite();
return;
}
}
On the other hand, before redirecting to the client site, the SSO site generates a
RequestId
, appends it with the query string, and puts it in
Application
using the
RequestId
as the key and value. Following is how the SSO site redirects back to the client site:
private void Redirect(string Url)
{
string RequestId = Utility.GetGuidHash();
string redirectUrl = Utility.GetAppendedQueryString(Url,
AppConstants.UrlParams.REQUEST_ID, RequestId);
Application[RequestId] = RequestId;
Response.Redirect(redirectUrl);
}
Note that, before redirection,
RequestId
is stored in the
Application
scope to mark that this
RequestId
is valid for this particular response to the client site. Once the client site receives the redirected request, it executes the
GetUserStatus()
Web Service method, and following is how the
GetUserStatus()
web method clears the
RequestId
from the
Application
scope so that any subsequent requests with the same
RequestId
or any request with an invalid
RequestId
can be tracked as an invalid
RequestId
:
[WebMethod]
public UserStatus GetUserStauts(string Token, string RequestId)
{
UserStatus userStatus = new UserStatus();
if (!string.IsNullOrEmpty(RequestId))
{
if ((string)Application[RequestId] == RequestId)
{
Application[RequestId] = null;
userStatus.RequestIdValid = true;
}
}
userStatus.UserLoggedIn =
HttpContext.Current.Application[Token] == null ? false : true;
return userStatus;
}
Get user's logged in status on the SSO site
The
GetUserStauts()
Web Service method returns the user's status inside a
UserStatus
object, which has two properties:
UserLoggedIn
and
RequestIdValid
.
Once a user is logged onto the SSO site via the
Authenticate
Web Service method, it generates a User Token (hash code of a new GUID) and stores the user Token
inside an
Application
variable using the Token as the Key:
[WebMethod]
public WebUser Authenticate(string UserName, string Password)
{
WebUser user = UserManager.AuthenticateUser(UserName, Password);
if (user != null)
{
HttpContext.Current.Application[user.Token] = user;
}
return user;
}
When the user logs out of the system from any client site, the authentication cookie is removed, and also the user object is removed from the
Application
scope (inside
Authenticate.aspx.cs in the SSO site):
private void LogoutUser()
{
if (Token != null)
{
HttpCookie Cookie = Request.Cookies[AppConstants.Cookie.AUTH_COOKIE];
if (Cookie.Value == Token)
{
RemoveCookie(Cookie);
}
}
Application[Token] = null;
Redirect(ReturnUrl);
}
So, without redirecting to the SSO site, it is possible to know the user's logged in status just by checking the user's presence in the
Application
scope of the SSO site. The client sites invoke the Web Service method of the SSO site, and the SSO site returns the user's logged in status inside the
UserStatus
object.
This method of knowing the user's logged in status is handy because when a postback occurs, the client sites would not want to redirect to the SSO site (because, if they do that, the postback event methods cannot be executed).
In such cases, they invoke the web method to know the user's logged in status, and if the user is not available at the SSO site, the current request is redirected to the login page. Otherwise, the normal postback event method is executed.
Wait a minute, storing the user in the Application scope should mark the user logged in for all sessions. How do you handle that?
True. Once a user is authenticated, he/she is stored in the
Application
scope to mark as logged in. But, the
Application
scope is a global scope irrespective of the site and user sessions. So, there is a risk that the user might also get marked as logged in for all browser sessions.
This sounds risky. But, this is handled with care so that the user object of a particular browser session is not available to other browser sessions. Let us now see how this has been handled.
Once a user logs onto the SSO site, the user is stored in the
Application
scope against the user
Token
, which is valid only for a particular user Login session.
If some direct request is hit in a new window (hence with a new
Session
) with the user Token (with or without the
RequestId
) by copying the URL from the address bar, the system will not let the URL request bypass the login screen. Why? Because the authentication cookie that is set by the SSO site is a "non-persistent" cookie, and hence this cookie is sent by the browser to the SSO site only if subsequent requests are hit in the same browser session (from the same browser window or different tabs in the same window). That means, if a new browser window is opened, it does not have any authentication cookie to send to the SSO site, and naturally, the request is redirected to the login page of the client site. So, even if a user is stored in the
Application
scope in the SSO site, that user object is stored against a different user Token as a key, that can never be accessed for any new request in the new session, because this request does not know about the existing user Token, and once the user logs onto this new browser session, it gets a new user Token which never matches with the existing ones.
How cookie timeout and sliding expiration is maintained?
The
web.config of the SSO site has configuration options for configuring the cookie timeout value and for enabling/disabling the sliding expiration of the cookie.
<appSettings>
<add key="AUTH_COOKIE_TIMEOUT_IN_MINUTES" value="30"/>
<add key="SLIDING_EXPIRATION" value="true"/>
</appSettings>
The cookie timeout value can be configured in the
web.config of the SSO site and the timeout value applies to all client sites under the SSO. That is, if the cookie timeout value is specified in the
web.config as 30 minutes and if
user1 logs onto
www.domain1.com, the cookie is available for the next 30 minutes in the browser, and hence
user1 is signed on the other two sites for this 30 minutes, unless
user1 is logged out of the site.
Now, how is this cookie timeout implemented? Simple, by setting the cookie expiration time, of course.
Unfortunately, I couldn't do that. Why? Because, by default, when a cookie is set in the
Response
, it is created as a non-persistent cookie (the cookie is stored only in the browser's memory for the current session, not in the client's disk). If the expiry date is specified for the cookie, ASP.NET runtime automatically instructs the browser to store the cookie as a persistent cookie.
In our case, we don't want to create a persistent cookie, because this will let the other sessions to also send the authentication cookie to the SSO site and eventually mark the user as logged in. We do not want that to happen.
But, the expiration datetime has to be set somehow. So, I stored the expiration value in the cookie's value, along with appending to the user's Token, as follows:
private void SetAuthCookie()
{
HttpCookie AuthCookie = new HttpCookie(AppConstants.Cookie.AUTH_COOKIE);
int CookieTimeoutInMinutes = Config.AUTH_COOKIE_TIMEOUT_IN_MINUTES;
AuthCookie.Value = Utility.BuildCookueValue(Token, CookieTimeoutInMinutes);
Response.Cookies.Add(AuthCookie);
ReturnUrl = Utility.GetAppendedQueryString(ReturnUrl,
AppConstants.UrlParams.TOKEN, Token);
Redirect(ReturnUrl);
}
public static string BuildCookueValue(string Value, int Minutes)
{
return string.Format("{0}|{1}", Value,
DateTime.Now.AddMinutes(Minutes).ToString());
}
Eventually, when the cookie is received at the SSO site, its value is retrieved as follows:
public static string GetCookieValue(HttpCookie Cookie)
{
if (string.IsNullOrEmpty(Cookie.Value))
{
return Cookie.Value;
}
return Cookie.Value.Substring(0, Cookie.Value.IndexOf("|"));
}
And, the expiration date time is retrieved as follows:
public static DateTime GetExpirationDate(HttpCookie Cookie)
{
if (string.IsNullOrEmpty(Cookie.Value))
{
return DateTime.MinValue;
}
string strDateTime =
Cookie.Value.Substring(Cookie.Value.IndexOf("|") + 1);
return Convert.ToDateTime(strDateTime);
}
If
SLIDING_EXPIRATION
is set to
true
in the
web.config, the cookie expiration date-time value is increased with each request, with the minute value specified in
AUTH_COOKIE_TIMEOUT_IN_MINUTES
in the
web.config. The following code does that:
private HttpCookie IncreaseCookieExpiryTime(HttpCookie AuthCookie)
{
string Token = Utility.GetCookieValue(AuthCookie);
DateTime Expirytime = Utility.GetExpirationDate(AuthCookie);
DateTime IncreasedExpirytime =
Expirytime.AddMinutes(Config.AUTH_COOKIE_TIMEOUT_IN_MINUTES);
Response.Cookies.Remove(AuthCookie.Name);
HttpCookie NewCookie = new HttpCookie(AuthCookie.Name);
NewCookie.Value =
Utility.BuildCookueValue(Token, Config.AUTH_COOKIE_TIMEOUT_IN_MINUTES);
Response.Cookies.Add(NewCookie);
return NewCookie;
}
Can this implementation be used for production systems?
Yes! It surely can be used,
but before that, some security and other cross-cutting issues have to be addressed. This is just a basic implementation, and I didn't verify the model with a professional Quality Assurance process (though I did some basic acceptance testing myself). Also, this authentication does not offer the full flexibility and powers that Forms authentication provides. Additionally, it does not have the built-in authorization mechanism of Forms authentication, and hence you might need to write some more customization on the current SSO implementation, based upon your specific requirements.
However, I'll try to update the SSO model to enrich it with more features and make it robust so that this could be used in commercial systems without requiring any customization.