private void Application_AuthenticateRequest(Object source, EventArgs e)
{
CasAuthenticationConfigurationSection configuration = (CasAuthenticationConfigurationSection)
WebConfigurationManager.GetSection(
HttpContext.Current,
CasAuthenticationConfigurationSection.SectionName,
typeof(CasAuthenticationConfigurationSection));
// skip all if the module is not enabled
if (!configuration.Enabled)
return;
// get a HttpApplication objects to gain access request and response properties.
HttpApplication application = (HttpApplication)source;
// retrieve the cas host urls from web configuration file
if (String.IsNullOrEmpty(configuration.LoginUrl))
{
// trigger a server error if cashost is not set in the web.config
throw new HttpException(500, "CasAuthentication module misconfigured : missing LoginUrl");
}
string casLogin = configuration.LoginUrl;
if (String.IsNullOrEmpty(configuration.ValidateUrl))
{
// trigger a server error if cashost is not set in the web.config
throw new HttpException(500, "CasAuthentication module misconfigured : missing ValidateUrl");
}
string casValidate = configuration.ValidateUrl;
// Create a generic principal on each request based on the authentication ticket cookie
// The user's role is also extracted from this cookie and pushed into the generic principal
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = application.Request.Cookies[cookieName];
// if the cookie exist we are authenticated
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = null;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch
{
// TODO: Make a 500 error or go back to authentication
return;
}
if (authTicket == null)
{
throw new HttpException(401, "");
}
// create an identity objet
FormsIdentity identity = new FormsIdentity(authTicket);
// create a principal
GenericPrincipal principal = new GenericPrincipal(identity, null);
// attach the principal to tue context objet that will flow throughout the request.
application.Context.User = principal;
}
else
{
// Check if we are back from CAS Authentication
// Look for the "ticket=" string after the "?" in the URL when back from CAS
string casTicket = application.Request.QueryString["ticket"];
// The CAS service name is the page URL for CAS Server call back
// so any query string is discard.
string service = application.Request.Url.GetLeftPart(UriPartial.Path);
// First pass because there is no ticket, so redirect to CAS login
if (casTicket == null || casTicket.Length == 0)
{
// memorize the initial request query string
application.Response.Cookies[ReturnUrl].Value = application.Request.RawUrl;
// redirect to cas server
string redir = casLogin + "?service=" + service;
application.Response.Redirect(redir);
return;
}
else
{
// Second pass (return from CAS server) because there is a ticket in the query string to validate
string validateurl = casValidate + "?ticket=" + casTicket + "&" + "service=" + service;
WebClient client = new WebClient();
StreamReader Reader = new StreamReader(client.OpenRead(validateurl));
// Put the validation response in a string
string resp = Reader.ReadToEnd();
// Some boilerplate to set up the parse of validation response.
NameTable nt = new NameTable();
XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);
XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None);
XmlTextReader reader = new XmlTextReader(resp, XmlNodeType.Element, context);
string netid = null;
// A very dumb use of XML by looping in all tags.
// Just scan for the "user". If it isn't there, its an error.
while (reader.Read())
{
if (reader.IsStartElement())
{
string tag = reader.LocalName;
if (tag == "user")
{
netid = reader.ReadString();
break;
}
}
}
reader.Close();
// If there was a problem, leave the message on the screen. Otherwise, return to original page.
if (netid == null)
{
application.Response.Write("Votre identité n'a pas été validé par le serveur CAS");
application.Response.Write(resp);
}
else
{
application.Response.Write("Bienvenue " + netid);
// create the authentication ticket and store the roles in the user data
FormsAuthenticationTicket formAuthTicket = new
FormsAuthenticationTicket(
1, // version
netid, // user name
DateTime.Now, // creation
DateTime.Now.AddMinutes(20), // expiration
false, // persistant
""); // userData
// encrypt the ticket
string encryptedTicket = FormsAuthentication.Encrypt(formAuthTicket);
// create a cookie and use the encrypted ticket as data
authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
// add the cookie to the response cookie collection
application.Response.Cookies.Add(authCookie);
// go the initial request URL
string returnUrl;
// if the return url cookie is lost, return to the default page
if (application.Request.Cookies[ReturnUrl] == null)
returnUrl = application.Request.ApplicationPath;
else
returnUrl = application.Request.Cookies[ReturnUrl].Value;
application.Response.Redirect(returnUrl);
}
}
}
}