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

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@3994
Revision 3994, 5.7 KB checked in by pjkersha, 12 years ago (diff)
  • Added AuthKit? as a dependency to ndg.security.server egg
  • Fixed imports for standalone SSO Service
  • Changed ProxyHttpConnection? for ZSI clients to check for no_proxy env var setting.
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.AttAuthority import AttAuthorityClient
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 = AttAuthorityClient(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 AttAuthorityClient 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("AttAuthorityClient 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.