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

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

Fixes to BADC SSO service templates:

  • re-instated error.kid for use by logout controller
  • added login/logout link switch to header
  • fixed header and footer alignments for IE correct display
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    '''Collection of variables to set in templates'''
34    def __init__(self):
35        self.openid = 'None'
36        self.title = "Login"
37        self.xml = ''
38        self.doc = 'logged in'
39        self.providers = {}
40        self.loggedIn = False
41
42
43# State variable for WAYF kid file set-up
44c = State()
45
46import base64
47
48def make_template():
49    '''Make kid template for OpenID login - the NDG WAYF piggy backs this.
50   
51    It's triggered by a HTTP 401 authorisation error and called explicitly
52    via the WAYF controller'''
53   
54    g = config['pylons.g']
55   
56    # Check for return from OpenID login
57    try:
58        userSet = 'REMOTE_USER' in request.environ
59    except TypeError, e:
60        # Request object may not be registered - crude fix here wrapping it a
61        # catch
62        # TODO: referencing environ outside a controller
63        log.info("Keying 'REMOTE_USER' in request.environ: %s" % e)
64        userSet = False
65       
66    if userSet:
67        if not g.ndg.security.common.sso.state.returnToURL:
68            log.error("No returnToURL set for redirect following OpenID "
69                      "login")
70        else:
71            log.info("Redirecting to [%s] following OpenID login ..." %
72                     g.ndg.security.common.sso.state.returnToURL)
73            h.redirect_to(g.ndg.security.common.sso.state.returnToURL)
74
75    state = g.ndg.security.common.sso.state
76    cfg =  g.ndg.security.common.sso.cfg
77   
78    # Set encoded return to address - ensure login can return to an address
79    # over https to preserve confidentiality of credentials
80    # TODO: revisit - at the moment a redirect back from https -> http at the
81    # client to the IdP is rejected
82#    if state.returnToURL and cfg.server in state.returnToURL:
83#        state.returnToURL = state.returnToURL.replace(cfg.server,
84#                                                      cfg.sslServer)
85#        log.debug("make_template: switched return to address to https = %s" %
86#                                                            state.returnToURL)
87
88    state.b64encReturnToURL = base64.urlsafe_b64encode(str(state.returnToURL))       
89   
90    # Retrieve IdP details
91    _getTrustedIdPs(g)
92   
93    return _render("ndg.security.wayf", h=h, g=g, c=c)
94
95
96def _render(templateName, **kw):
97    '''TODO: Wrapper to enable substitution of $message and $css_class used by
98    AuthKit open_id module'''
99    rendering = buffet.render('ndg.security.kid', 
100                              template_name=templateName,
101                              namespace=kw)
102    # Add $message and $css_class here somehow
103    return rendering
104
105
106from ndg.security.server.wsgi.utils.attributeauthorityclient import \
107    WSGIAttributeAuthorityClient
108
109def _getTrustedIdPs(g):
110    '''Retrieve list of trusted login sites for user to select - calls
111    Attribute Authority WS'''
112
113    # Get references to globals
114    state = g.ndg.security.common.sso.state
115    cfg =  g.ndg.security.server.sso.cfg
116                               
117    # Check for cached copy and return if set to avoid recalling
118    # Attribute Authority - This has the consequence that if the list
119    # of trusted hosts in the Map Configuration changes, the Attribute
120    # Authority and THIS service must be restarted.
121    if len(g.ndg.security.server.sso.state.trustedIdPs) > 0:
122        return
123   
124    log.debug("Initialising connection to Attribute Authority [%s]"%cfg.aaURI)
125   
126    try:
127        aaClnt = WSGIAttributeAuthorityClient(environ=pylons.request.environ,
128                                        uri=cfg.aaURI,
129                                        environKey=cfg.aaEnvironKey,
130                                        tracefile=cfg.tracefile,
131                                        httpProxyHost=cfg.httpProxyHost,
132                                        noHttpProxyList=cfg.noHttpProxyList,
133                                        **cfg.wss)
134    except Exception, e:
135        log.error("Initialising AttributeAuthorityClient for "
136                  "getAllHostsInfo call: %s" % e)
137        return
138
139    # Get list of login uris for trusted sites including THIS one
140    log.debug("Calling Attribute Authority getAllHostsInfo for wayf ...")
141
142    try:
143        hosts = aaClnt.getTrustedHostInfo() 
144    except Exception, e:
145        log.error("AttributeAuthorityClient getAllHostsInfo call: %s" % e) 
146        return
147       
148    # Pick out siteName for as it should be set to a more user friendly
149    # description of the site.  Site name may not be set so if unavailable,
150    # default to host name identifier.
151    g.ndg.security.server.sso.state.trustedIdPs = \
152                        dict([(v['siteName'] or k, v['loginURI']) 
153                                 for k, v in hosts.items()])
154
155
156from ndg.security.common.pylons.security_util import setSecuritySession
157from urlparse import urlsplit
158
159def url2user(environ, url):
160    '''Function picked up by authkit.openid.urltouser config setting.  It
161    sets a username from the users OpenID URL following login'''
162    log.info("OpenID sign in with [%s]" % url)
163   
164    # Remove protocol prefix and strip /'s
165    username = ''.join(urlsplit(url)[1:]).strip('/').replace('/', '-')
166    return username
Note: See TracBrowser for help on using the repository browser.