.. _single-sign-on:
Single sign on (OIDC)
=====================
Geant Argus supports Single Sign On using ``social-auth-core`` and ``social-auth-django``
(`Python Social Auth `_). These libraries
make integration with CoreAAI straight forward for authentication of users. However, they only
deal with the first part of the auhtentication/authorization flow, namely authentication when
a user logs in. It does not handle authorization neither does it make sure that the authentication
(and authorization) is still valid for an existing session.
CoreAAI
-------
Geant Argus is registered as an OIDC Client in the CoreAAI platform. When registering, the
following authorization grants are required:
* authorization_code
* refresh_token
Also, the following scopes are required:
* Display name
* Email address
* Groups (Entitlements)
Development
###########
During development, by default OIDC integration is disabled. To start developing with the Core AAI
OIDC integration, set ``ARGUS_OIDC_DISABLE`` environment variable to 0 (or unset it completely) in
your ``cmd.sh``. You then also need to set the other ``ARGUS_OIDC_*`` environment variables in your
``cmd.sh``. The values for these variables can be found in LastPass under the Argus OIDC settings.
Choose the "Local" settings.
For development, Geant Argus is registered as a different application with a different
``client_id`` than for production. The reason for this is that the development client_id supports
a redirect uri beginning with ``http://127.0.0.1:8000`` so that it can be used with local
development. In order to log in using the development ``client_id`` your oidc user account must be
part of the Sandbox VO group. You can add yourself to this group as part of the login process.
.. _single-sign-on-authorization:
Authorization
-------------
Geant Argus uses group based authentication. By default, OIDC users have read-only access to Argus.
Then, depending on authorization rules, OIDC users can be assigned Argus groups based on their
*entitlements*. Entitlements is the list of VO groups that the user is part of. This list is part
of the user data coming from the CoreAAI platform.
Mapping the entitlements to Argus groups is based on the ``OIDC_AUTHORIZATION_RULES`` setting
which is set using the :ref:`config-json`. This setting contains a list of rules that can have one
of two types. The first is an entitlement rule to one-to-one map an entitlement to a group. For
example::
{
"entitlement": "some:entitlement:string",
"group": "some-group"
}
The second type is an entitlement pattern to use regex to capture groups from a class of
entitlements an construct a group name based on the result. The named regex capture groups
can be used to form a group name using python ``format`` style string interpolation. For
example::
{
"entitlement_pattern": "prefix:(?P\\S+)#aai.geant.org",
"group": "{group}-members"
}
The above example would mean that a user with an entitlement ``prefix:swd#aai.geant.org``
would be added to the ``swd-members`` group. Keep in mind that the regex should be constructed
in such a way to prevent accidental matches.
The actual entitlements that users have are URNs and are generally more complex in nature, but the
concept remains the same.
.. _single-sign-on-group-permissions:
Group permissions
#################
After a user has been assigned groups, these groups are used to determine the permissions a user.
There are two ways that permissions are granted to a user/group. The first is by direct membership.
``geant_argus.auth`` has two constant variables: ``DJANGO_WRITE_PERMSSION_GROUP`` and
``DJANGO_SUPERUSER_GROUP``. If a user is part of the group defined in
``DJANGO_WRITE_PERMSSION_GROUP`` (ie: ``editors``), they will get full write access to Geant Argus.
If a user is part of the ``DJANGO_SUPERUSER_GROUP`` (ie: ``admin``), they will get access to the
administrative area of Geant Argus (the Djano Admin backend)
The second way that authorization is granted, is by making use of the existing django permission
system. Permisions can be granted to groups and users in the Admin area. Edit a user or group and
add or remove Permissions. There are currently two of these permissions used:
* blacklist | Can view blacklist (``blacklist.view_blacklist``)
* blacklist | Can change blacklist (``blacklist.change_blacklist``)
These blacklist permissions are used to allow only the NOC to view and edit blacklists.
Views can be guarded using the ``django.contrib.auth.decorators.permission_required`` decorator
(see also :django:`topics/auth/default/#permissions-and-authorization`)
Middleware
----------
By default, once a user has successfully logged in, Python Social Auth does not validate whether
a user is still active in the OIDC provider or if their entitlements have changed. Geant Argus has
middleware in place that periodically checks the CoreAAI platform for these changes:
``geant_argus.auth.SocialAuthRefreshMiddleware``.
.. note::
As of May 2025 there is a bug in the CoreAAi platform that prevents the
``SocialAuthRefreshMiddleware`` to obtain a user's current entitlements for the duration of the
user's session. Therefore this middleware has been disabled in favor of a different middleware:
``geant_argus.auth.SocialAuthLimitSessionAgeMiddleware``. This middleware limits the session
lifetime of OIDC users to 24 hours, so that after a user's authorization has been revoked, it
takes a maximum of 24 hours for the user's sessions to be evicted from Geant Argus. This session
lifetime was chosen as a compromise between security and usability. It is also possible to delete
a user's sessions manually through the admin interface, under *Sessions*
Settings
--------
The following settings are used to setup the SSO configuration.
.. list-table::
:widths: 25 50 25
:header-rows: 1
* - Setting
- Description
- Location
* - ``ARGUS_OIDC_DISABLE``
- Whether to disable the OIDC authentication backend
- Environment variable
* - ``ARGUS_OIDC_METHOD_NAME``
- The text to show on the button in the login page
- ``geant_argus.settings.base``
* - ``ARGUS_OIDC_URL``
- The root url of the CoreAAI OIDC service
- Environment variable
* - ``ARGUS_OIDC_CLIENT_ID``
- The Geant Argus OIDC client ID, see Lastpass
- Environment variable
* - ``ARGUS_OIDC_SECRET``
- The Geant Argus OIDC client secret, see Lastpass
- ``geant_argus.settings.base``
* - ``OIDC_AUTHORIZATION_RULES``
- A list of authorization rules as described in :ref:`single-sign-on-authorization`
- ``config.json``
* - ``SOCIAL_AUTH_OIDC_SCOPE``
- The OIDC scopes to request with the authentication request, in addition to the default
``openid`` , ``profile`` and ``email`` scopes. ``entitlements`` is required to obtain the
entitlements and ``offline_access`` is required for the refresh token
- ``geant_argus.settings.base``
* - ``SOCIAL_AUTH_PIPELINE``
- When a user logs in using OIDC, a pipeline is run to setup the user. See also
`Python Social Auth: Pipeline `_
- ``geant_argus.settings.base``
* - ``SOCIAL_AUTH_USERNAME_IS_FULL_EMAIL``
- Use the user's email as their username
- ``geant_argus.settings.base``
* - ``SOCIAL_AUTH_LOGIN_ERROR_URL``
- Redirect users back to the login page if an OIDC login errors somehow
- ``geant_argus.settings.base``
* - ``SOCIAL_AUTH_JSONFIELD_ENABLED``
- Optimization to store OIDC data as a JSONField in PostgreSQL
- ``geant_argus.settings.base``
* - ``SOCIAL_AUTH_OIDC_AUTH_EXTRA_ARGUMENTS``
- Addtional parameters to send with the authentication request ``prompt=consent`` is somehow
required for the ``offline_access`` scope
- ``geant_argus.settings.base``