Getting started
Installation
To get started, create your virtual environment and install the django-aai-eduhr package.
python3 -m venv venv
source venv/bin/activate
pip install django-aai-eduhr
Applications and middleware
Add djangosaml2 and django_aai_eduhr to your INSTALLED_APPS setting:
INSTALLED_APPS = [
# your application
'django_aai_eduhr',
'djangosaml2',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.staticfiles',
]
Hint
Make sure your application appears before the aforementioned two in the list in case you want to override the default 403 Forbidden template, which the ACS view renders if the assertions are not valid.
Add djangosaml2.middleware.SamlSessionMiddleware to your middleware. The middleware ensures saml_session attribute
is set on the request object. Note that it depends on the django.contrib.sessions.middleware.SessionMiddleware, so
the SamlSessionMiddleware should appear later in the list.
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'djangosaml2.middleware.SamlSessionMiddleware'
]
Authentication backend
Configure the AAIBackend authentication backend. You can use it in combinations with other backends or as the only
authentication backend.
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'django_aai_eduhr.backends.AAIBackend',
)
It is important to set SAML_SESSION_COOKIE_SAMESITE policy to None, otherwise browsers won’t send the SAML session
cookie on cross-origin requests, e.g. on successful login. In addition, SameSite=None cookies must have Secure
attribute and will only be sent in secure context, e.g. HTTPS. See Web API considerations for more
details.
SAML_SESSION_COOKIE_SAMESITE = 'None'
SESSION_COOKIE_SECURE = True
Hint
For local development, consider using a reverse proxy with self-signed HTTPS certificates to serve your Django
application securely. This allows browsers to accept SameSite=None cookies, which require a secure (HTTPS) context
to be sent. Otherwise, you will have to configure allow_unsolicited: True in your SAML_CONFIG.
You can choose whether the backend creates unknown users or rejects authentication.
SAML_CREATE_UNKNOWN_USER = True # default
If you want to authorise only a subset of AAI@EduHr accounts, you can configure the authorisation policy.
AAI_BACKEND_AUTHORISATION = {
'hrEduPersonPrimaryAffiliation': ['djelatnik'],
'o': ['uniri'],
'ou': ['inf']
}
AAI_BACKEND_POLICY = 'all' # default
This will grant access only to the employees of Faculty of Information and Digital Technologies of University of
Rijeka. Alternatively, you can set the AAI_BACKEND_POLICY to any. In this case, access will be granted to anyone
who is an employee, is from University of Rijeka, or is in inf organisational unit, regardless of other attributes.
Note
This feature only works with django_aai_eduhr.backends.AAIBackend and it’s derivatives. It is not a feature of the
base djangosaml2.backends.Saml2Backend. You can extend the existing backend or provide your own, see
djangosaml2 docs for more
details.
URL configuration
Include django-aai-eduhr URLs in your Django project. This will configure AAI@EduHr Login, Logout, ACS and metadata
views in your project.
from django.urls import path, include
urlpatterns = [
# other URL patterns
path('aai/', include('django_aai_eduhr.urls')),
]
This adds following URLs to your project:
# url name
aai/login/ # saml2_login
aai/acs/ # saml2_acs
aai/logout/ # saml2_logout
aai/ls/ # saml2_ls
aai/ls/post/ # saml2_ls_post
aai/metadata/ # saml2_metadata
You need to configure LOGIN_URL where users will be redirected if not logged in, and ACS_DEFAULT_REDIRECT_URL where
users will be redirected to on successful login. You may also configure LOGOUT_REDIRECT_URL.
LOGIN_URL = '/aai/login/' # or reverse_lazy('saml2_login')
ACS_DEFAULT_REDIRECT_URL = LOGIN_REDIRECT_URL = '/'
LOGOUT_REDIRECT_URL = '/thank-you/'
Important
If your redirect URL is not on the same host as your ACS view, you need to add it to SAML_ALLOWED_HOSTS. See
djangosaml2 docs for more
details.
Note
Note that the default ACS view first looks up the next GET parameter, and only falls back to
ACS_DEFAULT_REDIRECT_URL or LOGIN_REDIRECT_URL if the parameter is not present or is invalid.
SAML configuration
The easiest way to configure SAML is to run manage.py aai_quickstart. This will start a wizard which
will guide you through setting up SAML SP endpoint. Upon completion, the wizard will generate copy of your settings
file including the generated SAML config.
Alternatively, you can override your settings by passing in the -w flag, or you can supply a different path by
passing the -o <path> parameter.
Warning
The generated settings are not suitable for production. See production for more details.
Important
If you generated the settings instead of overwriting them, don’t forget to point to it by modifying
DJANGO_SETTINGS_MODULE environment variable.
If you’re looking to configure the endpoint yourself, see djangosaml2 and pysaml documentation for more details.
Attribute mapping
As a next step, you need to configure how AAI@EduHr attributes will map to your User and related models. The
AAIBackend can map attributes to your User model directly or to the related model holding AAI@EduHr data.
AAI_MODEL = 'app.CustomAAIModel'
AAI_MODEL_RELATED_NAME = 'aai_data'
SAML_DJANGO_USER_MAIN_ATTRIBUTE = 'username'
SAML_DJANGO_USER_MAIN_ATTRIBUTE_LOOKUP = '__iexact'
SAML_ATTRIBUTE_MAPPING = {
'hrEduPersonUniqueID': ('username',),
'mail': ('email', ),
'givenName': ('first_name',),
'sn': ('last_name',),
'o': ('aai_data.organisation_name',),
# phone_numbers is a related name of a ForeignKey field defined on the `CustomAAIModel`.
'mobile': ('aai_data.phone_numbers.number',)
}
SAML_DJANGO_USER_MAIN_ATTRIBUTE specifies the identifying (unique) attribute of the User model. This is typically
username, but can be other attribute if using custom User model.
SAML_DJANGO_USER_MAIN_ATTRIBUTE_LOOKUP specifies
lookup query for the main attribute.
This configuration will map NameID (e.g. hrEduPersonUniqueId) to the username attribute, and the first 4
attributes of SAML_ATTRIBUTE_MAPPING directly to the User model. Organisation name o will be mapped to the
related app.CustomAAIModel’s organisation_name attribute. Because mobile is a multi-valued attribute, it will create
multiple instances of PhoneNumber model and associate it to the corresponding CustomAAIModel.
In this example, CustomAAIModel and PhoneNumber would look like the following:
from django.contrib import auth
from django.db import models
class CustomAAIModel(models.Model):
user = models.OneToOneField(auth.get_user_model(), models.CASCADE, related_name='aai_data')
organisation_name = models.CharField(max_length=250)
class PhoneNumber(models.Model):
aai_data = models.ForeignKey('myapp.CustomAAIModel', models.CASCADE, related_name='phone_numbers')
number = models.CharField(max_length=32)
Important
Starting from the User model, AAIBackend traverses relationships up to one level deep for regular attributes, and
up to two levels deep for multi-valued attributes. Deeply nested attributes won’t be set by the backend.
Target attribute can also be a method defined on the User object, in which case it will be called with the attribute
values. For more details on SAML_ATTRIBUTE_MAPPING, consult the
djangosaml2 docs.
Warning
When using AAI@EduHr Lab, i.e. test instance, not all of the configured attributes will be delivered to your
application. Missing attributes will be logged if DEBUG=True, otherwise ImproperlyConfigured exception will be
raised.
Resource registry
Finally, you need to configure the IdP side in the resource registry with the matching settings. For information on how to register a SAML resource, see the official AAI@EduHr documentation.
Start by choosing Univerzalni Auth Service, basic Name Format and persistent NameId Format.
NameID Attribute is a unique value identifying each user, and can be one of the following:
hrEduPersistentID- a unique hash value,hrEduUniqueID- a unique string in the format<uid>@<realm>, e.g.full.name@example.org, ormail- an email.
Note
Provided authentication backends assume NameId format is persistent, but nothing stops you from developing your own authentication backend which supports transient NameID values.
In development, you can leave encryption and signing turned off, but it is recommended to turn them on in
production. In any case, your settings should match the settings configured in SAML_CONFIG.
Configure URLs pointing to your web application, i.e. entity id, assertion consumer service and single logout service.
Entity ID is a unique identifier that represents your application to AAI@EduHr, typically the URL of your SAML metadata. Assertion Consumer Service (ACS) is the endpoint where AAI@EduHr sends authentication responses (SAML assertions). Single Logout Service (SLS) is the endpoint used for sending and receiving logout requests and responses, enabling user logout across all SAML-connected applications.
If you followed the documentation so far, metadata, assertion consumer service and single
logout service will be exposed on /aai/metadata/, /aai/acs/, and /aai/ls/ paths respectively.
Hint
You can use localhost or loopback ip as the domain as long as it’s reachable from your clients, which is convenient in local development environments.
That’s it, you can now use AAI@EduHr as an authentication method!