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()