Using docker, docker-compose, and Keycloak, you can roll your own local IdP for use with REMS.
- Setting up the docker-compose file
Create a
docker-compose.yaml
file for REMS and your Keycloak IdP. Mount your custom REMS config to/rems/config/config.edn
. The following example is provided as adocker-compose.yaml
file in this directory:
version: "3.7"
services:
rems:
image: cscfi/rems
mem_reservation: 200m
mem_limit: 500m
ports:
- "127.0.0.1:3000:3000"
volumes:
- ./services/rems/simple-config.edn:/rems/config/config.edn
depends_on:
- db
- keycloak
db:
image: postgres:9.6
environment:
POSTGRES_USER: rems
POSTGRES_PASSWORD: remspassword
mem_reservation: 30m
mem_limit: 150m
ports:
- "127.0.0.1:5432:5432"
keycloak:
image: quay.io/keycloak/keycloak:latest
environment:
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: admin
ports:
- "8080:8080"
volumes:
db:
Next, we will set up Keycloak with the following settings:
Keycloak property | Setting | Value |
---|---|---|
Keycloak admin's username | Username or email | admin |
Keycloak admin's password | Password | admin |
realm | Name | rems-idp |
client | Client ID | rems-client |
client auth protocol | Client Protocol | openid-connect |
acceptable client redirect URIs | Valid Redirect URIs | * |
client access type | Access Type | confidential |
client authenticator | Client Authenticator | Client Id and Secret |
Keycloak-generated client secret | Secret | 0ed4b9e0-5ff0-446a-ab7b-82dac465b9d5 |
REMS user's username | Username | username |
REMS user's password | Password | password |
- Running and preparing Keycloak
- Run the keycloak container with
docker-compose up keycloak
. - Login to keycloak as
admin
/admin
. Login athttp://keycloak:8080/auth/admin
. The administration username and password can be set as environment variables, as shown in thedocker-compose.yaml
example above. - (Optional) Import the generic REMS Keycloak realm provided in this repository.
Download the
realm-export.json
file provided in this directory. Mouse overMaster
near the top-left of the page, and clickAdd realm
. Next toImport
, clickSelect file
and choose therealm-export.json
file. ClickCreate
to finish. Skip to step #4 below.
- Run the keycloak container with
If you opt to not do #2.3, follow the instructions outlined in step #3 (below) to set up the realm manually.
-
(Optional) Manually preparing a Keycloak Realm
- Add an identity provision
realm
to Keycloak namedrems-idp
. Add the realm by mousing overMaster
near the top-left of the page, and clickingAdd realm
. A realm can be thought of as a single vault containing a set of users, credentials, groups, clients, security settings, etc. When authenticating with a realm, the client is only able to authenticate within that realm. - Add an OIDC client named
rems-client
to the realm. Navigate toClients
on the left side of the page and clickCreate
. Set theClient Protocol
toopenid-connect
. Clients are allowed to authenticate users within the Keycloak realm that they are bound to. For this example, the Client ID will berems-client
. - Define the set of acceptable redirect URIs.
Upon client creation, you will be redirected to
Clients
>rems-client
. To accept all redirect URIs, put*
in theValid Redirect URIs
field. - Authenticate the client with Keycloak using the
Client Id and Secret
. There various ways to authenticate the client itself with Keycloak. REMS uses theClient ID
and a Keycloak-generatedSecret
. In Keycloak, navigate toClients
>rems-client
. Set theAccess Type
toconfidential
.
- Add an identity provision
-
Configuring REMS to Authenticate with Keycloak
- Generate the REMS client secret.
In Keycloak, navigate to
Clients
>rems-client
>Credentials
. ClickRegenerate Secret
and copy the generated secret to your clipboard. In this example, the generated secret is0ed4b9e0-5ff0-446a-ab7b-82dac465b9d5
, but yours will be something different. - Configure REMS to use the secret.
Modify your custom REMS config file (called
./services/rems/simple-config.edn
in this example). Tell REMS to use OIDC by modifying the:authentication
parameter, and setting the values for some OIDC parameters specific to your keycloak instance. Remember that docker-compose will mount this file into your REMS container as/rems/config/config.edn
.
:authentication :oidc ; The location of Keycloak's OIDC metadata for the realm to which REMS is client :oidc-metadata-url "http://keycloak:8080/auth/realms/rems-idp/.well-known/openid-configuration" ; REMS' client ID, as defined in Keycloak :oidc-client-id "rems-client" ; REMS' client secret, as generated in keycloak in step #4.1 :oidc-client-secret "0ed4b9e0-5ff0-446a-ab7b-82dac465b9d5"
- Generate the REMS client secret.
In Keycloak, navigate to
-
Spinning up REMS
- Finalize the REMS configuration.
The full configuration used in this example is provided in the
simple-config.edn
file in this directory. Add any other configuration that your REMS instance needs to yoursimple-config.edn
file. For example, you will want to populate thedatabase-url
andport
parameters.
:port 3000 :database-url "postgresql://db:5432/rems?user=rems&password=remspassword" :search-index-path "/tmp/rems-search-index" :authentication :oidc :public-url "http://localhost:3000/"
- Migrate the REMS database.
- Migrate REMS with:
docker-compose run --rm -e CMD="migrate" rems
- (Optional) Populate REMS with test data with:
docker-compose run --rm -e CMD="test-data" rems
- Migrate REMS with:
- Run with:
docker-compose up rems
- Navigate to REMS, at http://localhost:3000/ in this example.
- Finalize the REMS configuration.
The full configuration used in this example is provided in the
-
Testing Authentication
- Create REMS user username/password in Keycloak.
- To test authentication with Keycloak, add a test User in Keycloak by navigating to
Users
and clickingAdd user
. Give them ausername
and clickSave
. - Navigate to the new User's
Credentials
tab and set apassword
for them. Set theTemporary
toggle toOFF
.
- To test authentication with Keycloak, add a test User in Keycloak by navigating to
- In REMS, at http://localhost:3000/ in this example, click the
Login
button to be redirected to Keycloak. - Access the account by logging in with the user's
username
/password
credentials. You should be authenticated and redirected back to REMS.
- Create REMS user username/password in Keycloak.
-
Exporting the Realm
- You can export your realm and save it source control, to reduce development and testing time. Simply navigate to
Export
on the bottom-left of the page, setExport clients
toON
, and clickExport
. - Next time you want to add this realm to keycloak, navigate to
Add Realm
and select yourrealm-export.json
file for import.
- You can export your realm and save it source control, to reduce development and testing time. Simply navigate to
If you are using docker-compose to spin up your IdP alongside REMS, you may run into hostname issues pertaining to :oidc-metadata-url
when using a browser. Keycloak generates the redirect URLs served at the ./well-known/openid-configuration
endpoint based on the hostname of the incoming request. But if this hostname is relative to a set of docker containers, it might not make sense to the browser from which you are accessing REMS and the Keycloak IdP.
For example, suppose your docker-compose.yaml
has a Keycloak IdP configured as follows:
services:
keycloak:
ports:
- "8080:8080"
Then, in your REMS config file, you must set something like:
:oidc-metadata-url "http://keycloak:8080/auth/realms/rems-idp/.well-known/openid-configuration"
If you use localhost:8080
instead of keycloak:8080
, then REMS will crash with a Connection Refused
exception early in runtime.
Using the keycloak:8080
hostname, the problem arises when a user attempts to Login to REMS. REMS requests authentication redirection URLs from Keycloak at the keycloak:8080
address. Keycloak then generates those URLs using the keycloak:8080
hostname used in the request. However, keycloak:8080
is meaningless to the user's browser, which does not have access to the docker-compose network namespace. The browser is unable to find Keycloak at that address.
This can be resolved with either of the processes outlined below, which cause keycloak to generate the URLs served at .well-known/openid-configuration
with a specified frontendUrl. The frontendUrl
resolves to a hostname that the browser is able to find (localhost:8080
in this example). REMS will still be able to connect to keycloak at keycloak:8080
at runtime, but the .well-known/openid-configuration
Keycloak endpoint will serve URLs with the frontendUrl
base URL you set.
This solution is host-independent, can be saved to source control, and is easy to automate into your overall Keycloak setup process.
- Run your keycloak and REMS with
docker-compose up
. - Create or import a
realm
if you have not done so already. - In the realm settings on the admin console, populate the
Frontend URL
field withhttp://localhost:8080/auth/
. This is assuming you want Keycloak to authenticate atlocalhost:8080
. Amend the hostname as needed, but make sure the value for Frontend URL terminates with/auth/
. - You can export your realm with this custom frontendUrl and add the resulting
realm-export.json
to source control. Next time you set up keycloak by importing the realm, the frontendUrl will be populated automatically.
This solution is a common work-around for keycloak redirection issues, but has the following disadvantages:
- Requires administrative access to the host machine
- Is a manual process that must be run on each new machine that keycloak is being installed on
- Can cause confusion when multiple seperate instances of Keycloak are run on one host
- May not work if the port number inside the docker network differs from the port exposed on the host, for example if
localhost:8081
is mapped tokeycloak:8080
- Open the host's
/etc/hosts
file for editing, for example with:sudo nano /etc/hosts
- Add the end of the file, add the IP address of your keycloak instance followed by the domain name and its aliases:
IPAddress DomainName [DomainAliases]
. For example, append:
127.0.0.1 keycloak
- Save the modified
/etc/hosts
file.