@@ -156,45 +156,47 @@ def __init__(self):
156156 self .user = {}
157157 self .result = {}
158158
159- def kaka2user (self , kaka ):
160- logger .debug ("KAKA: %s" % kaka )
161- if kaka :
162- cookie_obj = SimpleCookie (kaka )
159+ def get_user (self , environ ):
160+ cookie = environ .get ("HTTP_COOKIE" , '' )
161+
162+ logger .debug ("Cookie: %s" % cookie )
163+ if cookie :
164+ cookie_obj = SimpleCookie (cookie )
163165 morsel = cookie_obj .get (self .cookie_name , None )
164166 if morsel :
165167 try :
166168 return self .uid2user [morsel .value ]
167169 except KeyError :
168170 return None
169171 else :
170- logger .debug ("No spauthn cookie" )
172+ logger .debug ("No %s cookie" , self .cookie_name )
173+
171174 return None
172175
173- def delete_cookie (self , environ = None , kaka = None ):
174- if not kaka :
175- kaka = environ .get ("HTTP_COOKIE" , '' )
176- logger .debug ("delete KAKA: %s" % kaka )
177- if kaka :
176+ def delete_cookie (self , environ ):
177+ cookie = environ .get ("HTTP_COOKIE" , '' )
178+ logger .debug ("delete cookie: %s" % cookie )
179+ if cookie :
178180 _name = self .cookie_name
179- cookie_obj = SimpleCookie (kaka )
181+ cookie_obj = SimpleCookie (cookie )
180182 morsel = cookie_obj .get (_name , None )
181183 cookie = SimpleCookie ()
182184 cookie [_name ] = ""
183185 cookie [_name ]['path' ] = "/"
184186 logger .debug ("Expire: %s" % morsel )
185- cookie [_name ]["expires" ] = _expiration ("dawn " )
186- return tuple ( cookie .output ().split (": " , 1 ) )
187+ cookie [_name ]["expires" ] = _expiration ("now " )
188+ return cookie .output ().split (": " , 1 )
187189 return None
188190
189- def user2kaka (self , user ):
191+ def set_cookie (self , user ):
190192 uid = rndstr (32 )
191193 self .uid2user [uid ] = user
192194 cookie = SimpleCookie ()
193195 cookie [self .cookie_name ] = uid
194196 cookie [self .cookie_name ]['path' ] = "/"
195197 cookie [self .cookie_name ]["expires" ] = _expiration (480 )
196198 logger .debug ("Cookie expires: %s" % cookie [self .cookie_name ]["expires" ])
197- return tuple ( cookie .output ().split (": " , 1 ) )
199+ return cookie .output ().split (": " , 1 )
198200
199201
200202# -----------------------------------------------------------------------------
@@ -318,6 +320,12 @@ def not_authn(self):
318320# -----------------------------------------------------------------------------
319321
320322
323+ class User (object ):
324+ def __init__ (self , name_id , data ):
325+ self .name_id = name_id
326+ self .data = data
327+
328+
321329class ACS (Service ):
322330 def __init__ (self , sp , environ , start_response , cache = None , ** kwargs ):
323331 Service .__init__ (self , environ , start_response )
@@ -357,7 +365,14 @@ def do(self, response, binding, relay_state="", mtype="response"):
357365 return resp (self .environ , self .start_response )
358366
359367 logger .info ("AVA: %s" % self .response .ava )
360- resp = Response (dict_to_table (self .response .ava ))
368+
369+ user = User (self .response .name_id , self .response .ava )
370+ cookie = self .cache .set_cookie (user )
371+
372+ resp = Redirect ("/" , headers = [
373+ ("Location" , "/" ),
374+ cookie ,
375+ ])
361376 return resp (self .environ , self .start_response )
362377
363378 def verify_attributes (self , ava ):
@@ -543,7 +558,6 @@ def redirect_to_auth(self, _cli, entity_id, came_from):
543558 ht_args = _cli .apply_binding (_binding , "%s" % req , destination ,
544559 relay_state = _rstate )
545560 _sid = req_id
546- logger .debug ("ht_args: %s" % ht_args )
547561 except Exception , exc :
548562 logger .exception (exc )
549563 resp = ServiceError (
@@ -582,6 +596,19 @@ def do(self):
582596# ----------------------------------------------------------------------------
583597
584598
599+ class SLO (Service ):
600+ def __init__ (self , sp , environ , start_response , cache = None ):
601+ Service .__init__ (self , environ , start_response )
602+ self .sp = sp
603+ self .cache = cache
604+
605+ def do (self , response , binding , relay_state = "" , mtype = "response" ):
606+ req_info = self .sp .parse_logout_request_response (response , binding )
607+ return finish_logout (self .environ , self .start_response )
608+
609+ # ----------------------------------------------------------------------------
610+
611+
585612#noinspection PyUnusedLocal
586613def not_found (environ , start_response ):
587614 """Called if no URL matches."""
@@ -593,9 +620,18 @@ def not_found(environ, start_response):
593620
594621
595622#noinspection PyUnusedLocal
596- def main (environ , start_response , _sp ):
597- _sso = SSO (_sp , environ , start_response , cache = CACHE , ** ARGS )
598- return _sso .do ()
623+ def main (environ , start_response , sp ):
624+ user = CACHE .get_user (environ )
625+
626+ if user is None :
627+ sso = SSO (sp , environ , start_response , cache = CACHE , ** ARGS )
628+ return sso .do ()
629+
630+ body = dict_to_table (user .data )
631+ body += '<br><a href="/logout">logout</a>'
632+
633+ resp = Response (body )
634+ return resp (environ , start_response )
599635
600636
601637def disco (environ , start_response , _sp ):
@@ -613,12 +649,67 @@ def disco(environ, start_response, _sp):
613649
614650# ----------------------------------------------------------------------------
615651
652+
653+ #noinspection PyUnusedLocal
654+ def logout (environ , start_response , sp ):
655+ user = CACHE .get_user (environ )
656+
657+ if user is None :
658+ sso = SSO (sp , environ , start_response , cache = CACHE , ** ARGS )
659+ return sso .do ()
660+
661+ logger .info ("[logout] subject_id: '%s'" % (user .name_id ,))
662+
663+ # What if more than one
664+ data = sp .global_logout (user .name_id )
665+ logger .info ("[logout] global_logout > %s" % data )
666+
667+ for entity_id , logout_info in data .items ():
668+ if isinstance (logout_info , tuple ):
669+ binding , http_info = logout_info
670+
671+ if binding == BINDING_HTTP_POST :
672+ body = '' .join (http_info ['data' ])
673+ resp = Response (body )
674+ return resp (environ , start_response )
675+ elif binding == BINDING_HTTP_REDIRECT :
676+ for key , value in http_info ['headers' ]:
677+ if key .lower () == 'location' :
678+ resp = Redirect (value )
679+ return resp (environ , start_response )
680+
681+ resp = ServiceError ('missing Location header' )
682+ return resp (environ , start_response )
683+ else :
684+ resp = ServiceError ('unknown logout binding: %s' , binding )
685+ return resp (environ , start_response )
686+ else : # result from logout, should be OK
687+ pass
688+
689+ return finish_logout (environ , start_response )
690+
691+
692+ def finish_logout (environ , start_response ):
693+ logger .info ("[logout done] environ: %s" % environ )
694+ logger .info ("[logout done] remaining subjects: %s" % CACHE .uid2user .values ())
695+
696+ # remove cookie and stored info
697+ cookie = CACHE .delete_cookie (environ )
698+
699+ resp = Response ('You are now logged out of this service' , headers = [
700+ cookie ,
701+ ])
702+ return resp (environ , start_response )
703+
704+ # ----------------------------------------------------------------------------
705+
616706# map urls to functions
617707urls = [
618708 # Hmm, place holder, NOT used
619709 ('place' , ("holder" , None )),
620710 (r'^$' , main ),
621- (r'^disco' , disco )
711+ (r'^disco' , disco ),
712+ (r'^logout$' , logout ),
622713]
623714
624715
@@ -630,6 +721,13 @@ def add_urls():
630721 urls .append (("%s/redirect$" % base , (ACS , "redirect" , SP )))
631722 urls .append (("%s/redirect/(.*)$" % base , (ACS , "redirect" , SP )))
632723
724+ base = "slo"
725+
726+ urls .append (("%s/post$" % base , (SLO , "post" , SP )))
727+ urls .append (("%s/post/(.*)$" % base , (SLO , "post" , SP )))
728+ urls .append (("%s/redirect$" % base , (SLO , "redirect" , SP )))
729+ urls .append (("%s/redirect/(.*)$" % base , (SLO , "redirect" , SP )))
730+
633731# ----------------------------------------------------------------------------
634732
635733
0 commit comments