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

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@4377
Revision 4377, 5.8 KB checked in by pjkersha, 11 years ago (diff)

Renamed Attribute Authority classes and reran unittests

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.common.attributeauthority import AttributeAuthorityClient
105
106def _getTrustedIdPs(g):
107    '''Retrieve list of trusted login sites for user to select - calls
108    Attribute Authority WS'''
109
110    # Get references to globals
111    state = g.ndg.security.common.sso.state
112    cfg =  g.ndg.security.server.sso.cfg
113                               
114    # Check for cached copy and return if set to avoid recalling
115    # Attribute Authority - This has the consequence that if the list
116    # of trusted hosts in the Map Configuration changes, the Attribute
117    # Authority and THIS service must be restarted.
118    if len(g.ndg.security.server.sso.state.trustedIdPs) > 0:
119        return _render('ndg.security.wayf', h=h, g=g, c=c)
120   
121    log.debug("Initialising connection to Attribute Authority [%s]" % \
122              cfg.aaURI)
123   
124    try:
125        aaClnt = AttributeAuthorityClient(uri=cfg.aaURI,
126                                tracefile=cfg.tracefile,
127                                httpProxyHost=cfg.httpProxyHost,
128                                noHttpProxyList=cfg.noHttpProxyList,
129                                **cfg.wss)
130    except Exception, e:
131        c.xml='Error establishing security context.  Please report ' + \
132              'the error to your site administrator'
133        log.error("Initialising AttributeAuthorityClient for " + \
134                  "getAllHostsInfo call: %s" % e)
135        return _render('ndg.security.error', h=h, g=config['pylons.g'], c=c)
136       
137    # Get list of login uris for trusted sites including THIS one
138    log.debug("Calling Attribute Authority getAllHostsInfo for wayf ...")
139
140    try:
141        hosts = aaClnt.getAllHostsInfo() 
142    except Exception, e:
143        c.xml='Error getting a list of trusted sites for login.  ' + \
144            'Please report the error to your site administrator.'
145        log.error("AttributeAuthorityClient getAllHostsInfo call: %s" % e) 
146        return _render('ndg.security.error', h=h, g=config['pylons.g'], c=c)
147       
148    g.ndg.security.server.sso.state.trustedIdPs = \
149                        dict([(k, v['loginURI']) for k, v in hosts.items()])
150
151
152from ndg.security.common.pylons.security_util import setSecuritySession
153from urlparse import urlsplit
154
155def url2user(environ, url):
156    '''Function picked up by authkit.openid.urltouser config setting.  It
157    sets a username from the users OpenID URL following login'''
158    log.info("OpenID sign in with [%s]" % url)
159   
160    # Remove protocol prefix and strip /'s
161    username = ''.join(urlsplit(url)[1:]).strip('/').replace('/', '-')
162    return username
Note: See TracBrowser for help on using the repository browser.