SAMLv2 conformance fixes (encryption settings, ECP, affiliations, etc.)
git-svn-id: svn://localhost/lasso-conform/trunk@33 2a3a78c3-912c-0410-af21-e1fb2d1df599
This commit is contained in:
parent
d5899ed8a6
commit
e7135c0be4
98
lcs/root.ptl
98
lcs/root.ptl
|
@ -94,7 +94,7 @@ class LoginDirectory(Directory):
|
|||
|
||||
class RootDirectory(Directory):
|
||||
_q_exports = ['', 'admin', 'backoffice', 'login', 'logout', 'liberty', 'saml',
|
||||
'ident', 'register', 'info']
|
||||
'ident', 'register', 'info', 'encryption', 'replay_artifact']
|
||||
|
||||
def _q_index [html] (self):
|
||||
template.html_top('Lasso Conformance SP')
|
||||
|
@ -109,7 +109,8 @@ class RootDirectory(Directory):
|
|||
http_accept = request.environ.get('HTTP_ACCEPT')
|
||||
http_poas = request.environ.get('HTTP_PAOS')
|
||||
|
||||
if http_accept != 'application/vnd.paos+xml' and http_poas != 'urn:liberty:paos:2003-08':
|
||||
if 'application/vnd.paos+xml' not in http_accept or \
|
||||
'urn:liberty:paos:2003-08' not in http_poas:
|
||||
return template.error_page(_('Invalid PAOS Request'))
|
||||
|
||||
server = misc.get_lasso_server(protocol = 'saml2')
|
||||
|
@ -121,13 +122,20 @@ class RootDirectory(Directory):
|
|||
login.request.nameIDPolicy.format = lasso.SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT
|
||||
login.request.nameIDPolicy.allowCreate = True
|
||||
login.request.forceAuthn = False
|
||||
login.request.isPassive = True
|
||||
login.request.isPassive = False
|
||||
login.request.consent = 'urn:oasis:names:tc:SAML:2.0:consent:current-implicit'
|
||||
login.request.protocolBinding = lasso.SAML2_METADATA_BINDING_SOAP
|
||||
login.request.protocolBinding = lasso.SAML2_METADATA_BINDING_PAOS
|
||||
if False:
|
||||
# NTT ECP requires this:
|
||||
login.request.requestedAuthnContext = lasso.Samlp2RequestedAuthnContext()
|
||||
t = lasso.StringList()
|
||||
t.append('urn:oasis:names:tc:SAML:2.0:ac:classes:MobileOneFactorContract')
|
||||
login.request.requestedAuthnContext.authnContextClassRef = t
|
||||
login.buildAuthnRequestMsg()
|
||||
|
||||
response = get_response()
|
||||
response.set_content_type('text/xml')
|
||||
response.set_content_type('application/vnd.paos+xml', 'UTF-8')
|
||||
response.set_header('PAOS', 'ver=urn:liberty:paos:2003-08;urn:oasis:names:tc:SAML:2.0:profiles:SSO:ecp')
|
||||
return login.msgBody
|
||||
|
||||
def unlogged_page [html] (self):
|
||||
|
@ -148,7 +156,7 @@ class RootDirectory(Directory):
|
|||
('transient', _('Transient')),
|
||||
('encrypted', _('Encrypted')),
|
||||
('none', _('(none)'))])
|
||||
# XXX: affiliation
|
||||
form.add(StringWidget, 'affiliation', title = _('Affiliation'))
|
||||
form.add(SingleSelectWidget, 'consent',
|
||||
title = _('Consent'),
|
||||
options = ['', 'obtained', 'prior', 'current-implicit',
|
||||
|
@ -173,12 +181,12 @@ class RootDirectory(Directory):
|
|||
form.add_submit('intro', _('Get IdP via Introduction Cookie'))
|
||||
elif get_session().saml_idp_cookie:
|
||||
common_domain = get_cfg('sp', {}).get('common_domain')
|
||||
intro_cookie_q = urllib.unquote(get_session().saml_idp_cookie)
|
||||
intro_cookie_q = urllib.unquote_plus(get_session().saml_idp_cookie)
|
||||
splitted_cookie = [x for x in intro_cookie_q.split(str(' ')) if x]
|
||||
last_id = splitted_cookie[-1]
|
||||
v = misc.get_provider_key(base64.decodestring(last_id))
|
||||
form.add_submit('intro-%s' % v,
|
||||
_('Log on using IdP discovered from IdP Introduction'))
|
||||
_('Log on using IdP discovered from IdP Introduction (%s)') % v)
|
||||
|
||||
if form.is_submitted():
|
||||
return self.do_login(form)
|
||||
|
@ -192,6 +200,10 @@ class RootDirectory(Directory):
|
|||
_('Service Provider not configured to use IdP Introduction Cookie')
|
||||
'</p>'
|
||||
|
||||
'<p>'
|
||||
'Sample <a href="/data/affiliations.xml">affiliations</a> file to download'
|
||||
'</p>'
|
||||
|
||||
def loggedin_page [html] (self):
|
||||
identity_dump = get_request().user.lasso_dump
|
||||
session_dump = get_session().lasso_session_dump
|
||||
|
@ -223,15 +235,38 @@ class RootDirectory(Directory):
|
|||
|
||||
'<p>%s</p>' % _('Logged in (%s)') % get_request().user.display_name
|
||||
if get_request().user.anonymous:
|
||||
'<a href="register">%s</a>' % _('Register')
|
||||
if identity_dump:
|
||||
'<strong><a href="register">%s</a></strong>' % _('Register')
|
||||
|
||||
'<pre>'
|
||||
get_session().lasso_identity_provider_id
|
||||
'</pre>'
|
||||
|
||||
'<pre>'
|
||||
get_session().name_identifier
|
||||
'</pre>'
|
||||
'<div id="logged-in-options">'
|
||||
form.render()
|
||||
'</div>'
|
||||
|
||||
if os.path.exists(str('/tmp/artifact-msg-url')):
|
||||
'<p>'
|
||||
'<a href="replay_artifact">%s</a>' % _('Replay last artifact response')
|
||||
'</p>'
|
||||
|
||||
def replay_artifact [html] (self):
|
||||
msg_url = file(str('/tmp/artifact-msg-url')).read()
|
||||
msg_body = file(str('/tmp/artifact-msg-body')).read()
|
||||
from qommon.liberty import soap_call
|
||||
soap_answer = soap_call(msg_url, msg_body)
|
||||
open(str('/tmp/replayed-artifact.xml'), str('w')).write(soap_answer)
|
||||
formatted = os.popen(str('xmllint --format /tmp/replayed-artifact.xml')).read()
|
||||
|
||||
template.html_top(_('Artifact Replayed'))
|
||||
'<pre>'
|
||||
formatted
|
||||
'</pre>'
|
||||
|
||||
|
||||
def register [html] (self):
|
||||
if not get_request().user:
|
||||
|
@ -318,6 +353,10 @@ class RootDirectory(Directory):
|
|||
if consent:
|
||||
login.request.consent = 'urn:oasis:names:tc:SAML:2.0:consent:%s' % consent
|
||||
|
||||
affiliation = form.get_widget('affiliation').parse()
|
||||
if affiliation:
|
||||
login.request.nameIDPolicy.spNameQualifier = affiliation
|
||||
|
||||
# XXX: authn_context
|
||||
|
||||
login.buildAuthnRequestMsg()
|
||||
|
@ -363,6 +402,47 @@ class RootDirectory(Directory):
|
|||
|
||||
return Directory._q_traverse(self, path)
|
||||
|
||||
def encryption [html] (self):
|
||||
form = Form(enctype='multipart/form-data')
|
||||
options = []
|
||||
for klp, lp in get_cfg('idp', {}).items():
|
||||
try:
|
||||
label = misc.get_provider_label(misc.get_provider(klp))
|
||||
except KeyError:
|
||||
continue
|
||||
options.append((klp, label, klp))
|
||||
options.sort()
|
||||
|
||||
for klp, label, klp2 in options:
|
||||
form.add(HtmlWidget, '<h3>%s</h3>' % label)
|
||||
form.add(CheckboxWidget, 'encrypt_nameid_%s' % klp,
|
||||
title = _('Encrypt NameID'),
|
||||
value = get_cfg('idp')[klp].get('encrypt_nameid'))
|
||||
|
||||
form.add_submit('submit', _('Submit'))
|
||||
form.add_submit('cancel', _('Cancel'))
|
||||
|
||||
if form.is_submitted():
|
||||
self.encryption_submit(form, options)
|
||||
return redirect('.')
|
||||
|
||||
template.html_top()
|
||||
|
||||
if not get_cfg('sp').has_key('encryption_privatekey'):
|
||||
'<div class="errornotice">'
|
||||
_('There is currently no encryption key set on this server.')
|
||||
'</div>'
|
||||
|
||||
form.render()
|
||||
|
||||
def encryption_submit(self, form, options):
|
||||
for klp, label, klp2 in options:
|
||||
get_cfg('idp')[klp]['encrypt_nameid'] = form.get_widget(
|
||||
'encrypt_nameid_%s' % klp).parse()
|
||||
get_publisher().write_cfg()
|
||||
|
||||
|
||||
|
||||
def _q_lookup(self, component):
|
||||
if component == 'themes':
|
||||
dirname = os.path.join(get_publisher().data_dir, 'themes')
|
||||
|
|
Reference in New Issue