This post is intended to describe the single sign on capabilities of jsreport with the Keycloak authorization server, we will focus on the two ways you can use this feature to integrate the jsreport studio with Keycloak and delegate the user authentication to it.
Let's start by installing jsreport, create a new directory on your preferred location and run jsreport init
.
when it is done you should see something like this on your terminal
➜ jsreport init
jsreport installation not found, installing jsreport the latest version now, wait a moment...
jsreport installation finished..
Creating server.js
Creating package.json
Creating default config jsreport.config.json
Initialized
The easiest way to install and run Keycloak is by using Docker, so let's go that route.
run the following docker run -p 8080:8080 -e KEYCLOAK_ADMIN=admin -e KEYCLOAK_ADMIN_PASSWORD=admin quay.io/keycloak/keycloak:19.0.1 start-dev
, which will start Keycloak on port 8080
with an initial admin user
username: admin
password: admin
Now we need to configure the Keycloak, to do this we go to the Keycloak Admin Console and login there with the admin username and password we specified in the docker run ...
.
We start by creating a new realm. We open the select on the left side bar and click Create Realm
and use the name jsreport
.
With the jsreport
realm created we can now access the OpenID endpoints exposed by Keycloak by opening page http://localhost:8080/realms/jsreport/.well-known/openid-configuration. We need to copy some of these endpoints in the jsreport configuration in order to configure the integration appropriately.
Open the jsreport.config.json
file and add the following changes:
extensions.authentication.cookieSession.secret
to a secret valueextensions.authentication.enabled
to true
extensions.authentication.authorizationServer
configurationextensions.authentication.authorizationServer.name
to KeycloakServer
extensions.authentication.authorizationServer.issuer
to the value of the issuer
key listed in the Keycloak OpenID configurationextensions.authentication.authorizationServer.usernameField
to preferred_username
extensions.authentication.authorizationServer.endpoints.jwks
to the value of the jwks_uri
key listed in the Keycloak OpenID configurationextensions.authentication.authorizationServer.endpoints.authorization
to the value of the authorization_endpoint
key listed in the Keycloak OpenID configurationextensions.authentication.authorizationServer.endpoints.token
to the value of the token_endpoint
key listed in the Keycloak OpenID configurationextensions.authentication.authorizationServer.endpoints.introspection
to the value of the introspection_endpoint
key listed in the Keycloak OpenID configurationextensions.authentication.authorizationServer.endpoints.userinfo
to the value of the userinfo_endpoint
key listed in the Keycloak OpenID configurationYour jsreport.config.json
after these changes should look like this:
{
"httpPort": 5488,
"store": {
"provider": "fs"
},
"blobStorage": {
"provider": "fs"
},
"logger": {
"console": {
"transport": "console",
"level": "debug"
},
"file": {
"transport": "file",
"level": "info",
"filename": "logs/reporter.log"
},
"error": {
"transport": "file",
"level": "error",
"filename": "logs/error.log"
}
},
"trustUserCode": false,
"reportTimeout": 60000,
"workers": {
"numberOfWorkers": 2
},
"extensions": {
"authentication": {
"cookieSession": {
"secret": "secret"
},
"admin": {
"username": "admin",
"password": "password"
},
"authorizationServer": {
"name": "KeycloakServer",
"issuer": "http://localhost:8080/realms/jsreport",
"usernameField": "preferred_username",
"endpoints": {
"jwks": "http://localhost:8080/realms/jsreport/protocol/openid-connect/certs",
"authorization": "http://localhost:8080/realms/jsreport/protocol/openid-connect/auth",
"token": "http://localhost:8080/realms/jsreport/protocol/openid-connect/token",
"introspection": "http://localhost:8080/realms/jsreport/protocol/openid-connect/token/introspect",
"userinfo": "http://localhost:8080/realms/jsreport/protocol/openid-connect/userinfo"
}
},
"enabled": true
},
"sample-template": {
"createSamples": true
}
}
}
Now we need to register the jsreport studio and jsreport http api applications in keycloak so that they can request authentication of a user against keycloak.
To do this, we click to the Clients
on the left side bar and then click Create client
.
Register the following information and click Save
for the jsreport-studio
.
And the following information for the jsreport-api
Back in the Clients
list page we click on the jsreport-studio
, add *
to the Valid redirect URIs
field and click Save
.
Now we need to copy the credentials generated for this client application and add them to the jsreport.config.json
, we click the Credentials
tab and click on the Copy to clipboard
for the Client secret
.
With the secret copied, we open the jsreport.config.json
and add the following at extensions.authentication.authorizationServer.studioClient
"authorizationServer": {
...
"studioClient": {
"clientId": "jsreport-studio",
"clientSecret": "<the secret your copied from keycloak>"
}
...
}
We repeat the same steps for the jsreport-api
client, we add *
to the Valid redirect URIs
field, copy the secret and add it to the extensions.authentication.authorizationServer.apiResource
.
"authorizationServer": {
...
"apiResource": {
"clientId": "jsreport-api",
"clientSecret": "<the secret your copied from keycloak>"
}
...
}
The final jsreport.config.json
should look something like this (remember that you should replace the parts <the secret your copied from keycloak>
with the values you copy from Keycloak).
{
"httpPort": 5488,
"store": {
"provider": "fs"
},
"blobStorage": {
"provider": "fs"
},
"logger": {
"console": {
"transport": "console",
"level": "debug"
},
"file": {
"transport": "file",
"level": "info",
"filename": "logs/reporter.log"
},
"error": {
"transport": "file",
"level": "error",
"filename": "logs/error.log"
}
},
"trustUserCode": false,
"reportTimeout": 60000,
"workers": {
"numberOfWorkers": 2
},
"extensions": {
"authentication": {
"cookieSession": {
"secret": "secret"
},
"admin": {
"username": "admin",
"password": "password"
},
"authorizationServer": {
"name": "KeycloakServer",
"issuer": "http://localhost:8080/realms/jsreport",
"usernameField": "preferred_username",
"endpoints": {
"jwks": "http://localhost:8080/realms/jsreport/protocol/openid-connect/certs",
"authorization": "http://localhost:8080/realms/jsreport/protocol/openid-connect/auth",
"token": "http://localhost:8080/realms/jsreport/protocol/openid-connect/token",
"introspection": "http://localhost:8080/realms/jsreport/protocol/openid-connect/token/introspect",
"userinfo": "http://localhost:8080/realms/jsreport/protocol/openid-connect/userinfo"
},
"studioClient": {
"clientId": "jsreport-studio",
"clientSecret": "<the secret your copied from keycloak>"
},
"apiResource": {
"clientId": "jsreport-api",
"clientSecret": "<the secret your copied from keycloak>"
}
},
"enabled": true
},
"sample-template": {
"createSamples": true
}
}
}
jsreport needs to know how to associate the users from Keycloak to users/groups in jsreport. This association is needed to correctly identify which jsreport entities and permissions the user of Keycloak is able to work with in the context of jsreport.
There are two ways we can use the keycloak users for the login in jsreport studio.
3.2.0
version the only way to attach permissions was to use jsreport users and it was needed an strict map.groups
, by attaching permissions directly to the read permission group
, edit permissions group
fields of entities, and on the Keycloak side you will need to set an extra attribute on each user in order to associate it to the jsreport group it belongs.Open Keycloak Admin Console and navigate to the Users
section at the left side bar and click Create new user
.
There we fill the following information and click Create
:
The we click on the Credentials
tab, click Set password
and create a password for this user and click Save
.
Now we start jsreport by running npm start
, navigate to http://localhost:5488
and find the login page
Notice there is a new button LOGIN WITH KEYCLOAKSERVER
, but for now we aren't going to use it. We need to create a jsreport user first before we can login in studio with Keycloak.
At the studio login page login with our jsreport admin user credentials (which by default are username: admin, password: password
) and proceed to create a new jsreport user.
The new user should match the user created in Keycloak, so we are going to name it the same ukeycloak
(it isn't needed to use the same password).
We are going to edit the permissions for the sample
folder in the jsreport studio, in order the ukeycloak
user to see entities there when its login passes.
Now we are ready to test the login in jsreport studio with Keycloak, but we first logout our current session.
We should see the jsreport studio login page now and click the LOGIN WITH KEYCLOAKSERVER
button. Then we get redirected to the Keycloak login page where we enter the password for the ukeycloak
user.
Finally we should now be logged in to the studio, and we should be able to see the samples
folder.
In the Keycloak Admin Console navigate to the Users
section in the left side bar and click Add user
.
There fill the following information and click Create
:
Click on the Credentials
tab, click Set password
and create a password for this user and click Save
.
Then we click on the Attributes
tab, and add a group
key with the value gkeycloak
and click Save
.
Go to the Client scopes
in the left side bar and search for the profile
item, and click it.
Click the Mappers
tab and select the Add mapper
, By configuration
button.
Choose User Attribute from the list
and fill the following details and then click Save
:
Now we navigate to the jsreport studio at http://localhost:5488
. Ff there is an active session we should logout first. We need to create a jsreport group first before we can test the login with Keycloak for the group.
On the studio login page we login with our jsreport admin user credentials (which by default are username: admin, password: password
) and proceed to create a new jsreport group.
The new group should match the group value we used in the attributes of ukeycloak2
user in Keycloak, so we are going to name it gkeycloak
.
We are going to edit the group permissions for the sample
folder in the jsreport studio. In order for the ukeycloak2
user to see entities there when its login passes.
Now again, we are ready to test the login in jsreport studio with Keycloak, but we first logout our current session.
On the jsreport studio login page, we click the LOGIN WITH KEYCLOAKSERVER
button. Them we get redirected to the Keycloak login page, where we enter the password for the ukeycloak2
user.
Finally, we should be logged in the studio now, and we should be able to see the samples
folder.
Hope this post helps to understand better the two ways to integrate single sign on with jsreport. The source code for this post can be found here