1
|
import os
|
2
|
import urlparse
|
3
|
|
4
|
import lasso
|
5
|
|
6
|
from quixote import get_request, get_response, redirect, get_field, get_publisher
|
7
|
from quixote.http_request import parse_header
|
8
|
from quixote.directory import Directory
|
9
|
from quixote import get_user, get_session, get_session_manager
|
10
|
|
11
|
from users import User
|
12
|
import misc
|
13
|
import template
|
14
|
|
15
|
from liberty import SOAPException, soap_call
|
16
|
|
17
|
|
18
|
class RootDirectory(Directory):
|
19
|
_q_exports = ['login', 'singleSignOnArtifact',
|
20
|
('metadata.xml', 'metadata'), 'public_key']
|
21
|
|
22
|
def _q_index(self):
|
23
|
raise errors.AccessError()
|
24
|
|
25
|
def login(self):
|
26
|
return self.perform_login()
|
27
|
|
28
|
def perform_login(self, idp = None):
|
29
|
server = misc.get_lasso_server(protocol = 'saml2')
|
30
|
if not server:
|
31
|
return template.error_page(_('SAML 2.0 support not yet configured.'))
|
32
|
login = lasso.Login(server)
|
33
|
login.initAuthnRequest(idp, lasso.HTTP_METHOD_REDIRECT)
|
34
|
login.request.nameIDPolicy.format = lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT
|
35
|
login.request.nameIDPolicy.allowCreate = True
|
36
|
login.request.forceAuthn = False
|
37
|
login.request.isPassive = False
|
38
|
# login.request.consent = /* XXX */
|
39
|
login.buildAuthnRequestMsg()
|
40
|
return redirect(login.msgUrl)
|
41
|
|
42
|
|
43
|
def singleSignOnArtifact(self):
|
44
|
server = misc.get_lasso_server(protocol = 'saml2')
|
45
|
if not server:
|
46
|
return template.error_page(_('SAML 2.0 support not yet configured.'))
|
47
|
login = lasso.Login(server)
|
48
|
request = get_request()
|
49
|
login.initRequest(request.get_query(), lasso.HTTP_METHOD_ARTIFACT_GET)
|
50
|
login.buildRequestMsg()
|
51
|
try:
|
52
|
soap_answer = soap_call(login.msgUrl, login.msgBody)
|
53
|
except SOAPException:
|
54
|
return template.error_page(_("Failure to communicate with identity provider"))
|
55
|
|
56
|
login.processResponseMsg(soap_answer)
|
57
|
|
58
|
login.acceptSso()
|
59
|
session = get_session()
|
60
|
if login.isSessionDirty:
|
61
|
if login.session:
|
62
|
session.lasso_session_dump = login.session.dump()
|
63
|
else:
|
64
|
session.lasso_session_dump = None
|
65
|
user = self.lookup_user(session, login)
|
66
|
if user:
|
67
|
session.set_user(user.id)
|
68
|
else:
|
69
|
session.set_user('anonymous-%s' % login.nameIdentifier.content)
|
70
|
session.lasso_anonymous_identity_dump = login.identity.dump()
|
71
|
|
72
|
response = get_response()
|
73
|
if session.after_url:
|
74
|
after_url = session.after_url
|
75
|
session.after_url = None
|
76
|
return redirect(after_url)
|
77
|
response.set_status(303)
|
78
|
response.headers['location'] = urlparse.urljoin(request.get_url(), str('..'))
|
79
|
response.content_type = 'text/plain'
|
80
|
return "Your browser should redirect you"
|
81
|
|
82
|
def lookup_user(self, session, login):
|
83
|
ni = login.nameIdentifier.content
|
84
|
session.name_identifier = ni
|
85
|
nis = list(User.select(lambda x: ni in x.name_identifiers))
|
86
|
if nis:
|
87
|
user = nis[0]
|
88
|
else:
|
89
|
return None
|
90
|
|
91
|
user.lasso_dump = login.identity.dump()
|
92
|
user.store()
|
93
|
return user
|
94
|
|
95
|
|
96
|
def metadata(self):
|
97
|
response = get_response()
|
98
|
response.set_content_type('text/xml', 'utf-8')
|
99
|
metadata = unicode(open(misc.get_abs_path(
|
100
|
misc.cfg['sp']['saml2_metadata'])).read(), 'utf-8')
|
101
|
return metadata
|
102
|
|
103
|
def public_key(self):
|
104
|
response = get_response()
|
105
|
response.set_content_type('application/octet-stream')
|
106
|
publickey = file(misc.get_abs_path(misc.cfg['sp']['publickey'])).read()
|
107
|
return publickey
|
108
|
|
109
|
|
110
|
|