How to: META-SHARE SSO Introduction and links Install djangosaml2 Neeme Kahusk

How to: META-SHARE SSO
Neeme Kahusk
May 27, 2014
Introduction and links
• https://bitbucket.org/lgs/djangosaml2 (Djangosaml2 page)
Install djangosaml2
sudo pip install djangosaml2
Module djaongosaml2 needs xmlsec1. It seems that the best would be
to use the version that is installable via package management. At first we
had a newer version, but it was incompatible and caused some errors. On
Ubuntu we did
$sudo apt-get install xmlsec1
$xmlsec1 --version
xmlsec1 1.2.14 (openssl)
Changed files of META-SHARE installation
In Configuratin chaper of the djangosaml2 documentation, there are mentioned settings.py, urls.py and pysaml2 specific files. We divided the
settings.py and pysaml2 settings between META-SHARE settings.py,
and saml_settings.py (new file).
File settings.py
Logging in
1
# LOGIN_URL = ’/{0}login/’.format(DJANGO_BASE)
LOGIN_URL = ’/{0}saml2/login/’.format(DJANGO_BASE) # new for djangosaml
LOGIN_REDIRECT_URL = ’/{0}’.format(DJANGO_BASE)
LOGOUT_URL = ’/{0}logout/’.format(DJANGO_BASE)
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
# new for djangosaml
Installed apps
INSTALLED_APPS += (’djangosaml2’,) # new for djangosaml
And finally,
from saml_settings import *
To debug the connection we also set up aditional logging:
LOGGING = {
’version’: 1,
’disable_existing_loggers’: True,
’formatters’: {
’standard’: {
’format’ : "[%(asctime)s] %(levelname)s [%(name)s:%(lineno)s] %(message)s",
’datefmt’ : "%d/%b/%Y %H:%M:%S"
},
},
’handlers’: {
’null’: {
’level’:’DEBUG’,
’class’:’django.utils.log.NullHandler’,
},
’logfile’: {
’level’:’DEBUG’,
’class’:’logging.handlers.RotatingFileHandler’,
’filename’: "/usr/local/META-SHARE-3.0.1/metashare/sitelogger",
’maxBytes’: 50000,
’backupCount’: 2,
’formatter’: ’standard’,
},
’console’:{
’level’:’INFO’,
2
’class’:’logging.StreamHandler’,
’formatter’: ’standard’
},
},
’loggers’: {
’django’: {
’handlers’:[’console’],
’propagate’: True,
’level’:’WARN’,
},
’django.db.backends’: {
’handlers’: [’console’],
’level’: ’DEBUG’,
’propagate’: False,
},
’’: {
’handlers’: [’console’, ’logfile’],
’level’: ’DEBUG’,
},
}
}
New file saml_settings.py
The pysaml2 specific configuration, like in https://bitbucket.org/lgs/djangosaml2#rstheader-pysaml2-specific-files-and-configuration
SAML_ATTRIBUTE_MAPPING and unknown user
For TAAT we used the following attribute mapping (still in file saml_settings.py),
and added variable for creating unknown user:
SAML_ATTRIBUTE_MAPPING = {
’eduPersonPrincipalName’:(’username’,),
’mail’:(’email’,),
’cn’:(’last_name’, ’first_name’),
’schacHomeOrganization’:(’affiliation’,),
}
SAML_CREATE_UNKNOWN_USER = True
3
File urls.py
# saml2 settings
urlpatterns += patterns(’’,
(r’^{0}saml2/’.format(DJANGO_BASE), include(’djangosaml2.urls’)),
)
Other files
In metashare/templates/header.html for SSO Login and SSO Logout buttons
<div class="inner_box" style="width:300px;float:right;">
{% if user.username %}
<a href="{% url djangosaml2.views.logout %}?next={{ request.path }}" style="flo
<a href="{% url metashare.views.logout %}?next={{ request.path }}" style="float
{% else %}
<a href="{% url metashare.accounts.views.create %}"><div class="topright">Regis
<a href="{% url djangosaml2.views.login %}?next={{ request.path }}"><div class=
<a href="{% url metashare.views.login %}?next={{ request.path }}"><div class="t
{% endif %}
</div>
Directory attributemaps from djangosaml installation to metashare directory (cp -r).
File ekrk_remote_metadata.xml for IDP metadata.
We have also changed backends.py in djangosaml2 installation, in order
to get First and Last Name from cn attribute (function _set_attribute):
def _set_attribute(self, obj, attr, value):
"""Set an attribute of an object to a specific value.
Return True if the attribute was changed and False otherwise.
"""
def namesplitter(iStr):
"""Splits strings by blanks or change of case"""
oList = []
if iStr.count(’ ’):
return iStr.split(’ ’)
elif iStr.islower():
4
return iStr
else:
iStr = list(iStr)
oStr = iStr.pop(0)
while iStr:
i = iStr.pop(0)
if i.islower():
oStr += i
else:
oList.append(oStr)
oStr = i
oList.append(oStr)
return oList
field = obj._meta.get_field_by_name(attr)
# names from attrs vvv ###
if attr == ’first_name’:
value = namesplitter(value)[0]
elif attr == ’last_name’:
value = namesplitter(value)[-1]
# names from attrs ^^^ ###
/- - -/
Known bugs and features
If User has logged in via SSO, then she can use ordinary “Logout” button,
but then it is possible to log in again with the same user name without
password, during the same browser session. “SSO Logout” button logs out
like the browser was closed.
If a User logs in in old-fashioned way (as local user), then pressing “SSO
Logout” button results in Internal Server Error (500), but it is not fatal.
The Local Users and SSO Users are not connected to each other, it is the
responsibility of Administrator to give SSO users editor rights.
5