Imports System.Web Imports System.Configuration Public Class CASauthenticate Inherits System.Web.UI.Page Public Function SimpleAuth() As String '------------------------------------------------------------ ' This code is adapted from: http://opensource.case.edu/projects/CAS/wiki/CASP ' FSUID project home page: http://fsuid.fsu.edu/admin ' CAS information: http://www.ja-sig.org/wiki/display/CAS/Home ' Spec: http://www.yale.edu/tp/cas/specification/CAS%202.0%20Protocol%20Specification%20v1.0.html ' ' Usage: it is expected that this function will be called first thing ' in the Page_Load function. This function will check the Session variable ' "WebAuthCAS_UserID" to see if there is a value, if so, that is assumed to be ' the authenticated userid. Next, we check to see if there is a ticket variable ' in the query string. If so, we will open a socket connection to a validate ' URL and will pass the ticket and will be returned a simple string of the ' form yesuserid. However, if we don't have a ticket, we will ' redirect to a login URL. The CAS protocol is such that it will redirect back ' to the calling page with a ticket variable in the querystring. Note that the ' CAS server will drop a cookie along the way so that if we happen to redirect ' to the login page and we are already logged in, it will not ask us to login again and ' will return a ticket. ' ' Here we assume the CAS server with the login and validate URLs is "https://bb5.fsu.edu/cas/" ' However, this can be overridden by specifying a value for "CASserver" in the ' appSettings section of web.config '------------------------------------------------------------ If Not Context.Session("WebAuthCAS_UserID") Is Nothing Then _ Return Context.Session("WebAuthCAS_UserID") Dim CASserver As String = ConfigurationManager.AppSettings("CASserver") If CASserver Is Nothing Then CASserver = "https://bb5.fsu.edu/cas/" Dim myService As String = HttpUtility.UrlEncode(Context.Request.Url.AbsoluteUri.Split("?")(0)) If (Not Context.Request.QueryString("ticket") Is Nothing) Then Try Dim myValidateURL As String = CASserver & "validate?ticket=" & Context.Request.QueryString("ticket") & "&service=" & myService Dim wc As New System.Net.WebClient Dim st As System.IO.Stream = wc.OpenRead(myValidateURL) Dim rdr As New System.IO.StreamReader(st) Dim ans As String = rdr.ReadToEnd rdr.Close() wc.Dispose() Dim s As String() = ans.Split(vbLf) '---------------------------------------------------- ' WARNING: the specification calls for a response of the ' form yesuserid or no ' but tests showed that we are getting yesuserid ' so we will just take out the extra CR. We don't really ' expect a no. But if we get it, we drop through to login. '---------------------------------------------------- If s(0) = "yes" Then Context.Session("WebAuthCAS_UserID") = s(1).Replace(vbCr, "") Return Context.Session("WebAuthCAS_UserID") End If Catch myErr As Exception '------------------------------------------------------ ' If an exeption occurs, then we will just fall through ' and go back to the Login URL. Its possible this could lead to a ' looping application. But we will ignore it for now. '------------------------------------------------------ End Try End If Dim myLoginURL As String = CASserver & "login?service=" & myService Context.Response.Redirect(myLoginURL, True) Return Nothing End Function Public Function DetailAuth() As CASresult '------------------------------------------------------------ ' This code uses serviceValidate as part of the CAS specification. ' Spec: http://www.yale.edu/tp/cas/specification/CAS%202.0%20Protocol%20Specification%20v1.0.html ' ' Usage: it is expected that this function will be called first thing ' in the Page_Load function. This function will check the Session variable ' "WebAuthCAS_UserID" to see if there is a value, if so, that is assumed to be ' the authenticated userid. Next, we check to see if there is a ticket variable ' in the query string. If so, we will open a socket connection to a serviceValidate ' URL and will pass the ticket and will be returned a string containing an XML ' document. The specification gives the following example on success: ' ' ' username ' PGTIOU-84678-8a9d… ' ' ' and the following example on failure: ' ' ' Ticket ST-1856339-aA5Yuvrxzpv8Tau1cYQ7 not recognized ' ' ' However, the FSU implementation, returns the following info for a successful login: ' ' ' dyancey ' LDAP1 ' dyancey ' Active ' 00036...blah...blah... ' Dr David Price Yancey ' dyancey ' ' ' If we don't have a ticket, we will ' redirect to a login URL. The CAS protocol is such that it will redirect back ' to the calling page with a ticket variable in the querystring. Note that the ' CAS server will drop a cookie along the way so that if we happen to redirect ' to the login page and we are already logged in, it will not ask us to login again and ' will return a ticket. ' ' Here we assume the CAS server with the login and validate URLs is "https://bb5.fsu.edu/cas/" ' However, this can be overridden by specifying a value for "CASserver" in the ' appSettings section of web.config '------------------------------------------------------------ If Not Context.Session("WebAuthCAS_CASresult") Is Nothing Then _ Return Context.Session("WebAuthCAS_CASresult") Dim CASserver As String = ConfigurationManager.AppSettings("CASserver") If CASserver Is Nothing Then CASserver = "https://bb5.fsu.edu/cas/" Dim myService As String = HttpUtility.UrlEncode(Context.Request.Url.AbsoluteUri.Split("?")(0)) If (Not Context.Request.QueryString("ticket") Is Nothing) Then Dim CR As New CASresult Try Dim myValidateURL As String = CASserver & "serviceValidate?ticket=" & _ Context.Request.QueryString("ticket") & "&service=" & myService Dim wc As New System.Net.WebClient Dim st As System.IO.Stream = wc.OpenRead(myValidateURL) Dim rdr As New System.IO.StreamReader(st) Dim ans As String = rdr.ReadToEnd rdr.Close() wc.Dispose() '-------------------------------------------------- ' Parse the XML response '-------------------------------------------------- Dim d As New XMLcustom d.LoadXml(ans) CR.FailureMessage = d.GetValue("cas:authenticationFailure") CR.user = d.GetValue("cas:user") CR.fsuAuthServer = d.GetValue("cas:fsuAuthServer") CR.fsuEduCarsUserName = d.GetValue("cas:fsuEduCarsUserName") CR.employeeStatus = d.GetValue("cas:employeeStatus") CR.fsuEduUserkey = d.GetValue("cas:fsuEduUserkey") CR.displayName = d.GetValue("cas:displayName") CR.cn = d.GetValue("cas:cn") If d.HasNode("cas:authenticationSuccess") Then CR.AuthenticationSuccess = True ElseIf d.HasNode("cas:authenticationFailure") Then CR.AuthenticationSuccess = False Else CR.AuthenticationSuccess = False CR.FailureMessage = "Unrecognized XML document" End If Context.Session("WebAuthCAS_CASresult") = CR Return CR Catch myErr As Exception CR.AuthenticationSuccess = False CR.FailureMessage = myErr.Message Return CR End Try End If Dim myLoginURL As String = CASserver & "login?service=" & myService Context.Response.Redirect(myLoginURL, True) Return Nothing End Function End Class Public Class CASresult Public AuthenticationSuccess As Boolean Public FailureMessage As String Public user As String Public fsuAuthServer As String Public fsuEduCarsUserName As String Public employeeStatus As String Public fsuEduUserkey As String Public displayName Public cn As String End Class Public Class XMLcustom Inherits System.Xml.XmlDocument Public Function GetValue(ByVal NodeName As String) As String Dim l As System.Xml.XmlNodeList = Me.GetElementsByTagName(NodeName) If l.Count < 1 Then Return "" Return l.Item(0).InnerText End Function Public Function HasNode(ByVal NodeName As String) As Boolean Dim l As System.Xml.XmlNodeList = Me.GetElementsByTagName(NodeName) If l.Count = 0 Then Return False Else Return True End If End Function End Class