A UW-specific adapter to the python3-saml package.
Project description
uw-saml
A UW-specific adapter to the python3-saml package. This package was built to federate with other IdPs, but the default case is to use the UW Identity Provider. It can be used against any framework. For a django-specific package, also consider uw-django-saml2.
Installation
pip install uw-saml[python3-saml]
The extra [python3-saml]
is because the SAML package can be cumbersome to
install in a workstation environment, on account of needing the libxmlsec1-dev
library. Therefore, it's an optional requirement, causing a runtime error
instead of an install-time error. Alternatively, you can use a mock
interface by setting uw_saml2.python3_saml.MOCK = True
.
Example login endpoint using flask
In this example you've gone to SP Registry and registered an Entity ID of https://samldemo.iamdev.s.uw.edu/saml, with an ACS endpoint of https://samldemo.iamdev.s.uw.edu/saml/login. GETs will return a redirect to the IdP for authentication, and POSTs will try to process a SAML Response.
from flask import request, session, redirect
import uw_saml2
@app.route('/saml/login', methods=['GET', 'POST'])
def login():
session.clear()
args = {
'entity_id': 'https://samldemo.iamdev.s.uw.edu/saml',
'acs_url': 'https://samldemo.iamdev.s.uw.edu/saml/login'
}
if request.method == 'GET':
args['return_to'] = request.args.get('url', None)
return redirect(uw_saml2.login_redirect(**args))
attributes = uw_saml2.process_response(request.form, **args)
session['userid'] = attributes['uwnetid']
session['groups'] = attributes.get('groups', [])
relay_state = request.form.get('RelayState')
if relay_state and relay_state.startswith('/'):
return redirect(urljoin(request.url_root, request.form['RelayState']))
return 'Welcome ' + session['userid']
Considerations
Sessions
Give some consideration to session lifetime. The session in this example lives as a signed cookie. Ideally the cookie would expire at browser close, along with some time limit appropriate for your application. An example again with flask for a ten minute limit...
from datetime import timedelta
app.config.update(
PERMANENT_SESSION_LIFETIME=timedelta(minutes=10)
)
Replay attack prevention
By default this package uses an in-memory cache to check for replay attacks.
To use a distributed cache such as redis or memcached you would inject a
cache object into uw_saml2.auth.CACHE
. Here's an example of how to do it...
import werkzeug.contrib.cache
import uw_saml2.auth
uw_saml2.auth.CACHE = werkzeug.contrib.cache.RedisCache()
Django's cache backend uses the same methods so that could be injected as well.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.