Skip to main content
Version: v4

External Authentication

Introduction

PILOS has two types of users:

Local users Local users can be created by administrators. They can log in to the system with the combination of email address and password. Via PILOS, an email can be sent to the user upon creation, also a password reset function can be activated.

External users In large environments it is impractical to manage all users in PILOS. Therefore PILOS can be connected to external authentication systems. LDAP, Shibboleth and OpenID Connect are available as interfaces. All three authentication providers can be operated in parallel, but none of them more than once.

Setup of external authentication providers

LDAP

To enable LDAP, you need to add/set the following options in the .env file and adjust to your needs.

# LDAP config
LDAP_ENABLED=true
LDAP_HOST=ldap.university.org
# For anonymous bind keep LDAP_USERNAME and LDAP_PASSWORD empty
LDAP_USERNAME="cn=readonly,dc=university,dc=org"
LDAP_PASSWORD="readonly"
LDAP_PORT=389
LDAP_BASE_DN="ou=users,dc=university,dc=org"
LDAP_TIMEOUT=5
LDAP_SSL=false
LDAP_TLS=true

# LDAP logging debugging only
LDAP_LOGGING=false

# Query the users attributes using the users own credentials
#LDAP_LOAD_ATTRIBUTES_AS_USER=false

# Raw LDAP filter to restrict the user search
#LDAP_FILTER=

# Attribute with GUID; OpenLDAP: 'entryuuid', AD: 'objectGUID'
LDAP_GUID_KEY=entryuuid

# Comma seperated list of the object class
LDAP_OBJECT_CLASSES=top,person,organizationalperson,inetorgperson

# Attribute by which the user should be found in the LDAP
LDAP_LOGIN_ATTRIBUTE=uid

SSL / TLS

You can either use SSL or TLS to secure the connection to the LDAP server. SSL has been deprecated and is typically a separate port (636). TLS is using the same port as the unsecured connection (389) and doing an upgrade to TLS after the connection has been established. Read more.

By default, PILOS doesn't verify the TLS certificate of the LDAP server. However, you can customize this by overwriting the ldap.conf (Read more ) config file in /etc/openldap/ldap.conf using docker volumes.

Shibboleth

The shibboleth authentication is available if the reverse proxy is apache with mod_shib. The application trusts the header information of the apache webserver and authenticates the user via the shibboleth protected route /auth/shibboleth/callback.

Configure Apache + mod_shib

You need to add the two options to your apache reverse proxy configuration to enable shibboleth support.

<Location />
AuthType shibboleth
ShibUseHeaders On
Require shibboleth
</Location>

<Location /auth/shibboleth/callback>
AuthType shibboleth
ShibUseHeaders On
ShibRequireSession On
Require valid-user
</Location>

If you host your own discovery service, you also need to add these lines before the ProxyPass so that these requests are not proxied.

ProxyPass /shibboleth-ds !
ProxyPass /shibboleth-sp !

You need the add the url of the font- and back-channel to the ApplicationDefaults element in the /etc/shibboleth/shibboleth2.xml file:

<Notify Channel="back" Location="https://DOMAIN.TLD/auth/shibboleth/logout" />
<Notify Channel="front" Location="https://DOMAIN.TLD/auth/shibboleth/logout" />

Configure application to use shibboleth

To enable Shibboleth, you need to enable it in the .env file.

# Shibboleth config
SHIBBOLETH_ENABLED=true

If Shibboleth authentication is enabled and a user is logged in via Shibboleth, session validity is checked on every request. If the check fails, the user is automatically logged out.

This is a common problem when running multiple SPs behind a load balancer, as by default they don't share session information and therefore other SPs cannot validate the session. As running a shared session between multiple SPs is a complex task, the recommended approach is not to require a valid Shibboleth session for every request (Learn more).

It is also the default behaviour of SPs to drop a session when the user's IP changes. This can happen if the user changes networks (mobile -> wifi) or uses a VPN (e.g. iCloud Private Relay). This can be mitigated either by disabling the IP check in the Shibboleth configuration (Learn mode) or by disabling the Shibboleth session check in PILOS.

To disable the shibboleth session check you can set the following .env variable:

# Disable checking Shibboleth session in every request
SHIBBOLETH_SESSION_CHECK_ENABLED=false

OpenID Connect

This application uses the Authorization Code Flow for OpenID Connect authentication.

Key Requirements

  • Client Registration

    Manual registration with your OpenID Connect Provider is required. Dynamic registration is not supported.

  • Client Authentication

    The application authenticates with the token endpoint using the client_secret_basic method.

  • Supported Signing Algorithms
    • RS256, RS384, RS512
    • PS256, PS384, PS512
    • ES256, ES384, ES512
    • EdDSA (only with the Ed25519 curve)
    • HS256, HS384, HS512
  • Limitations
    • Encrypted ID token responses are not supported.
    • Back-channel logout is recommended, especially in shared environments (e.g., computer labs), to prevent immediate re-login after logout.
    • Front-channel logout and OpenID Connect session management are not supported.

Configure OpenID Connect Provider

Register PILOS as a new client with your OpenID Connect Provider using these settings:

  • Authentication flow: Authorization Code Flow
  • Client authentication: client_secret_basic
  • Client ID and client secret: Generated by the OpenID Connect Provider or set application URL
  • Client secret: Generated by the OpenID Connect Provider or use a secure random string
  • Redirect URI: https://your-domain.com/auth/oidc/callback
  • Post-Logout Redirect URI: https://your-domain.com/logout
  • Back-Channel Logout URI: https://your-domain.com/auth/oidc/logout

Configure PILOS

To enable OpenID Connect, you need to add/set the following options in the .env file and adjust to your needs.

# OpenID Connect Configuration
OIDC_ENABLED=true
OIDC_ISSUER=http://idp.university.org
OIDC_CLIENT_ID=my_client_id
OIDC_CLIENT_SECRET=my_client_secret
OIDC_SCOPES="profile,email"

Configuration Options

OptionDefault ValueDescription
OIDC_ENABLEDfalseEnable OpenID Connect authentication.
OIDC_ISSUERnullThe issuer URL of the OpenID Connect Provider.
OIDC_CLIENT_IDnullThe client ID for the OpenID Connect application.
OIDC_CLIENT_SECRETnullThe client secret for the OpenID Connect application.
OIDC_SCOPESprofile,emailThe scopes (e.g., profile,email) to request from the OpenID Connect Provider as a comma-separated list. The openid scope is always included automatically.
OIDC_LEEWAY300The leeway in seconds for validating the ID token's expiration time.
OIDC_TIMEOUT10The timeout in seconds for the OpenID Connect requests.
OIDC_VERIFY_PEERtrueWhether to verify the SSL certificate of the OpenID Connect Provider. This can only be disabled in local env.
OIDC_CACHE_CONFIG_MAX_AGE0Overwrite openid-configuration cache duration if OpenID Connect Provider doesn't set a max-age cache duration > 0
OIDC_CACHE_JWKS_MAX_AGE0Overwrite jwks cache duration if OpenID Connect Provider doesn't set a max-age cache duration > 0
OIDC_PROFILE_IMAGE_TRUSTED_HOSTSnullComma-separated list of trusted hosts to load profile images from.
OIDC_PROFILE_IMAGE_MAX_SIZE5Maximum size in megabytes for profile images fetched from OpenID Connect Providers.

Configure mapping

For each external authentication provider the attribute and role mapping needs to be configured. The mapping is defined in a JSON file, which is stored in the directory app/Auth/config of the PILOS installation.

Authentication ProviderFilename
LDAPldap_mapping.json
Shibbolethshibboleth_mapping.json
OpenID Connectoidc_mapping.json

Attribute mapping

Required attributes

You must add attribute mapping for the following attributes.

AttributeDescription
external_idUnique identifier of the user, e.g. username
first_nameFirst name
last_nameLast name
emailEmail

Notice: The external identifier (external_id) is used to uniquely identify a user within each authentication provider. User accounts are not shared between authentication providers.

Array attributes

If the value of one of the required attributes is an array, the first array entry is used.

Profile image (LDAP)

An LDAP server can store a profile image in the jpegPhoto attribute as per RFC 2798. To sync the profile image, map jpegPhoto to image in the mapping file. While the profile image is stored in the LDAP server, it cannot be changed by the user in PILOS UI and is synced on every login.

{
"attributes": {
"external_id": "cn",
"first_name": "givenname",
"last_name": "sn",
"email": "mail",
"image": "jpegPhoto"
}
}

Profile image (OpenID Connect)

The OpenID Connect providers may return a picture claim (see OpenID Connect Core 1.0). The claim must be a valid image URL (jpg, png, or gif). PILOS downloads and stores the image and only re-fetches it if the URL changes. To enable syncing, map picture to image in the mapping file. You might also have to add additional scopes to OIDC_SCOPES to get the claim from the provider. While the picture claim is present, the user cannot change the profile image in the PILOS UI; it is updated on each login.

{
"attributes": {
"external_id": "preferred_username",
"first_name": "given_name",
"last_name": "family_name",
"email": "email",
"image": "picture"
}
}

Additional attributes

You can define additional attributes. These attributes are not saved in the database, but they can be used for role mapping.

Role mapping

Roles

To add a mapping to a role, add a new object to the roles array. The attribute name must match the name of the role in PILOS.

Disable roles

To disable a role, you can add and set the attribute disabled to true.

Rule policy

By default, only one role must be fulfilled for the role to be applied. However, if you want to combine the rules, so that every rule must be fulfilled, set the attribute all to true.

Rules

Each rule is defined by at least an attribute and regex. The attribute is the name of an attribute of the user object defined in the attribute mapping. The value of the attribute is matched with a regular expression. If the regular expression find a match the rule is fulfilled.

To create and test regular expression you can use tools like: https://regex101.com/ or https://regexr.com/ . Please note: You have to double escape the \ symbol.

Array attributes

If the attribute returns an array and not a string, by default the regular expression only has to match one array entry for the rule to pass.

If the regular expression has to match all array entries, add the attribute all to the rule object and set its value to true.

Negate

To negate the result of the regex, add the attribute not to the rule object and set its value to true.

Arrays

The negation of arrays means: Check that regular expression doesn't match on any entry. If the all attribute is also true: Check that regular expression doesn't match all entries.

Examples

LDAP

Attributes

In this example the LDAP schema uses the common name (CN) as username and has the group memberships in the memberof attribute.

Roles
  • The "superuser" role is assigned to any user whose email ends with @its.university.org and who is in the "cn=admin,ou=Groups,dc=uni,dc=org" group.

  • The "user" role is given to everyone.

{
"attributes": {
"external_id": "cn",
"first_name": "givenname",
"last_name": "sn",
"email": "mail",
"groups": "memberof"
},
"roles": [
{
"name": "user",
"disabled": false,
"rules": [
{
"attribute": "external_id",
"regex": "/^.*/i"
}
]
},
{
"name": "superuser",
"disabled": false,
"all": true,
"rules": [
{
"attribute": "email",
"regex": "/@its\\.university\\.org$/i"
},
{
"attribute": "groups",
"regex": "/^cn=admin,ou=Groups,dc=university,dc=org$/im"
}
]
}
]
}

Shibboleth

Attributes

The attribute names are the header names in which the attribute values are send by the apache mod_shib to the application.

Roles
  • The "superuser" role is assigned to any user whose email ends with @its.university.org and who has the "staff" affiliation.

  • The "user" role is given to everyone.

{
"attributes": {
"external_id": "principalname",
"first_name": "givenname",
"last_name": "surname",
"email": "mail",
"roles": "affiliation"
},
"roles": [
{
"name": "superuser",
"disabled": false,
"all": true,
"rules": [
{
"attribute": "email",
"regex": "/.*(@its\\.university\\.org)$/i"
},
{
"attribute": "roles",
"regex": "/^(staff)$/im"
}
]
},
{
"name": "user",
"disabled": false,
"rules": [
{
"attribute": "external_id",
"regex": "/^.*/im"
}
]
}
]
}

OpenID Connect

Attributes

In this example the OpenID Connect provider returns the claim preferred_username which contains the username and an additional claim roles with an array of roles.

Roles
  • The "superuser" role is assigned to any user who has the "pilos-superuser" role.
{
"attributes": {
"external_id": "preferred_username",
"first_name": "given_name",
"last_name": "family_name",
"email": "email",
"roles": "roles"
},
"roles": [
{
"name": "superuser",
"disabled": false,
"rules": [
{
"attribute": "roles",
"regex": "/^pilos-superuser$/im"
}
]
}
]
}