Authentication backends

This plugin allows using alternative authentication backends for Rudder: OAuth 2.0, OpenID Connect, and LDAP or Active Directory (AD). The old radius module is deprecated and will be totally removed in a future version.

Each authentication method is detailed below. Users are expected to know how an authentication system works independently of Rudder to configure it in Rudder: you will likely need authentication token, URLs, and other properties provided by your company.

Configuring log level

Rudder has general info level information for user authentication. They trace what user get connected, with the use of what means.

[2020-07-28 12:01:13+0200] INFO application - Rudder authentication attempt for principal 'alice' with backend 'ldap': success

They trace log login failure at trace level:

[2023-07-28 12:00:07+0200] INFO application - Rudder authentication attempt for principal 'alice' with backend 'ldap': failure [2023-07-28 12:00:07+0200] INFO application - Rudder authentication attempt for principal 'alice' with backend 'file': failure [2023-07-28 12:00:07+0200] WARN application - Login authentication failed for user 'alice' from IP '127.0.0.1': Bad credentials

They are enough to follow user authentication. But authentication methods based on central authentication provider can be tricky to configure correctly, and that level of log won’t help you to set-up things. Rudder try to give you helpful information for that task:

  • there is a logger for the authentication backend plugin that can help you for general information like configuration: <logger name="auth-backends" level="debug" />

  • each authentication backend can provide more information with other loggers, which are in that case documented in their relevant section.

Centralized user authorization management with OIDC

In addition to alternative authentication provider, the OIDC backends allow providing Rudder roles through the OIDC token so that you can control your Rudder user authorisation directly from your identity provider. See OIDC chapter below for more information.

Configure login form rendering

By default, the standard Rudder login form is displayed. SSO backends like OpenID Connect ones add links to the relevant SSO own login page below that Rudder login form. When you use such an authentication method, you want to hide or totally remove Rudder own login form to avoid to confuse you user. For that, you can use the following property:

rudder.auth.displayLoginForm=show

Possible values are:

  • show [default]: show Rudder login form as usual

  • hide: hide the login form below a toggle button. This is a good option if you want to let your user only see SSO links by default, but still have access to the login form for special cases (like, typically, for emergency admin access when the SSO or network to it is down)

  • remove: completely remove Rudder login form.

For example, with an OpenID Connect service configured and the hide value chosen, your login form will be updated to look like:

oauth2 oidc login form

Configure enabled backends

Using one external backend for authentication

By default, both authentication and authorization are handle in the rudder-users.xml file. But you may want to rely on your existing enterprise Active Directory or LDAP to take care of the authentication part.

This behavior can be changed to use one of the provided authentication provider described below by editing the configuration property rudder.auth.provider in /opt/rudder/etc/rudder-web.properties.

For example, if you want to use the LDAP/AD authentication backend, you will set:

rudder.auth.provider=ldap

Identifier for each authentication backend is documented in its respective chapter below.

After a change in Rudder /opt/rudder/etc/rudder-web.properties configuration file or any configuration files under /opt/rudder/etc/rudder-web.properties.d/, Rudder needs to be restarted with the command:

systemctl restart rudder-jetty

When set to external provider like 'ldap', passwords in rudder-users.xml are ignored and the authentication is delegated to the corresponding provider.

By convention, when LDAP authentication is enabled, 'password' field in rudder-users.xml are set to 'LDAP'.

After a change in rudder-users.xml configuration file, you need to reload user information. This can be done with user-management plugin (either in UI or via API, see that plugin documentation for more information), or by restarting the web application with the command:

systemctl restart rudder-jetty

Using several backends for authentication

You can also use a comma separated list of authentication providers in rudder.auth.provider, like 'ldap,file' in which case each one will be tested in turned for authentication.

For example, to use first an ldap authentication, and then in case the user is not found in ldap, fall-back in file authentication, you will specify:

rudder.auth.provider=ldap,file

For example, that rudder-users.xml file will configure "admin" by file access, and "joe" by LDAP:

<authentication hash="sha512" case-sensitivity="true">
  <user name="admin" password="ab7f...b8a538dc69dd8de907ec" role="administrator" />
  <user name="joe" password="LDAP" role="administrator" />
</authentication>

Be careful to have only one rudder.auth.provider property in your files!

If an error happened in one of the authentication modules, the following in the provider sequence won’t be tried.

Root access when external authentication is not working

In case your authentication backend does not work, you can still configure the rootAccount in /opt/rudder/etc/rudder-web.properties to regain an administrator access. Once logged as an administrator, you can go to the Plugins > Authentication Backends page to check that Rudder interpreted correctly your configuration.

In particular, check that Computed list of providers entry matches your will.

LDAP / AD backend configuration

LDAP and Active Directories are a common enterprise authentication mean. In Rudder, they are configured with the same backend. That section explain what option are available, and in the following paragraphs we deal with the backend own logger and configuration of a secured (LDAPS) connection and how to register the corresponding certificate in Rudder.

LDAP backend parameters

The configuration properties needed to configure the LDAP or AD authentication backend are displayed below.

You should copy the whole configuration properties in a new file under /opt/rudder/etc/rudder-web.properties.d/(see xref:reference:administration:webapp.adoc#_configuration for more detail about how Rudder configuration properties override works).

Note that key "rudder.auth.provider" is already defined in /opt/rudder/etc/rudder-web.properties and will need to be updated in that place:

#
# update provider:
#
rudder.auth.provider=ldap
---- copy into new file /opt/rudder/etc/rudder-web.properties.d/20-ldap-authentication.properties ----


###########################
# LDAP Authentication      #############################################################
###########################


# The following parameters allow to configure the LDAP authentication provider.
# The LDAP authentication procedure is a typical bind/search/rebind, in which
# an application connection (bind) is used to search (search) for an user entry
# given some base and filter parameters, and then, a bind (rebind) is tried on
# that entry with the credential provided by the user.
# That allows to separate the user DN (especially RDN) from the search criteria while
# in the same time supporting users located in several different organisational units.
#
# Be careful, authorizations are still done based on the content of rudder-user.xml,
# meaning that each user should have access to Rudder MUST have a line in that file.
# Without that line, the user can have a successful LDAP authentication, but
# won't be able to do or see anything in Rudder (only logout).
#

# === EXAMPLE / ldapsearch test===
#
# With the example data below, if the user "jon.doe" try to login with password "mypasswd",
# the corresponding `ldapsearch` request are:
#
# 1/ search for user with `service` login:
# ----
# $ ldapsearch -LLL -o ldif-wrap=no -h ldap.mycorp.com -p 389 -x -D "cn=rudder,ou=services,dc=mycorp,dc=com" -w secret -b "ou=Users,dc=mycorp,dc=com" -s sub '(&(cn=jon.doe)(objectclass=person))' 1.1
#
#  dn: cn=jon.doe,ou=Paris,ou=Users,dc=mycorp,dc=com
# ----
#
# Errors and unexpected:
# - an authentication error here means that your rudder service user does not have the
#   rights to do a search and will not be able to find the corresponding user full DN;
# - you should get exactly one result: the DN to use in the second request. If you don't
#   get any results, check the base DN and the LDAP filter.
#
# 2/ bind request with user DN (search user own entry with its credentials):
# ----
# $ ldapsearch -LLL -o ldif-wrap=no -h ldap.mycorp.com -p 389 -x -D "cn=jon.doe,ou=Paris,ou=Users,dc=mycorp,dc=com" -w mypasswd -b "cn=jon.doe,ou=Paris,ou=Users,dc=mycorp,dc=com" -s base 1.1
#
# dn: cn=jon.doe,ou=Paris,ou=Users,dc=mycorp,dc=com
# ----
#
# Errors and unexpected:
# - an authentication error here is likely to mean that the user password is not correct,
#   but you should also check your LDAP directory ACLs.
#

#
# Connection URL to the LDAP server, in the form:
# ldap://hostname:port/base_dn
#
rudder.auth.ldap.connection.url=ldap://ldap.mycorp.com:389/dc=mycorp,dc=com

#
# Bind DN used by Rudder to do the search. This is the "service" or
# "application" DN for Rudder in you LDAP directory, or an LDAP user with
# enough rights to be able to walk the user branch configured below.
# LDAP dn, no default value.
# Be careful to not add quote around the DN, the value is used as provided.
#
rudder.auth.ldap.connection.bind.dn=cn=rudder,ou=services,dc=mycorp,dc=com

#
# Bind password used by Rudder service (the DN configured just above) to do the search.
# String, no default value.
#
rudder.auth.ldap.connection.bind.password=secret

#
# If your directory uses remote links that need to be dereferenced
# for resolving the actual entry, for example in the case of an
# AD forest, you need to uncomment the following option.
#
# rudder.auth.ldap.connection.derefLink=true

#
# Search base and filter to use to find the user.
# The search base can be left empty. In that
# case, the root of directory is used.
#
rudder.auth.ldap.searchbase=ou=People

#
# In the filter, {0} denotes the value provided as
# login by the user.
# The filter must lead to at most one result, which
# will be used to try the (re)bind request.
#
rudder.auth.ldap.filter=(&(uid={0})(objectclass=person))

#
# An AD example would be:
#
#rudder.auth.ldap.searchbase=
#rudder.auth.ldap.filter=(&(sAMAccountName={0})(objectclass=user))

---- end of ldap authentication properties to copy ----

LDAP backend logger

In addition to the common loggers, LDAP backend use the org.springframework.security.ldap namespace. You can configure the corresponding logger in /opt/rudder/etc/logback.xml at debug or trace level by adding the line:

<logger name="org.springframework.security.ldap" level="trace" />

This will lead to trace looking like the following in the different case of errors/success/

LDAP/AD server not reachable

When the LDAP server configured in rudder.auth.ldap.connection.url is not reachable, you will get (be careful, it starts like the base for bad DN/password for service account):

[2023-08-21 16:14:53+0200] DEBUG org.springframework.security.ldap.authentication.BindAuthenticator - Failed to bind with any user DNs []
[2023-08-21 16:14:53+0200] TRACE org.springframework.security.ldap.authentication.BindAuthenticator - Searching for user using FilterBasedLdapUserSearch [searchFilter=(&(cn={0})(objectclass=person)); searchBase=ou=Users; scope=subtree; searchTimeLimit=0; derefLinkFlag=false ]
[2023-08-21 16:14:53+0200] TRACE org.springframework.security.ldap.search.FilterBasedLdapUserSearch - Searching for user 'admin', with FilterBasedLdapUserSearch [searchFilter=(&(cn={0})(objectclass=person)); searchBase=ou=Users; scope=subtree; searchTimeLimit=0; derefLinkFlag=false ]
[2023-08-21 16:14:54+0200] INFO  application - Rudder authentication attempt for principal 'admin' with backend 'ldap': failure
[2023-08-21 16:14:54+0200] ERROR org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - An internal error occurred while trying to authenticate the user.
org.springframework.security.authentication.InternalAuthenticationServiceException: nested exception is javax.naming.CommunicationException [Root exception is java.io.IOException: connection closed]
	at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:190)
	at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:79)
	at bootstrap.liftweb.RudderAuthenticationProvider.authenticate(AppConfigAuth.scala:701)
	at bootstrap.liftweb.RudderProviderManager.authenticate(RudderProviderManager.java:116)
....
Caused by: org.springframework.ldap.CommunicationException: nested exception is javax.naming.CommunicationException [Root exception is java.io.IOException: connection closed]
	at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:108)
	at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:363)
....
Caused by: java.io.IOException: connection closed
	at java.naming/com.sun.jndi.ldap.LdapClient.ensureOpen(LdapClient.java:1598)
   ...
[2023-08-21 16:14:54+0200] WARN  application - Login authentication failed for user 'admin' from IP '127.0.0.1': nested exception is javax.naming.CommunicationException [Root exception is java.io.IOException: connection closed]

Bad DN or bad password for service account

When parameter rudder.auth.ldap.connection.bind.dn (DN for service account) or parameter rudder.auth.ldap.connection.bind.password (password for service account) is incorrect, you will get something like (be careful, it starts like the previous case for server unreachable):

[2023-08-21 15:43:49+0200] DEBUG org.springframework.security.ldap.authentication.BindAuthenticator - Failed to bind with any user DNs []
[2023-08-21 15:43:49+0200] TRACE org.springframework.security.ldap.authentication.BindAuthenticator - Searching for user using FilterBasedLdapUserSearch [searchFilter=(&(cn={0})(objectclass=person)); searchBase=ou=Users; scope=subtree; searchTimeLimit=0; derefLinkFlag=false ]
[2023-08-21 15:43:49+0200] TRACE org.springframework.security.ldap.search.FilterBasedLdapUserSearch - Searching for user 'alice', with FilterBasedLdapUserSearch [searchFilter=(&(cn={0})(objectclass=person)); searchBase=ou=Users; scope=subtree; searchTimeLimit=0; derefLinkFlag=false ]
[2023-08-21 15:43:49+0200] INFO  application - Rudder authentication attempt for principal 'alice' with backend 'ldap': failure
[2023-08-21 15:43:49+0200] ERROR org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter - An internal error occurred while trying to authenticate the user.
org.springframework.security.authentication.InternalAuthenticationServiceException: [LDAP: error code 49 - Invalid Credentials]; nested exception is javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]
	at org.springframework.security.ldap.authentication.LdapAuthenticationProvider.doAuthentication(LdapAuthenticationProvider.java:190)
	at org.springframework.security.ldap.authentication.AbstractLdapAuthenticationProvider.authenticate(AbstractLdapAuthenticationProvider.java:79)
	....
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:938)
	at java.base/java.lang.Thread.run(Thread.java:1589)
Caused by: org.springframework.ldap.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]; nested exception is javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]
	at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:191)
	....
    at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:351)
	... 63 common frames omitted
[2023-08-21 15:43:49+0200] WARN  application - Login authentication failed for user 'alice' from IP '127.0.0.1': [LDAP: error code 49 - Invalid Credentials]; nested exception is javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]

Bad login name (in login page)

This case is less visibly an error: we see in the log that Rudder tries ldap but has a failure and switch to next configured backend.

[2023-08-21 16:19:08+0200] DEBUG org.springframework.security.ldap.authentication.BindAuthenticator - Failed to bind with any user DNs []
[2023-08-21 16:19:08+0200] TRACE org.springframework.security.ldap.authentication.BindAuthenticator - Searching for user using FilterBasedLdapUserSearch [searchFilter=(&(cn={0})(objectclass=person)); searchBase=ou=Users; scope=subtree; searchTimeLimit=0; derefLinkFlag=false ]
[2023-08-21 16:19:08+0200] TRACE org.springframework.security.ldap.search.FilterBasedLdapUserSearch - Searching for user 'Bob', with FilterBasedLdapUserSearch [searchFilter=(&(cn={0})(objectclass=person)); searchBase=ou=Users; scope=subtree; searchTimeLimit=0; derefLinkFlag=false ]
[2023-08-21 16:19:08+0200] TRACE org.springframework.security.ldap.SpringSecurityLdapTemplate - Searching for entry under DN 'cn=rudder-configuration', base = 'ou=Users', filter = '(&(cn={0})(objectclass=person))'
[2023-08-21 16:19:08+0200] INFO  application - Rudder authentication attempt for principal 'Bob' with backend 'ldap': failure
[2023-08-21 16:19:09+0200] INFO  application - Rudder authentication attempt for principal 'Bob' with backend 'file': failure
[2023-08-21 16:19:09+0200] WARN  application - Login authentication failed for user 'Bob' from IP '127.0.0.1': Bad credentials

Bad password for user (in login page)

[2023-07-28 12:00:07+0200] TRACE org.springframework.security.ldap.authentication.BindAuthenticator - Searching for user using FilterBasedLdapUserSearch [searchFilter=(&(cn={0})(objectclass=person)); searchBase=ou=Users; scope=subtree; searchTimeLimit=0; derefLinkFlag=false ]
[2023-07-28 12:00:07+0200] TRACE org.springframework.security.ldap.search.FilterBasedLdapUserSearch - Searching for user 'alice', with FilterBasedLdapUserSearch [searchFilter=(&(cn={0})(objectclass=person)); searchBase=ou=Users; scope=subtree; searchTimeLimit=0; derefLinkFlag=false ]
[2023-07-28 12:00:07+0200] TRACE org.springframework.security.ldap.SpringSecurityLdapTemplate - Searching for entry under DN 'cn=rudder-configuration', base = 'ou=Users', filter = '(&(cn={0})(objectclass=person))'
[2023-07-28 12:00:07+0200] DEBUG org.springframework.security.ldap.SpringSecurityLdapTemplate - Found DN: cn=alice,ou=Users
[2023-07-28 12:00:07+0200] DEBUG org.springframework.security.ldap.search.FilterBasedLdapUserSearch - Found user 'alice', with FilterBasedLdapUserSearch [searchFilter=(&(cn={0})(objectclass=person)); searchBase=ou=Users; scope=subtree; searchTimeLimit=0; derefLinkFlag=false ]
[2023-07-28 12:00:07+0200] TRACE org.springframework.security.ldap.authentication.BindAuthenticator - Attempting to bind as cn=alice,ou=Users,cn=rudder-configuration
[2023-07-28 12:00:07+0200] TRACE org.springframework.security.ldap.DefaultSpringSecurityContextSource - Removing pooling flag for user cn=alice,ou=Users,cn=rudder-configuration
[2023-07-28 12:00:07+0200] TRACE org.springframework.security.ldap.authentication.BindAuthenticator - Failed to bind as cn=alice,ou=Users
org.springframework.ldap.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]; nested exception is javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]
	at org.springframework.ldap.support.LdapUtils.convertLdapException(LdapUtils.java:191)
	at org.springframework.ldap.core.support.AbstractContextSource.createContext(AbstractContextSource.java:363)
    ...

Using a certificate for secure connection to LDAP/AD

If you want to connect with a secure connection to an LDAP or AD, you need to add the directory certificate to Rudder’s JVM keystore.

Without that, you will see errors in /var/log/rudder/webapp/XXXXXXX_stderrout.log files like:

WARN  application - Login authentication failed for user 'xxx' from IP '127.0.0.1|X-Forwarded-For:xxx.xxx.xxx.xxx': simple bind failed: xxx.xxx:636; nested exception is javax.naming.CommunicationException: simple bind failed:

xxx.xxx:636 [Root exception is java.net.SocketException: Connection or outbound has closed]

Adding certificate to JVM keystore

# copy the certificate somewhere in /opt/rudder

cd path/to/jdk<in-use-version>/lib/security

keytool -importcert -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias "rudder-ldap-certificate" -file <path to AD server certificate>

Error because certificate is 1024 bits

Since JVM version 8, certificate of size 1024 or less are forbidden by default. If you still use a certificate with that size, you will get errors like:

Root exception is javax.net.ssl.SSLHandshakeException: PKIX path validation failed: java.security.cert.CertPathValidatorException: Algorithm constraints check failed on keysize limits: RSA 1024 bit key used with certificate

To correct that problem, you need to remove that restriction (and update your certificates for security):

  • edit path/to/jdk<in-use-version>/conf/security/java.security

  • check constraints on RSA keysize like RSA keySize < 1024 and change them to match your key size for properties:

  • jdk.tls.disabledAlgorithms

  • jdk.certpath.disabledAlgorithms

  • restart rudder-jetty

OAUTHv2 / OpenID Connect (OIDC)

OpenID Connect (OIDC) is a very common SSO protocol to authenticate and manage authorizations of users in a decentralized, multi-tenant set-up (ie, typically web applications nowadays). It’s built on top of OAUTHv2 and replace it in most new cases.

These protocols delegate the actual authentication to an identity provider (IdP) that in turns send the relevant authentication information to the client, i.e. to Rudder in our case. These IdP can be public providers, like Google, deployed and managed internally in a company, like ForgeRock’s open source OpenAM, or used as SaaS, like Okta - and often, providers do a mix of these things.

Rudder support plain old OAUTHv2 and OpentID Connect. They have several normalized scenario and Rudder supports the most common for a web application server side authentication: Authentication using Authorization Code Flow.

We advise using OIDC over OAuth 2.0 if possible.

To use these providers, you need to update the rudder.auth.provider property with the oauth2 value for an OAuth 2.0 identity provider, and with the oidc value for an OpenID Connect identity provider.

As always, you can have several back-ends configured for fall-back authentication. For example, to use OIDC with a fall-back to the Rudder file based authentication, use:

rudder.auth.provider = oidc, file

You can configure several providers at the same time. The are defined by an identifier in a comma-separated list in the following property:

rudder.auth.oauth2.provider.registrations=okta,google

Each provider needs to then have a bunch of properties defined for it. They are listed below and all follow the pattern rudder.auth.oauth2.provider.${providerID}.${subPath} where `providerId is the ID in the previous list, and subPath is the remaining name of the property.

We advise to configure each provider in its own configuration file under /opt/rudder/etc/rudder-web.properties.d so that it is easier to change or disable some of them.

IdP-provided authorisations for Rudder users

You can configure an OAuth2 or OIDC provider so that it informs Rudder of the roles the user need to have. This allows to centrally manage both user and authorisation in the same place.

This feature works with the custom roles feature provided by the user-management plugin. Please see that linked documentation to understand how custom roles work in Rudder.

Unitary rights like node_all, technique_read, rule_write etc are not supported to describe a user’s authorisations through OIDC. It must be a pre-defined role or a custom role

You need three additional properties to enable and configure that property for a given OIDC provider: - the first, roles.enabled allows to enable the feature, - the second, roles.attribute defines the name of the OIDC token attribute which holds the list of roles, - the third, roles.override defines if the OIDC provided roles must be the only one the user get, or if they are merged with the rudder-users.xml ones.

See the example configuration file below for details about these property values.

IdP provisioning for Rudder users

You can configure an OAuth2 or OIDC provider so that users that are correctly authenticated with it can be automatically created in Rudder. This allows to avoid changing rudder-users.xml file. By default, user provisioned by that way don’t have any rights. You will need to also configure roles provisioning through your IdP (see previous section).

To allow IdP provisioning of users, set property enableProvisioning to true (default false).

See the example configuration file below for details about that property.

Example configuration for okta provider

In this section, we use okta as OIDC provider, and we chose the name okta to identify that provider in Rudder configuration file.

We chose this OIDC provider because it provides freely available extensive documentation and testing platform. This can be useful since OAUTHv2/OpenID Connect configuration can be a bit complicated and full of jargon.

In the remaining part of this section, you will need to change okta by the name you chose to identify your OIDC provider in Rudder.

You can copy the following example into /opt/rudder/etc/rudder-web.properties.d/30-oidc-okta-authentication.properties.

# Authentication provider id in rudder.auth.provider:
# - OAUTHv2       : oauth2
# - OpenID Connect: oidc

# Configure the list of Identity provider services. Here, you choose
# an identifier for each service as a comma separated list.
# Identifier should be lower case ascii, -, _. For example, if
# your company uses both "Okta" and "Google", you can choose "okta" and
# "google" (how original) identifiers:
rudder.auth.oauth2.provider.registrations=okta,google

# Now, configure Okta related properties. You will need to do
# the same for each provider with an identifier.

# The identity service provider name as it will be displayed in Rudder
rudder.auth.oauth2.provider.okta.name=Okta
# A more detailed explanation message displayed in authentication page.
rudder.auth.oauth2.provider.okta.ui.infoMessage=OpenID Connect SSO (Okta)

# In Oauth2/OIDC, a client (ie, Rudder) is identifier by a pair of credentials:
# - 1/ an id,
# - 2/ a corresponding secret key.
#
# 1/ Identifier of the application you created in your IdP for Rudder.
#    In Okta, it will be listed under https://xxxx-admin.okta.com/admin/apps/active
#    once you created it with "Create App Integration". If you click on your application,
#    it's located in "Client Credential > Client ID".
#
rudder.auth.oauth2.provider.okta.client.id=0oa3snkopsIRIIHb35d7
#
# 2/ The corresponding "client secret", provided by your Identity Provider.
#    For Okta, it's available when you click on your application in
#    https://xxxx-admin.okta.com/admin/apps/active in "Client Credential > Client Secret"
rudder.auth.oauth2.provider.okta.client.secret=-0Q5jGbdvV5WkfGNJwHfkOP0FdZ5vhqPYav7icYb
#
# Space separated list of OAUTHv2 "scope" for claims that should be included in the identity
# token once authentication is done. These values should be documented by your IdP documentation.
# Rudder only need to have at least scope which provides the attribute that will be used for
# `userId` (see next property)
rudder.auth.oauth2.provider.okta.scope=openid  email profile
#
# The attribute that will be used for `userId` and login matching with rudder users
# (generally, it's a login or email ; OIDC always provides at least `sub` attribute)
# The value of that attribute will be used to retrieved Rudder internal user, its rights, etc.
rudder.auth.oauth2.provider.okta.userNameAttributeName=email
#
# The next 4 URLs are the redirection URLs towards the IdP and which corresponds to
# each step of the authentication process (yes, the protocol does a lot of redirection):
# - `uri.auth`: first URL, Rudder ask for a code request. User is then redirected by
#    the IdP towards its own login form. It then redirect to Rudder with a code to process.
#    If you need to use extra information like an `acr_values` property, just happen it to that URL
# - `uri.token`: Rudder returned the code processed with its client secret. The IdP process it
     and return an authentication token to Rudder.
# - `uri.userInfo`: Rudder uses the authentication token to get user information on that URL
# - `uri.jwkSet`: in the case of OIDC, the token is a signed JWT token. That last url is the
#   URL where Rudder can get the IdP public key to sign the token.
rudder.auth.oauth2.provider.okta.uri.auth=https://xxxx.okta.com/oauth2/v1/authorize
# With an acr_values:
#rudder.auth.oauth2.provider.okta.uri.auth=https://xxxx.okta.com/oauth2/v1/authorize?acr_values=strongAuthRequired
rudder.auth.oauth2.provider.okta.uri.token=https://xxxx.okta.com/oauth2/v1/token
rudder.auth.oauth2.provider.okta.uri.userInfo=https://xxxx.okta.com/oauth2/v1/userinfo
rudder.auth.oauth2.provider.okta.uri.jwkSet=https://xxxx.okta.com/oauth2/v1/keys
#
# Rudder URL towards which the identity provider redirects, ie the URL seen by the IdP
# for Rudder. Apart if directed to do differently, you should keep the
# part after `rudder`, ie: `/login/oauth2/code/{registrationId}` part.
rudder.auth.oauth2.provider.okta.client.redirect=https://my-external-rudder-hostname/rudder/login/oauth2/code/{registrationId}
#
#
# The following properties are necessary for each provider configuration but should not be modified.
#
# The protocol scheme used for authentication - Rudder only supports with authorisation code.
rudder.auth.oauth2.provider.okta.grantType=authorization_code
# Authentication type - Rudder only supports client_secret_basic and client_secret_post.
rudder.auth.oauth2.provider.okta.authMethod=client_secret_basic

#
# Properties to configure roles and users provisioning through the OIDC token
#
# enable Rudder user role provisioning by the OIDC IdP. Use `true` or `false` (default)
rudder.auth.oauth2.provider.okta.roles.enabled=true

# Name of the OIDC token attribute that will hold rudder roles. This is something that you identity provider
# administrator will give you. The attribute value must be a OAuth list of string, ie in the format:
#  attribute: [role-oidc-a, role-oidc-b, etc]
# Each string will be mapped to a rudder role (or ignored if no matching is found). Default value: empty.
rudder.auth.oauth2.provider.okta.roles.attribute=rudderroles

# Define if the provided list of roles should *override* or *be appended to* the list of roles configured for
#the user in the `rudder-users.xml` file. Use `false` for append (default), `true` for override.
rudder.auth.oauth2.provider.okta.roles.override=true

# Mapping between IdP role name ("entitlements") and Rudder internal naming scheme.
#
# It is common for the IdP to use its own naming scheme, or to have several IdP using
# different naming incompatible naming scheme for roles. The following property allows
# to map an IdP entitlement into a rudder role name (custom or pre-defined)
#
# Unitary right like `node_all` `rule_read` `technique_write` cannot be mapped.
# If none of the pre-defined role suits you, please create a custom role to be able to map it.
# see https://docs.rudder.io/reference/8.1/plugins/user-management.html#_custom_roles
#
# Check the list of pre-defined roles: https://docs.rudder.io/reference/8.1/plugins/user-management.html#_pre_defined_roles
rudder.auth.oauth2.provider.okta.roles.mapping.entitlements.rudder_admin=administrator
rudder.auth.oauth2.provider.okta.roles.mapping.entitlements.rudder_readonly=readonly
# You can restrict the role that The IdP can assign to only role mapped to entitlements.
# When the following properties is true, roles that don't appear in `mapping.entitlements`
# will be filtered-out.
rudder.auth.oauth2.provider.okta.roles.mapping.enforced=true
# In some case, you OIDC provided roles will contains illegal character that can't be use in the
# left part of the `entitlement` key - typically an equal. You can reverse the order of mapping with
# the `reverseEntitlements`, in whicn the Rudder role name is on the left and the OIDC IdP role
# name is on the right. If the same key is defined in both `entitlements` and `reverseEntitlements`,
# then the value defined in `reverseEntitlements` is used.
# In the following example, OIDC role `rudder_readonly` will be mapped to local `readonly2` role,
# overriding the value previously defined above:
#rudder.auth.oauth2.provider.okta.roles.mapping.reverseEntitlements.readonly2=rudder_readonly
# And here, we map the IdP role "name=Alice,ou=users" to Rudder role "readonly"
#rudder.auth.oauth2.provider.okta.roles.mapping.reverseEntitlements.readonly=name=Alice,ou=users

# enable Rudder user provisioning by the OIDC IdP. Use `true` or `false` (default).
# Users provisioned through that channel don't have roles, you will need to also
# provisioned roles thanks to IdP.
rudder.auth.oauth2.provider.okta.enableProvisioning=true

Log information

OIDC and OAuth2 protocols may become complicated to configure, especially for the scopes part, when you need to match an attribute with Rudder login base. You can use the log level for auth-backends in /opt/rudder/etc/logback.xml:

  • debug to see which attributes are actually returned into the user info token,

  • and trace to also see their values.

Common Oauth2/OIDC error cases

It can be a bit challenging to understand what is not correct in an Oauth2 or OIDC configuration. Here are some guidelines to help address possible configuration problems.

I don’t see the list of Identity Provider in login form

Check that you correctly updated parameter rudder.auth.provider to include oidc or oauth2 in the list, that you have at least one key defined in rudder.auth.oauth2.provider.registrations, and that you have Rudder webapp logs (/var/log/rudder/webapp/YYYY_mm_dd.stderrout.log) lines like:

[timestamp] INFO  application - Configured authentication provider(s): [rootAdmin, oidc, file]
[timestamp] INFO  application - Add backend providers 'Oauth2 and OpenID Connect authentication backends provider: 'oauth2','oidc'
[timestamp] INFO  application.plugin - Oauthv2 or OIDC authentication backend is enabled, updating login form

I get a 404 page not found on Identity Provider

Check with your Identity Provider Manager that the URL for rudder.auth.oauth2.provider.${registrationKey}.uri.auth is correct.

I get a 400 bad request on Identity Provider

If when you click in Rudder login page to the IdP link and that you get an error 400 "bad request", the application code for Rudder is not correct, and so Rudder identity is not recognized by the IdP. Check with your IdP provider the application code for Rudder and check that that value is correctly set for property rudder.auth.oauth2.provider.${registrationKey}.client.id

After login on Identity Provider, I get a "login error" message in Rudder login page

This can have several cause, and we will need to analyse Rudder log to understand what happened.

Bad token URL

In the log, you see (exact error code or ID may vary, check invalid_token_response and The endpoint does not support the provided HTTP method):

[timestamp] DEBUG auth-backends - Processing OAuth2/OIDC authorization to: https://identity-provider-url/oauth2/v1/authorize
[timestamp] DEBUG auth-backends - Processing OAuth2/OIDC authorisation validation and starting authentication request
[timestamp] WARN  application - Login authentication failed for user 'unknown' from IP '127.0.0.1': [invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: 405 Method Not Allowed: "{"errorCode":"E0000022","errorSummary":"The endpoint does not support the provided HTTP method","errorLink":"E0000022","errorId":"oaeLqoJpDbwTzOTAJhp9TbVig","errorCauses":[]}"

Check with you Identity Provider Manager the value for rudder.auth.oauth2.provider.${registrationKey}.uri.token.

Bad user info URL

In the log, you see (exact error code or ID may vary, check invalid_user_info_response and The endpoint does not support the provided HTTP method):

[timestamp] DEBUG auth-backends - Processing OAuth2/OIDC authorization to: https://identity-provider-url/oauth2/v1/authorize
[timestamp] DEBUG auth-backends - Processing OAuth2/OIDC authorisation validation and starting authentication request
[timestamp] WARN  application - Login authentication failed for user 'unknown' from IP '127.0.0.1': [oauth2:invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 405 Method Not Allowed: "{"errorCode":"E0000022","errorSummary":"The endpoint does not support the provided HTTP method","errorLink":"E0000022","errorId":"oae1TIF6av1QOiox05xkUSkww","errorCauses":[]}"

Bad JWK (keys) URL

In the log, you see (exact error code or ID may vary, check invalid_id_token and The endpoint does not support the provided HTTP method):

[timestamp] DEBUG auth-backends - Processing OAuth2/OIDC authorization to: https://identity-provider-url/oauth2/v1/authorize
[timestamp] DEBUG auth-backends - Processing OAuth2/OIDC authorisation validation and starting authentication request
[timestamp] WARN  application - Login authentication failed for user 'unknown' from IP '127.0.0.1': [invalid_id_token] An error occurred while attempting to decode the Jwt: Couldn't retrieve remote JWK set: org.springframework.web.client.HttpClientErrorException$MethodNotAllowed: 405 Method Not Allowed: "{"errorCode":"E0000022","errorSummary":"The endpoint does not support the provided HTTP method","errorLink":"E0000022","errorId":"oae6_QrhU-UTWeykOHgyHqbuA","errorCauses":[]}"

Bad application secret or method

In the log, you see:

[timestamp] DEBUG auth-backends - Processing OAuth2/OIDC authorization to: https://identity-provider-url/oauth2/v1/authorize
[timestamp] DEBUG auth-backends - Processing OAuth2/OIDC authorisation validation and starting authentication request
[timestamp] WARN  application - Login authentication failed for user 'unknown' from IP '127.0.0.1': [invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: 401 Unauthorized: [no body]

This likely means that the value of rudder.auth.oauth2.provider.${registrationKey}.client.secret is incorrect. Please check with your Identity Provider manager to get the correct one.

It could also mean that your Identity Provider only support the client_secret_post authentication method. You can try to change rudder.auth.oauth2.provider.okta.authMethod to that value.

User attribute unknown

In the log, you see:

[timestamp] DEBUG auth-backends - Processing OAuth2/OIDC authorization to: https://identity-provider-url/oauth2/v1/authorize
[timestamp] DEBUG auth-backends - Processing OAuth2/OIDC authorisation validation and starting authentication request
[timestamp] DEBUG auth-backends - OAuth2/OIDC user info request with scopes [email openid profile] returned attributes: email, email_verified, family_name, given_name, locale, name, nickname, preferred_username, sub, updated_at, zoneinfo
[timestamp] WARN  application - Login authentication failed for user 'unknown' from IP '127.0.0.1': [oauth2:invalid_user_info_response] Missing attribute 'foo' in attributes

You used an attribute for value rudder.auth.oauth2.provider.${registrationKey}.userNameAttributeName that is not returned with the user profile. Please check rudder.auth.oauth2.provider.okta.scope with your Identity Provider Manager to ensure that the list of scope is correct, and check that the userNameAttributeName value is in the list of returned attributes.

Incorrect user attribute

In the log, you see:

[timestamp] DEBUG auth-backends - Processing OAuth2/OIDC authorization to: https://identity-provider-url/oauth2/v1/authorize
[timestamp] DEBUG auth-backends - Processing OAuth2/OIDC authorisation validation and starting authentication request
[timestamp] DEBUG auth-backends - OAuth2/OIDC user info request with scopes [email openid profile] returned attributes: email, email_verified, family_name, given_name, locale, name, nickname, preferred_username, sub, updated_at, zoneinfo
[timestamp] WARN  application - Login authentication failed for user 'unknown' from IP '127.0.0.1': User with username 'foo' was not found

It means that the value used for rudder.auth.oauth2.provider.${registrationKey}.userNameAttributeName was correctly returned in the profile list for the authenticated user, but that value was not found in Rudder user configuration files /opt/rudder/etc/rudder-users.xml. Check that one of the entries in that file has the corresponding value for its name attribute.

User role unknown

In the log, you see:

[timestamp] TRACE auth-backends - IdP configuration has registered role mapping: [(role-oidc-a,node_all)]
[timestamp] DEBUG auth-backends - Principal 'toto@acme.com': mapping IdP provided role 'role-oidc-a' to Rudder role 'node_all'
[timestamp] DEBUG auth-backends - Role 'role-oidc-a' does not match any Rudder role, ignoring it for user toto@acme.com

It means that the role node_all is not recognized. It is because it is not a ref:plugins:user-management.adoc#_pre_defined_roles[pre-defined role] or a custom role

In this case you should create a custom role (let’s say access_to_node) with the permission node_all that you will map to your IdP role role-oidc-a and modifying the parameter mapping.entitlements in the OIDC config file like so: rudder.auth.oauth2.provider.okta.roles.mapping.entitlements.role-oidc-a=access_to_node


← API authorizations Branding →