source: TI12-security/trunk/python/ndg.security.server/ndg/security/server/sso/sso/lib/openid_util.py @ 4584

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.server/ndg/security/server/sso/sso/lib/openid_util.py@4584
Revision 4584, 5.8 KB checked in by pjkersha, 12 years ago (diff)

Started integration work for common WSGI/SOAP client based interfaces (ndg.security.server.wsgi.utils.sessionmanagerclient and ndg.security.server.wsgi.utils.attributeauthorityclient) with Pylons Single Sign On package (ndg.security.server.sso)

Line 
1import pylons
2from pylons.templating import Buffet
3from pylons import config, request, session
4import ndg.security.server.sso.sso.lib.helpers as h
5from ndg.security.server.sso.sso.lib.app_globals import Globals
6
7import logging
8log = logging.getLogger(__name__)
9
10log.debug("Defining MyBuffet for OpenID template ...")
11
12class MyBuffet(Buffet):
13    def _update_names(self, ns):
14        return ns
15
16def_eng = config['buffet.template_engines'][0]
17log.info("def_eng = %s" % def_eng)
18buffet = MyBuffet(
19    def_eng['engine'],
20    template_root=def_eng['template_root'],
21    **def_eng['template_options']
22)
23
24for e in config['buffet.template_engines'][1:]:
25    buffet.prepare(
26        e['engine'],
27        template_root=e['template_root'],
28        alias=e['alias'],
29        **e['template_options']
30    )
31
32class State:
33    pass
34
35
36# State variable for WAYF kid file set-up
37c = State()
38c.openid = 'None'
39c.title = "Where are You From?"
40c.xml = ''
41c.doc = 'logged in'
42c.providers = {}
43
44import base64
45
46def make_template():
47    '''Make kid template for OpenID login - the NDG WAYF piggy backs this.
48   
49    It's triggered by a HTTP 401 authorisation error and called explicitly
50    via the WAYF controller'''
51   
52    g = config['pylons.g']
53   
54    # Check for return from OpenID login
55    try:
56        userSet = 'REMOTE_USER' in request.environ
57    except TypeError, e:
58        # Request object may not be registered - crude fix here wrapping it a
59        # catch
60        # TODO: referencing environ outside a controller
61        log.info("Keying 'REMOTE_USER' in request.environ: %s" % e)
62        userSet = False
63       
64    if userSet:
65        if not g.ndg.security.common.sso.state.returnToURL:
66            log.error("No returnToURL set for redirect following OpenID " + \
67                      "login")
68        else:
69            log.info("Redirecting to [%s] following OpenID login ..." % \
70                     g.ndg.security.common.sso.state.returnToURL)
71            h.redirect_to(g.ndg.security.common.sso.state.returnToURL)
72
73    state = g.ndg.security.common.sso.state
74    cfg =  g.ndg.security.common.sso.cfg
75   
76    # Set encoded return to address - ensure login can return to an address
77    # over https to preserve confidentiality of credentials
78    # TODO: revisit - at the moment a redirect back from https -> http at the
79    # client to the IdP is rejected
80#    if state.returnToURL and cfg.server in state.returnToURL:
81#        state.returnToURL = state.returnToURL.replace(cfg.server,
82#                                                      cfg.sslServer)
83#        log.debug("make_template: switched return to address to https = %s" % \
84#                                                            state.returnToURL)
85
86    state.b64encReturnToURL = base64.urlsafe_b64encode(str(state.returnToURL))       
87   
88    # Retrieve IdP details
89    _getTrustedIdPs(g)
90   
91    return _render("ndg.security.wayf", h=h, g=g, c=c)
92
93
94def _render(templateName, **kw):
95    '''TODO: Wrapper to enable substitution of $message and $css_class used by
96    AuthKit open_id module'''
97    rendering = buffet.render('ndg.security.kid', 
98                              template_name=templateName,
99                              namespace=kw)
100    # Add $message and $css_class here somehow
101    return rendering
102
103
104from ndg.security.server.wsgi.utils.attributeauthorityclient import \
105    WSGIAttributeAuthorityClient
106
107def _getTrustedIdPs(g):
108    '''Retrieve list of trusted login sites for user to select - calls
109    Attribute Authority WS'''
110
111    # Get references to globals
112    state = g.ndg.security.common.sso.state
113    cfg =  g.ndg.security.server.sso.cfg
114                               
115    # Check for cached copy and return if set to avoid recalling
116    # Attribute Authority - This has the consequence that if the list
117    # of trusted hosts in the Map Configuration changes, the Attribute
118    # Authority and THIS service must be restarted.
119    if len(g.ndg.security.server.sso.state.trustedIdPs) > 0:
120        return _render('ndg.security.wayf', h=h, g=g, c=c)
121   
122    log.debug("Initialising connection to Attribute Authority [%s]" % \
123              cfg.aaURI)
124   
125    try:
126        aaClnt = WSGIAttributeAuthorityClient(uri=cfg.aaURI,
127                                        tracefile=cfg.tracefile,
128                                        httpProxyHost=cfg.httpProxyHost,
129                                        noHttpProxyList=cfg.noHttpProxyList,
130                                        **cfg.wss)
131    except Exception, e:
132        c.xml='Error establishing security context.  Please report ' + \
133              'the error to your site administrator'
134        log.error("Initialising AttributeAuthorityClient for " + \
135                  "getAllHostsInfo call: %s" % e)
136        return _render('ndg.security.error', h=h, g=config['pylons.g'], c=c)
137       
138    # Get list of login uris for trusted sites including THIS one
139    log.debug("Calling Attribute Authority getAllHostsInfo for wayf ...")
140
141    try:
142        hosts = aaClnt.getAllHostsInfo() 
143    except Exception, e:
144        c.xml='Error getting a list of trusted sites for login.  ' + \
145            'Please report the error to your site administrator.'
146        log.error("AttributeAuthorityClient getAllHostsInfo call: %s" % e) 
147        return _render('ndg.security.error', h=h, g=config['pylons.g'], c=c)
148       
149    g.ndg.security.server.sso.state.trustedIdPs = \
150                        dict([(k, v['loginURI']) for k, v in hosts.items()])
151
152
153from ndg.security.common.pylons.security_util import setSecuritySession
154from urlparse import urlsplit
155
156def url2user(environ, url):
157    '''Function picked up by authkit.openid.urltouser config setting.  It
158    sets a username from the users OpenID URL following login'''
159    log.info("OpenID sign in with [%s]" % url)
160   
161    # Remove protocol prefix and strip /'s
162    username = ''.join(urlsplit(url)[1:]).strip('/').replace('/', '-')
163    return username
Note: See TracBrowser for help on using the repository browser.