/keycloak-spi-browser-session-api

A Keycloak SPI to start a browser session from a valid JWT

Primary LanguageJavaApache License 2.0Apache-2.0

keycloak-spi-browser-session-api

The goal of this SPI (Service Provider Interface) for Keycloak is to create a browser session by setting all relevant cookies out of a valid JWT (Json Web Token).

Useful to provide SSO (Single Sign On) capabilities for legacy web application to a new web application being authenticated by Keycloak.

Important to note is that this SPI expects the legacy web application to be able to access a valid JWT. This might occur if you need to introduce new features in legacy web applications.

Usage

Prerequisite is a valid JWT (access token) obtained from your Keycloak IDM.

With that valid JWT you may invoke within a browser the API provided by this SPI. E.g. with the following example JS code:

// config
var providerUrl = "http://localhost:5080";
var realm = "master";
var targetClientForNewSession = "application";
var jwt = "eyJhbGciOiJSUzI1NiIs.....";
// invocation
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", `${providerUrl}/auth/realms/${realm}/browser-session/init?publicClient=${targetClientForNewSession}`, false);
xmlHttp.withCredentials = true;
xmlHttp.setRequestHeader("Authorization", "Bearer " + jwt);
xmlHttp.send(null);
return xmlHttp.responseText;

This will create a new user session for the provided client and set the Keycloak cookies so that after loading / redirecting to the URL of the application secured by Keycloak no prompt to login will appear.

API

It contains of one single API request:

HTTP Method Path Request Header Description
GET baseUrl/auth/realms/realm/browser-session/init?publicClient=targetClientName Ensure Authorization: Bearer with the JWT baseUrl: URL to Keycloak e.g. https://your.keycloak.example.org
realm: realm to be used e.g. master
targetClientName: public client (defined in Keycloak) for which to start the browser session

Deployment

  1. Build with mvn clean package
  2. Copy resulting artifact keycloak-spi-browser-session-api-1.0.jar to the deployments folder of Keycloak

Configuration

There is no real configuration for the SPI itself. It relies on parameters of the SPI API call and Keycloak settings.

  • As user the one identified by the JWT will be used
  • The realm needs to be passed as path element in the browser-session API URL, see example
  • The GET parameter publicClient specifies the public client to be used for new session, see example
  • For CORS the Web Origins settings from the publicClient in Keycloak are used. Please note that * should be avoided in production environments.

How to test locally?

Start Keycloak with PostgreSQL as the IDM Provider, a start-app and dest-app.

docker-compose up

The start-app is the starting point e.g. an application where a user is already logged in and has a valid JWT. Please open http://localhost:5082. For sake of simplicity no authentication takes place here.

The dest-app is just a demo website secured with keycloak.js.

The goal is to initiate a browser session from start-app only having a valid JWT to dest-app.

Please configure Keycloak as follows:

  • login to Keycloak via http://localhost/ (user / bitnami)
  • create two clients
    • dest-app with access type public and Web Origin http://localhost:5082 and/or *
    • private with access type confidential
  • create one user
    • testuser with password Test123!

Build and deploy it

mvn clean package && docker cp target/keycloak-spi-browser-session-api-1.0.jar keycloak-spi-browser-session-api-keycloak-1:/opt/bitnami/keycloak/standalone/deployments/keycloak-spi-browser-session-api-1.0.jar

Run the test by generating a new access token and placing it into the demo/start-app/index.html. This is only for demo purposes.

CLIENT_ID=private
# ... please change CLIENT_SECRET accordingly as it gets generated by Keycloak
CLIENT_SECRET=8b3576db-6492-4238-aa60-d7c71a9663f7
API_USER=testuser
API_PASSWORD='Test123!'
ACCESS_TOKEN=$(curl -s -d "client_id=$CLIENT_ID" -d "client_secret=$CLIENT_SECRET" --data-urlencode "username=$API_USER" --data-urlencode "password=$API_PASSWORD" -d 'grant_type=password' 'http://localhost:5080/auth/realms/master/protocol/openid-connect/token' | jq -r '.access_token')
sed -i -E 's#var jwt = ".*$#var jwt = "'"$ACCESS_TOKEN"'";#' demo/start-app/index.html

And please don't forget to reload http://localhost:5082

License

APACHE LICENSE, VERSION 2.0