Install and enable confluence_http_authenticator by Joao Silva is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.
Based on a work at https://gist.github.com/jpmsilva/6f7ccdc8421d42eeab50d8ff19cdbb18.
These are the steps taken to enable authentication in Confluence by way of an OIDC compliant IdP.
These steps were tested with the following bill of materials:
- Atlassian Confluence 7.8
- Keycloak 11 (https://www.keycloak.org/)
- oauth2-proxy 7 (https://github.com/oauth2-proxy/oauth2-proxy)
The main focus of this article is on how to enable SSO in Confluence via oauth2/OpenID Connect. As such, the installation of Keycloak 11, the setup of a realm and the installation of oauth2-proxy will not be covered.
For our specific use-case, Keycloak was set up with user federation from the corporate LDAP.
Confluence was also configured with a user directory to read from the same LDAP, so that the same users will exist on both systems. In addition, Confluence will read groups and group memberships from LDAP, allowing us to create rich ACL models in Confluence.
+--------------------------+ http +---------------------+
| +------------->| Keycloak node 1 |
https | Keycloak | +---------------------+
+-------->| Load balancer/web server | ...
| | SSL/TLS termination | http +---------------------+
+------+ | | kb.example.org +------------->| Keycloak node x |
| +--------+ +--------------------------+ +---------------------+
| User |
| +--------+ +--------------------------+ http +---------------------+ http +--------------------------+ http +---------------------+
+------+ | | +------------->| oauth2-proxy node 1 +------------->| +------------->| Confluence node 1 |
| | oauth2-proxy | +---------------------+ | Confluence | +---------------------+
+-------->| Load balancer/web server | ... | Load balancer/web server | ...
https | SSL/TLS termination | http +---------------------+ http | | http +---------------------+
| id.example.org +------------->| oauth2-proxy node x +------------->| confluence.example.org +------------->| Confluence node x |
+--------------------------+ +---------------------+ +--------------------------+ +---------------------+
oauth2-proxy is a reverse proxy solution that will only allow request to be forwarded to the backend if a valid oauth2 access token is presented. If no such token is presented, a browser based oauth2 authentication flow will be triggered.
oauth2-proxy will ensure that requests are only forwarded to the upstream Confluence service if the client has been authenticated.
Note, though, that with the configuration presented here, oauth2-proxy only checks if a valid access token exists. It performs no other access control checks itself, even though it could also do group or role checks if needed. Access control is delegated entirely on Confluence.
The various pieces of the architecture (Confluence, Keycloak and oauth2-proxy) may be redundant. For such cases, load balancers may be required.
For security purposes it is assumed that at least the user facing components are exposed via https. SSL/TLS termination may be put in place, and the remaining communications can be over http, assuming they happen within a secure perimeter.
It SSL/TLS is not used at all, make sure to configure session cookies to not have the Secure flag. Each component uses their own type of session cookies.
Variables to change as needed:
-
https://kb.example.org
: the URL from which Confluence will be made available to end users, pointing to the oauth2-proxy load balancer (or directly to the service if only one node). -
https://id.example.org
: the URL from which Keycloak will be made available to end users, pointing to the Keycloak load balancer (or directly to the service if only one node). -
http://confluence.example.org
: the URL pointing directly to the Confluence load balancer (or directly to the service if only one node). -
corporaterealm
: the oauth2 realm, defined in Keycloak. -
confluence-client-id
: the JWT Client ID, defined in Keycloak. -
confluence-secret
: the JWT Secret, defined in Keycloak (treat it as a secret). -
averylongstringofsecurecharater
: a secret to encrypt oauth2-proxy cookies (make it a 32 character random string and treat it as a secret). -
$CONFLUENCE_HOME
the folder where Confluence was installed.
-
Access your Keycloak realm config and create a client. Take note of the Client ID (
confluence-client-id
). -
Configure the client with Access Type confidential.
-
Configure the Valid Redirect URIs with the public facing URL of your Confluence setup as
https://kb.example.org/oauth2/callback
. -
From the Credentials tab take note of the secret (
confluence-secret
).
- The following is the sample configuration for oauth2-proxy. Adjust to your needs as documented in
https://oauth2-proxy.github.io/oauth2-proxy/docs/configuration/overview/#config-file. Just take care regarding
the changes between CLI arguments and the respective configuration variables (such as
--client-id
becomesclient_id
).
provider = "oidc"
client_id = "confluence-client-id"
client_secret = "confluence-secret"
oidc_issuer_url = "https://id.example.org/auth/realms/corporaterealm"
email_domains = [ "*" ]
cookie_secret = "averylongstringofsecurecharater"
http_address = "http://:4180"
scope = "openid"
redirect_url = "https://kb.example.org/oauth2/callback"
reverse_proxy = "True"
cookie_secure = "True"
upstreams = [ "http://confluence.example.org/" ]
skip_provider_button = "True"
real_client_ip_header = "X-Forwarded-For"
skip_auth_regex = "^\\/((rest\\/token-auth\\/api\\/)|(download\\/token-auth\\/attachments\\/)|(plugins\\/servlet\\/imgFilter)|(rest\\/analytics\\/1.0\\/publish\\/bulk)|(s)|(download\\/attachments)|(rest\\/shortcuts\\/latest\\/shortcuts)|(rest\\/quickreload\\/latest)|(rest\\/webResources\\/1\\.0\\/resources)|(rest\\/gadgets\\/1\\.0\\/g\\/messagebundle)|(rest\\/nativemobile\\/1\\.0\\/info\\/)).*"
pass_basic_auth = "True"
pass_user_headers = "True"
This configuration may require adjustments. Notice that there is no configuration for SSL/TLS here, as in this configuration SSL termination is performed in the loadbalancer that sits in front of oauth2-proxy.
oauth2-proxy can also be configured to serve via https, by pointint to the security material in the configuration file. Note that if you don't have SSL/TLS downstream from oauth2-proxy, you may want to set cookie_secure to False.
Also note the property skip_auth_regex. This regex controls the URIs that will be passed directly to Confluence without requiring a valid access token. We did various tests to check everything that we may safely exclude this way. Some are well documented, while others we found by looking at 403 errors while browsing Confluence. Depending on the applications you have installed in Confluence you may require additional exclusions here.
- Launch oauth2-proxy.
If you created the configuration file in
/opt/oauth2-proxy/instances/confluence.cfg
you can run it with/path/to/oauth2-proxy --config=/opt/oauth2-proxy/instances/confluence.cfg
.
-
Download remoteUserAuth-2.7.3.jar from the available releases at https://github.com/chauth/confluence_http_authenticator/tree/master/releases and copy to
$CONFLUENCE_HOME/confluence/WEB-INF/lib
-
Create the file
$CONFLUENCE_HOME/confluence/WEB-INF/classes/remoteUserAuthenticator.properties
with the following content:local.login.supported=true create.users=false update.info=false update.last.login.date=true reload.config=false reload.config.check.interval=5000 default.roles=confluence-users header.remote_user=X-Forwarded-Preferred-Username header.remote_user.strategy=2 username.convertcase=true username.filter=CN=([A-Za-z0-9]*) update.roles=false convert.to.utf8=false dynamicroles.auto_create_role=false dynamicroles.output.tolowercase=true
The configuration is taken from the sample provided at https://github.com/chauth/confluence_http_authenticator/blob/master/conf/remoteUserAuthenticator.properties.
You should change it to better suite your needs. In our case, since we use LDAP as a read-only source of user information, we don't want to try to update user information via this plugin.
header.remote_user
defines the header set by oauth2-proxy that contains the username of the authenticated user, which isX-Forwarded-Preferred-Username
.Local logins are allowed in this configuration, but there is really no way to log in using these accounts, as the IdP has no knowledge of them. Instead, we configured a restricted frontend webserver, that talks directly with the Confluence Tomcat server pool. We restrict this frontend to a range of allowed IP addresses. That way we retain the ability to login with a local admin, in the event of issues with the corporate LDAP.
-
Edit the file
$CONFLUENCE_HOME/confluence/WEB-INF/classes/seraph-config.xml
.Comment out the default authenticator, and add the
confluence_http_authenticator
authenaticator:<!-- Default Confluence authenticator, which uses the configured user management for authentication. --> <!-- <authenticator class="com.atlassian.confluence.user.ConfluenceAuthenticator"/> --> <!-- Custom authenticators appear below. To enable one of them, comment out the default authenticator above and uncomment the one below. --> <!-- Authenticator with support for Crowd single-sign on (SSO). --> <!-- <authenticator class="com.atlassian.confluence.user.ConfluenceCrowdSSOAuthenticator"/> --> <!-- Specialised version of the default authenticator which adds authenticated users to confluence-users if they aren't already a member. --> <!-- <authenticator class="com.atlassian.confluence.user.ConfluenceGroupJoiningAuthenticator"/> --> <authenticator class="shibauth.confluence.authentication.shibboleth.RemoteUserAuthenticator"/>
-
Restart Confluence
This step assumes that there is a frontend load balancer/web server in the architecture that acts as SSL/TLS termination for end
users to access the service. The URL https://kb.example.org
is served by this service.
If you set up oauth2-proxy to serve directly to your end users (with or without SSL/TLS) this step is not needed.
Change the backend configuration of https://kb.example.org
to point to the oauth2-proxy
backends instead of the Confluence backends.
If all goes well, when you access https://kb.example.org
you will now be redirected to
https://id.example.org
to complete the authentication steps dimmed necessary by the realm.
Once you succesfully complete authentication you will be redirected back to
https://kb.example.org
fully logged in to Confluence.