KeyCloak
This is a guide to setting up a new Stroom instance or cluster with KeyCloak as the 3rd party Identity Provider (IDP) Identity Provider (IDP) An Identity Provider is a system or service that can authenticate a user and assert their identity. Identity providers can support single sign on (SSO), which allows the user to sign in once to the Identity Provider so they are then authenticated to all systems using that IDP.Click to see more details.... It assumes you have deployed a new instance or cluster of Stroom and have not yet started it.
See Also
Read External IDP first for what Stroom needs from any provider, and Stroom Configuration for what each setting does.
Note
This page covers Stroom itself being the OIDC client of the realm. If an authenticating reverse proxy (e.g. NGINX with oauth2-proxy) in front of Stroom does the sign in against KeyCloak instead, see NGINX, oauth2-proxy and KeyCloak.
Running KeyCloak
If you already have a KeyCloak instance running then move on to the next section.
This section is not a definitive guide to running or administering KeyCloak. It describes how to run KeyCloak using non-production settings for simplicity and to demonstrate using a 3rd party IDP. You should consult the KeyCloak documentation on how to set up a production ready instance.
The easiest way to run KeyCloak is using Docker. To create a KeyCloak container do the following:
This example maps KeyCloak’s port to port 9999 to avoid any clash with Stroom that also runs on 8080.
This will create a docker container called keycloak that uses an embedded H2 database to hold its state.
To start the container in the foreground, do:
KeyCloak should now be running on
http://localhost:9999/admin
.
If you want to run KeyCloak on a different port then delete the container and create it with a different port for the -p argument.
Log into KeyCloak using the username admin and password admin as specified in the environment variables set in the container creation command above.
You should see the admin console.
Note
The admin console layout and the names of some settings vary between KeyCloak versions. The steps below were written against the version above. On a newer version the same settings may sit under differently named tabs, and the bootstrap admin environment variables have been renamed.Creating a Realm
First you need to create a Realm.
- Click on the drop-down in the left pane that contains the word
master. - Click Create Realm.
- Set the Realm name to
StroomRealm. - Click Create.
Creating a Client
In the new realm click on Clients in the left pane, then Create client.
- Set the Client ID to
StroomClient. - Click Next.
- Set Client authentication to on, which makes this a confidential client.
- Ensure the following are ticked:
- Standard flow
- Direct access grants
- Click Save.
Open the new Client and on the Settings tab set:
- Valid redirect URIs to
https://STROOM_FQDN/api/auth/flow/v1/signin-oidc - Valid post logout redirect URIs to
https://STROOM_FQDN/*
Where STROOM_FQDN is the public address of Stroom, i.e. what you have set as appConfig.publicUri.
Warning
The redirect URI is a single exact value.
Do not use a wildcard such as https://STROOM_FQDN/* for it.
Earlier versions of Stroom sent the user’s current page as the redirect URI and so did need a wildcard here. If you are upgrading, replace it with the exact URI above.
The post logout redirect URI does use a wildcard, because Stroom appends a state parameter to it.
On the Advanced tab, under Advanced settings, set Proof Key for Code Exchange Code Challenge Method to S256.
Stroom always sends a PKCE challenge, so KeyCloak can be told to insist on one.
On the Credentials tab copy the Client secret for use later in Stroom config.
Adding an Audience Mapper
This step matters, and is easy to miss.
By default KeyCloak does not put the client id in the aud claim of the access tokens it issues; typically it puts account there instead.
Stroom validates the audience of every token it is given, so without this step API calls made with a KeyCloak access token are refused.
Interactive sign in still works, because the id_token does carry the client id.
In the realm, click Client scopes in the left pane, then the StroomClient-dedicated scope belonging to the client.
- Click Add mapper => By configuration => Audience.
- Set Name to
stroom-audience. - Set Included Client Audience to
StroomClient. - Ensure Add to access token is on.
- Click Save.
The alternative, if you would rather not change KeyCloak, is to tell Stroom what KeyCloak actually issues:
allowedAudiences:
- "account"
That is weaker, since account is an audience every client in the realm can obtain, so a token minted for another application in the same realm would be accepted by Stroom.
Prefer the mapper.
Creating Users
Click on Users in the left pane then Add user. Set the following:
- Username -
admin - First name -
Administrator - Last name -
Administrator
Click Create.
Select the Credentials tab and click Set password.
Set the password to admin and set Temporary to off.
Note
Standard practice would be for there to be a number of administrators where each has their own identity (in their own name) on the IDP. Each would be granted theAdministrator application permission (directly or via a group).
For this example we are calling our administrator admin.
Repeat this process for the following user:
- Username -
jbloggs - First name -
Joe - Last name -
Bloggs - Password -
password
Configure Stroom for KeyCloak
Edit the config.yml file and set the following values:
receive:
# Set to true to require authentication for /datafeed requests
authenticationRequired: true
# Set to true to allow authentication using an Open ID token
tokenAuthenticationEnabled: true
security:
authentication:
authenticationRequired: true
openId:
# Tells Stroom to use an external IDP for authentication
identityProviderType: EXTERNAL_IDP
# The endpoint to obtain the rest of the IDP's configuration. Specific to the realm/issuer.
openIdConfigurationEndpoint: "http://localhost:9999/realms/StroomRealm/.well-known/openid-configuration"
# The client ID created in KeyCloak
clientId: "StroomClient"
# The client secret copied from KeyCloak above
clientSecret: "XwTPPudGZkDK2hu31MZkotzRUdBWfHO6"
# The URL on the IDP to redirect users to when logging out of Stroom
logoutEndpoint: "http://localhost:9999/realms/StroomRealm/protocol/openid-connect/logout"
# KeyCloak stamps its access tokens with a 'typ' header of 'Bearer'. Requiring it stops an
# id_token being replayed against the API as though it were an access token.
requiredAccessTokenType: "Bearer"
These values are obtained from the IDP. In the case of KeyCloak they can be found by clicking on Realm settings => Endpoints => OpenID Endpoint Configuration and extracting the various values from the JSON response. Alternatively they can typically be found at https://host/.well-known/openid-configuration on any Open ID Connect IDP. The values will reflect the host and port that the IDP is running on along with the name of the realm.
Setting the above values assumes KeyCloak is running on localhost:9999 and the realm name is StroomRealm.
The claim defaults suit KeyCloak, so there is nothing to set for them.
KeyCloak issues preferred_username, which Stroom uses as the display name, and issues name where the user has a first and last name, which satisfies the default fullNameClaimTemplate of ${name}.
Note
Before settingrequiredAccessTokenType, confirm the value your KeyCloak version actually uses by decoding the header of a real access token.
Leave it unset if in doubt; it is a hardening measure rather than a requirement.
Setting up the Admin User in Stroom
Now that the admin user exists in the IDP we need to grant it Administrator rights in Stroom.
In the Users section of KeyCloak click on user admin.
On the Details tab copy the value of the ID field.
The ID is in the form of a
UUID
UUID
A Universally Unique Identifier for uniquely identifying something. UUIDs are used as the identifier in Doc Refs. An example of a UUID is 4ffeb895-53c9-40d6-bf33-3ef025401ad3.Click to see more details....
This ID is the sub claim, which is what Stroom uses to uniquely identify the user and associate it with the identity in KeyCloak.
To set up Stroom with this admin user run the following (before Stroom has been started for the first time):
Where XXX is the user ID copied from the IDP as described above.
This command is repeatable as it will skip any users/groups/memberships that already exist.
See Also
See Command Line Tools for more details on using the manage_users command.
This command will do the following:
- Create the Stroom User by creating an entry in the
stroom_userdatabase table for the IDP’sadminuser. - Ensure that an
Administratorsgroup exists (i.e. an entry in thestroom_userdatabase table for theAdministratorsgroup). - Add the
adminuser to the groupAdministrators. - Grant the application permission
Administratorto the groupAdministrators.
Note
This process is only required to bootstrap the admin user, to allow them to log in with administrator rights and manage the permissions and group memberships of everyone else. It does not need to be done for every user. Whenever a user successfully logs in via the IDP, Stroom will automatically create an entry in thestroom_user table for that user.
The user will have no permissions or group memberships, so these will need to be applied by the administrator.
This does mean that new users will need to log in before the administrator can manage their permissions and memberships.
Logging into Stroom
As the Administrator
Now that the user and permissions have been set up in Stroom, the administrator can log in.
First start the Stroom instance or cluster.
Warning
If themanage_users command is run while Stroom is running you will likely not see the effect when logging in, as the user permissions are cached.
Without Administrator rights you will not be able to clear the caches, so you will need to wait for the cache entries to expire or restart Stroom.
Navigate to https://STROOM_FQDN and Stroom should re-direct you to the IDP (KeyCloak) to authenticate.
Enter the username admin and password admin.
You should be authenticated by KeyCloak and re-directed back to Stroom.
Your user ID is shown in the bottom right corner of the Welcome tab.
As an administrator, the
menu item will be available to manage the permissions of any users that have logged on at least once.Now select
to be re-directed to the IDP to log out. Once you log out of the IDP it should re-direct you back to Stroom, which will send you to the IDP login screen to log back in again.As an Ordinary User
On the IDP login screen, log in as user jbloggs with the password password.
You will be re-directed to Stroom, however the explorer tree will be empty and most of the menu items will be disabled.
In order to gain permissions to do anything in Stroom, a Stroom administrator will need to grant application and document permissions and/or group memberships to the user via the
Configure Stroom-Proxy for KeyCloak
Create a second client in KeyCloak for the proxy, following the steps above but with Service accounts roles enabled so that it can use the client credentials grant. A proxy has no interactive users, so it needs no redirect URIs.
Edit the proxy’s config.yml file and set the following values:
receive:
# Set to true to require authentication for /datafeed requests
authenticationRequired: true
# Set to true to allow authentication using an Open ID token
tokenAuthenticationEnabled: true
security:
authentication:
openId:
identityProviderType: EXTERNAL_IDP
openIdConfigurationEndpoint: "http://localhost:9999/realms/StroomRealm/.well-known/openid-configuration"
clientId: "StroomProxyClient"
clientSecret: "THE_PROXY_CLIENT_SECRET"
logoutEndpoint: "http://localhost:9999/realms/StroomRealm/protocol/openid-connect/logout"
If Stroom-Proxy is configured to forward data on to another Stroom-Proxy or Stroom instance then it can use tokens when forwarding that data. This assumes the downstream Stroom or Stroom-Proxy is also configured to use the same external IDP.
forwardHttpDestinations:
# If true, adds a token for the service user to the request
- addOpenIdAccessToken: true
enabled: true
name: "downstream"
forwardUrl: "http://somehost/stroom/datafeed"
The token used will be for the service user account of the identity provider client used by Stroom-Proxy.
That token’s audience is validated at the destination just like any other, so the destination needs either an audience mapper on the proxy’s client, or the audience the proxy’s tokens actually carry listed in its allowedAudiences.