Production
Deploying an application which makes use of django-aai-eduhr to production takes a bit more effort, nevertheless it
is only a matter of configuration. The manage.py aai_quickstart command generates SAML configuration suitable for
development, but these settings are not necessarily secure, and incur minor performance penalty.
Hint
This is not an exhaustive list of security related settings by any means, see pysaml2 docs for more options like used algorithms, certificate validation, etc.
Security
Depending on your security requirements, and the data you exchange with AAI@EduHr IdP, you need to enable signing and
encryption. If you don’t exchange personal information, you may get away with signing only. This ensures that IdP and
SP can detect if messages have been tampered with during transmission, for example in case of man-in-the-middle
attacks. If you do exchange personal information, for example hrEduPersonOIB, it is strongly advised to enable
encryption as well. In any case, these come with a bit of a performance overhead, so they’re disabled by default in the
development configuration.
Signing
Depending on your configuration, you should enable Sign Assertion, Sign Response and Sign Logout in the AAI@EduHr resource registry. You should also enable signature validation for authentication and logout requests, i.e. Validate Authn Request and Validate Logout Request.
Configure your certificate/public key in the SP Signing Certificate field without the
-----BEGIN/END CERTIFICATE----- lines. This will enable signing and validation of exchanged messages by the IdP.
On the application side, you should enable want_assertions_signed and want_responses_signed. If you have enabled
validation of authentication and logout requests, you can enable signing by setting authn_requests_signed and
logout_requests_signed, respectively. For stricter security, consider signing logout responses as well
by enabling logout_responses_signed.
SAML_CONFIG = {
# extra configuration removed for clarity
'service': {
'sp': {
'want_assertions_signed': True, # validate signed assertions
'want_response_signed': True, # validate signed responses
'authn_requests_signed': True, # sign authentication requests
'logout_requests_signed': True, # sign logout requests
'logout_responses_signed': True, # sign logout responses
},
},
}
If you enabled signing on the SP side, you should enable Validate Authn Request, Validate Logout Request and Validate Redirect respectively.
Finally, configure the path to your certificate and corresponding private key which the SP will use for signing and validation.
SAML_CONFIG = {
# extra configuration removed for clarity
'key_file': '/path/to/my/signing_key.pem',
'cert_file': '/path/to/my/signing_certificate.pem'
}
Encryption
For the encryption, you should enable Encrypt Assertion and/or NameID Encryption, and then configure the encryption certificate. On the SP side you should configure both the certificate and the corresponding private key.
SAML_CONFIG = {
# extra configuration removed for clarity
'encryption_keypairs': [
{
'key_file': '/path/to/my/encryption_key.pem',
'cert_file': '/path/to/my/encryption_certificate.pem'
}
],
}
Bearer Assertion Replay
The backend provided by the django_aai_eduhr.backends includes built-in protection against bearer assertion replay
attacks. However, this protection requires proper configuration to function correctly.
If you’re developing a custom authentication backend and do not inherit from django_aai_eduhr.backends.AAIBackend,
you can still enable replay attack mitigation by including django_aai_eduhr.backends.AssertionReplayMitigationMixin.
This mixin implements the necessary logic to prevent the reuse of previously processed assertions.
The mixin relies on Django’s caching framework to temporarily store identifiers from processed assertions. It also
checks the NotOnOrAfter attribute of each assertion to ensure it hasn’t expired. Once an assertion is used,
it is recorded in the cache and will be rejected if seen again.
Because the mitigation logic depends on the cache, it is essential that your Django project has a correctly configured caching backend. In production environments, where your application may run in multiple processes (e.g., multiple Gunicorn workers), your cache must support cross-process caching.
By default, if you haven’t explicitly configured caching, Django uses the local memory cache, which is not shared between processes. This can result in replay attack protection silently failing, as each process maintains its own isolated cache.
To ensure proper functionality, you must use a cache backend that supports shared access across processes, such as Redis or Memcached, but any cache that implements the Django cache API is compatible.
You can choose which cache django_aai_eduhr.backends.AssertionReplayMitigationMixin will use by changing
AAI_ASSERTION_CACHE setting which is default if not explicitly configured.
Metadata
Exchange of metadata facilitates the automatic configuration of SAML entities by sharing important information about each party’s endpoints, capabilities, and configurations. This can be achieved by preloading the metadata locally, automatic retrieval from the remote URL or through an MDQ service.
The manage.py aai_quickstart command sets up remote retrieval of IdP’s metadata, but this slows down performance
since network IO is slower than local disk IO. You can configure your application to load metadata locally which will
improve performance.
SAML_CONFIG = {
# extra configuration removed for clarity
'metadata': {
'local': ['/path/to/idp/metadata.xml']
},
}
You can obtain the production and the AAI@EduHr Lab metadata by downloading it from the link provided in the AAI@EduHr documentation, under the “All SAML implementations” section.
Description
You can provide human-readable information about your service endpoint by adding descriptive information to your SAML configuration. This will be used when generating metadata, see pysaml2 docs for a full list of attributes.
SAML_CONFIG = {
# extra configuration removed for clarity
'name': 'My custom application.',
'description': 'My custom application does something rad.',
'organization': {
'name': [
('Example Organisation', 'en'),
('Primjer Organizacije', 'hr')
],
'display_name': ['Primjer Organizacije'],
'url': [
('http://example.org', 'en'),
('http://hr.example.org', 'hr'),
],
},
'contact_person': [
{
'given_name': 'Fox',
'sur_name': 'Mulder',
'company': 'The X-Files',
'email_address': ['fmulder@xfiles.com'],
'telephone_number': ['+1 234 567 89'],
# accepted values: technical, support, administrative, billing and other
'contact_type': 'technical',
},
{
'given_name': 'Dana',
'sur_name': 'Scully',
'company': 'The X-Files',
'email_address': ['dscully@xfiles.com'],
'telephone_number': ['123-456-789'],
'contact_type': 'administrative',
},
],
}
Resource type
After everything else has been configured, you will need to toggle AAI@EduHr resource from test to production. First
update the AAI@EduHr metadata URL in the SAML_CONFIG. Test and production URLs are documented in the
official AAI@EduHr documentation.
SAML_CONFIG = {
# extra configuration removed for clarity
'metadata': {
'remote': [
{
'url': 'https://login.aaiedu.hr/sso/saml2/idp/metadata.php',
}
]
},
}
Finally, toggle the Resource Type from Test to Produkcija in the resource registry.