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

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@4587
Revision 4587, 5.9 KB checked in by pjkersha, 11 years ago (diff)
  • Completed 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)
  • Integrated Single Sign On service into Combined Services Paste service as a Pylons app. This also includes Session Manager, Attribute Authority, OpenID. SSO Service will eventually be removed replaced with OpenID based 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(
127                                        environ=pylons.request.environ,
128                                        uri=cfg.aaURI,
129                                        tracefile=cfg.tracefile,
130                                        httpProxyHost=cfg.httpProxyHost,
131                                        noHttpProxyList=cfg.noHttpProxyList,
132                                        **cfg.wss)
133    except Exception, e:
134        c.xml='Error establishing security context.  Please report ' + \
135              'the error to your site administrator'
136        log.error("Initialising AttributeAuthorityClient for " + \
137                  "getAllHostsInfo call: %s" % e)
138        return _render('ndg.security.error', h=h, g=config['pylons.g'], c=c)
139       
140    # Get list of login uris for trusted sites including THIS one
141    log.debug("Calling Attribute Authority getAllHostsInfo for wayf ...")
142
143    try:
144        hosts = aaClnt.getAllHostsInfo() 
145    except Exception, e:
146        c.xml='Error getting a list of trusted sites for login.  ' + \
147            'Please report the error to your site administrator.'
148        log.error("AttributeAuthorityClient getAllHostsInfo call: %s" % e) 
149        return _render('ndg.security.error', h=h, g=config['pylons.g'], c=c)
150       
151    g.ndg.security.server.sso.state.trustedIdPs = \
152                        dict([(k, v['loginURI']) for k, v in hosts.items()])
153
154
155from ndg.security.common.pylons.security_util import setSecuritySession
156from urlparse import urlsplit
157
158def url2user(environ, url):
159    '''Function picked up by authkit.openid.urltouser config setting.  It
160    sets a username from the users OpenID URL following login'''
161    log.info("OpenID sign in with [%s]" % url)
162   
163    # Remove protocol prefix and strip /'s
164    username = ''.join(urlsplit(url)[1:]).strip('/').replace('/', '-')
165    return username
Note: See TracBrowser for help on using the repository browser.