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:
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
|
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
|
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 |
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
In particular, check that |
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
likeRSA 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 |
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 →