[Zope-dev] SAP SSO for Zope/CookieCrumbler/LDAPUserFolder

2005-06-27 Thread Dirk Datzert
Hi, 
 
this is my solution for SSO for Zope by accepting SAP-SSO-Ticket. 
 
SAP-SSO-Tickets are Cookies named MYSAPSSO2. They contain 
SAP-PortalUserName, SAP-Username, Validate-Time of the ticket and a signed 
signature by the issueing SAP-System. 
 
Since we currently use CookieCrumbler and LDAPUserFolder it was my goal to  
let the CookieCrumbler take the MYSAPSSO2 Cookie from the Request, let it 
be validated by an external ticket verification service, store the 
validated TicketInfo in the SESSION variable and let LDAPUserFolder load 
the trusted PortalUser with roles from the LDAP-Directory. 
 
Any comments or security discussion is welcome. 
 
Zope 2.7.6, CookieCrumbler 1.2, LDAPUserFolder 2.5 
 
Regards, 
Dirk 

-- 
Geschenkt: 3 Monate GMX ProMail gratis + 3 Ausgaben stern gratis
++ Jetzt anmelden  testen ++ http://www.gmx.net/de/go/promail ++diff -uNr CookieCrumbler/CookieCrumbler.py CookieCrumbler-dirk/CookieCrumbler.py
--- CookieCrumbler/CookieCrumbler.py	Mon Jun 14 18:34:36 2004
+++ CookieCrumbler-dirk/CookieCrumbler.py	Mon Jun 27 22:53:17 2005
@@ -18,6 +18,7 @@
 from base64 import encodestring, decodestring
 from urllib import quote, unquote
 import sys
+import md5
 
 from Acquisition import aq_inner, aq_parent
 from DateTime import DateTime
@@ -29,6 +30,8 @@
 from ZPublisher.HTTPRequest import HTTPRequest
 from OFS.Folder import Folder
 
+from urllib2 import urlopen, Request
+
 try:
 from zExceptions import Redirect
 except ImportError:
@@ -40,6 +43,7 @@
 ATTEMPT_NONE = 0   # No attempt at authentication
 ATTEMPT_LOGIN = 1  # Attempt to log in
 ATTEMPT_RESUME = 2 # Attempt to resume session
+ATTEMPT_TICKET = 3 # Attempt to authenticate via sso-ticket
 
 ModifyCookieCrumblers = 'Modify Cookie Crumblers'
 ViewManagementScreens = Permissions.view_management_screens
@@ -83,6 +87,10 @@
 'label':'Use cookie paths to limit scope'},
{'id':'cache_header_value', 'type': 'string', 'mode':'w',
 'label':'Cache-Control header value'},
+   {'id':'mysap_cookie', 'type': 'string', 'mode':'w',
+'label':'Authentication ticket cookie name'},
+   {'id':'ticket_verifier_url', 'type': 'string', 'mode':'w',
+'label':'Ticket Verifier URL'},
)
 
 auth_cookie = '__ac'
@@ -94,6 +102,8 @@
 logout_page = 'logged_out'
 local_cookie_path = 0
 cache_header_value = 'no-cache'
+mysap_cookie = 'MYSAPSSO2'
+ticket_verifier_url = 'http://localhost:4080/verify'
 
 security.declarePrivate('delRequestVar')
 def delRequestVar(self, req, name):
@@ -137,6 +147,24 @@
 def defaultExpireAuthCookie(self, resp, cookie_name):
 resp.expireCookie(cookie_name, path=self.getCookiePath())
 
+
+security.declarePrivate('verifyTicket')
+def verifyTicket( self, ticket ):
+ Verify Ticket with external verification service 
+
+req = Request( self.ticket_verifier_url, data=ticket )
+req.add_header( 'Cookie', '%s=%s;' % (self.mysap_cookie, ticket) )
+
+try:
+resp = urlopen(req)
+result = resp.read()
+print result
+return TicketInfo(result)
+except Exception, ex:
+print ex
+return None
+
+
 security.declarePrivate('modifyRequest')
 def modifyRequest(self, req, resp):
 Copies cookie-supplied credentials to the basic auth fields.
@@ -162,11 +190,41 @@
 # created it.  The user must be using basic auth.
 raise CookieCrumblerDisabled
 
-if req.has_key(self.pw_cookie) and req.has_key(self.name_cookie):
+	ticket_info = None
+
+	if req.has_key(self.mysap_cookie) and self.ticket_verifier_url:
+		cookie_val = req.get(self.mysap_cookie)
+		m = md5.new()
+		m.update(cookie_val)
+		cookie_hash = m.digest()
+
+		#print cookie_val
+
+		if req.SESSION.has_key(cookie_hash):
+		#print get ticket_info %s % cookie_hash
+		ticket_info = req.SESSION.get(cookie_hash)
+		else:
+		ticket_info = self.verifyTicket(cookie_val)
+
+		if ticket_info:
+			#print set ticket_info %s % cookie_hash
+		 	req.SESSION.set(cookie_hash, ticket_info)
+
+	if ticket_info:
+		name = ticket_info.getPortalUser()
+ac = encodestring('%s:__ssoticket__=%s' % (name,cookie_hash)).rstrip()
+req._auth = 'Basic %s' % ac
+resp._auth = 1
+#print req._auth
+#print name
+		attempt = ATTEMPT_TICKET
+
+elif req.has_key(self.pw_cookie) and req.has_key(self.name_cookie):
 # Attempt to log in and set cookies.
 attempt = ATTEMPT_LOGIN
 name = req[self.name_cookie]
 pw = req[self.pw_cookie]
+		if pw[:13] == '__ssoticket__': pw = None
 ac = encodestring('%s:%s' % (name, pw)).rstrip()
 

Re: [Zope-dev] SAP SSO for Zope/CookieCrumbler/LDAPUserFolder

2005-06-27 Thread Jens Vagelpohl


On 27 Jun 2005, at 22:27, Dirk Datzert wrote:


Hi,

this is my solution for SSO for Zope by accepting SAP-SSO-Ticket.


Apart from the fact that directly patching an existing product is  
never a good idea (subclass and override as needed is a much better  
solution) the creation of external HTTP requests within the product  
code is dangerous. Every time the request hangs (unforeseen network  
hiccup, server unavailable, etc, simple everyday stuff that is beyond  
anyone's control) you will have a hung thread. Four of them and you  
have a hung Zope.


jens

___
Zope-Dev maillist  -  Zope-Dev@zope.org
http://mail.zope.org/mailman/listinfo/zope-dev
**  No cross posts or HTML encoding!  **
(Related lists - 
http://mail.zope.org/mailman/listinfo/zope-announce

http://mail.zope.org/mailman/listinfo/zope )