ShinyProxy can integrate with any OIDC provider, this example specifically demonstrates how to integrate ShinyProxy with Keycloak.
Note
We do our best to document the steps in Keycloak, however, Keycloak may change and this documentation may get outdated. Please open an issue or PR in this case.
It's a good idea to first read the general ShinyProxy OpenID documentation.
The complete setup and configuration of Keycloak is out of the scope of this example. Check the Keycloak documentation and the Docker example for more information.
-
Login into Keycloak
-
Create or select a realm
-
Click on
Clients
, Click onCreate client
-
Provide a
Client ID
and remember this value, clickNext
-
Enable
Client authentication
, disableDirect access grants
, make sureStandard flow
is enabled, clickNext
-
Fill in the location of ShinyProxy (without any sub-path) in
Root URL
andHome URL
. -
Add the following as
Valid redirect URI
(replacingshinyproxy-demo.local
with your domain name):https://shinyproxy-demo.local/login/oauth2/code/shinyproxy
-
The filled in form should look like:
-
Go to the
Credentials
tab and copy theClient secret
value. You'll need this in the ShinyProxy configuration. -
Go to
Realm settings
(in the sidebar) and click onOpenID Endpoint Configuration
-
Copy the following fields from the JSON:
authorization_endpoint
token_endpoint
jwks_uri
Now that you configured Keycloak and you retrieved all parameters, you can configure ShinyProxy.
-
Add the following configuration to your ShinyProxy config (replace the examples with the values you retrieved from Keycloak):
proxy: authentication: openid openid: # see step 11 (of previous section): authorization_endpoint auth-url: https://keycloak-demo.local/auth/realms/master/protocol/openid-connect/auth # see step 11 (of previous section): token_endpoint token-url: https://keycloak-demo.local/auth/realms/master/protocol/openid-connect/token # see step 11 (of previous section): jwks_uri jwks-url: https://keycloak-demo.local/auth/realms/master/protocol/openid-connect/certs # see step 4 (of previous section) client-id: shinyproxy-config-example # see step 9 (of previous section) client-secret: 1aB... username-attribute: preferred_username
-
Restart ShinyProxy
You should now be able to log in on ShinyProxy using a Keycloak user. You can
create additional users by going to the Users
page in Keycloak.
The current setup will use the preferred_username
of the user to identify it
(this is e.g. shown in the navigation bar of ShinyProxy). This corresponds to
the username field in the Keycloak UI. By default keycloak sends most user
information as part of the ID token. Therefore, you can immediately use these
values to identify the user. For example, to use the e-mail address, change the
change the proxy.openid.username-attribute
in ShinyProxy to email
:
proxy:
openid:
username-attribute: email
Note
Make sure that every user has an e-mail address configured. Otherwise, the user will get an error when logging in.
It's possible to see all claims which are being sent to ShinyProxy, see the documentation.
In Keycloak, it is possible to assign (multiple) roles to a user. These roles can be used in ShinyProxy as groups, e.g. for adding authorization to apps.
-
Login into Keycloak
-
Select a realm
-
Go to
Clients
and select the client you created for ShinyProxy -
Go the
Client Scopes
tab -
Click on the first scope, e.g.
shinyproxy-config-example-dedicated
-
Click on
Add mapper
, click onBy configuration
(or immediately click onConfigure a new mapper
) -
Click on
User Realm Role
-
Use
realm_roles
asName
-
Keep
Realm Role prefix
empty -
Keep the
Multivalued
option enabled, -
Use
realm_roles
asToken Claim Name
-
Use
String
asClaim JSON type
-
Ensure the
Add to ID token
option is selected -
The
Add to access token
orAdd to userinfo
options may optionally be enabled, but are not required for ShinyProxy -
Click
Save
-
Add the
proxy.openid.roles-claim
property to the ShinyProxy config:proxy: openid: roles-claim: realm_roles
-
Restart ShinyProxy
When a user now logs in on ShinyProxy, Keycloak sends the roles of that user to
ShinyProxy. You can check whether this works by starting an app and retrieving
the SHINYPROXY_USERGROUPS
environment variable.
In addition to roles, Keycloak also supports the concept of groups, see Keycloak docs for the difference. Both Keycloak groups and Keycloak roles can be used in ShinyProxy as groups, e.g. for adding authorization to apps. It is, however, not possible to use both roles and groups at the same time in ShinyProxy.
-
Login into Keycloak
-
Select a realm
-
Go to
Clients
and select the client you created for ShinyProxy -
Go the
Client Scopes
tab -
Click on the first scope, e.g.
shinyproxy-config-example-dedicated
-
Click on
Add mapper
, click onBy configuration
(or immediately click onConfigure a new mapper
) -
Click on
Group Membership
-
Use
groups
asName
-
Use
groups
asToken Claim Name
-
Switch off the
Full group path
option -
Ensure the
Add to ID token
option is selected -
The
Add to access token
orAdd to userinfo
options may optionally be enabled, but are not required for ShinyProxy -
Click
Save
-
Add the
proxy.openid.roles-claim
property to the ShinyProxy config:proxy: openid: roles-claim: groups
-
Restart ShinyProxy
When a user now logs in on ShinyProxy, Keycloak sends the groups of that user to
ShinyProxy. You can check whether this works by starting an app and retrieving
the SHINYPROXY_USERGROUPS
environment variable.
Note: do not use the built-in groups mapper of Keycloak as this mapper provides the realm-roles of the user and not the groups.
When clicking the logout button in the current setup, the user will just be logged out from ShinyProxy. You can configure ShinyProxy to logout the user in Keycloak:
-
Go to the
OpenID Endpoint Configuration
in Keycloak (see the first section) and copy theend_session_endpoint
value. -
Add the
proxy.openid.logout-url
property to the ShinyProxy config:proxy: openid: logout-url: https://keycloak-demo.local/auth/realms/master/protocol/openid-connect/logout
-
Restart ShinyProxy
Note:
-
When a user clicks the logout button, Keycloak will ask the user whether they really want to logout:
If you want to automatically sign out the user you'll have to add
?id_token_hint=#{oidcUser.idToken.tokenValue}
to the end of thelogout-url
:proxy: openid: logout-url: https://keycloak-demo.local/auth/realms/master/protocol/openid-connect/logout?id_token_hint=#{oidcUser.idToken.tokenValue}
-
When the user is logged out, Keycloak shows a confirmation screen:
You can redirect the user to a different URL by adding the
post_logout_redirect_uri
parameter to the URL (in this case theid_token_hint
is mandatory):proxy: openid: logout-url: https://keycloak-demo.local/auth/realms/master/protocol/openid-connect/logout?id_token_hint=#{oidcUser.idToken.tokenValue}&post_logout_redirect_uri=http%3A%2F%2Fshinyproxy-demo.local/logout-success
In this setup Keycloak is (virtually) invisible to the user.
Up to version 3.0.x, ShinyProxy included a dedicated keycloak
authentication
backend. This backend was using the official Keycloak Java library, however,
this library was deprecated by the Keycloak developers. In addition,
the openid
backend is fully compatible with Keycloak and has more
(advances) features. Therefore, we deprecated the keycloak
backend in
ShinyProxy 3.0.0 (by adding a warning in the release notes and documentation)
and starting with version 3.1.0 of ShinyProxy, the keycloak backend has been
removed. This section explains how you can easily migrate from the old backend
to the new one.
-
Find you current Keycloak configuration, for example:
proxy: authentication: keycloak keycloak: realm: master auth-server-url: https://keycloak-demo.local/auth resource: shinyproxy-config-example credentials-secret: example_secret
-
Follow the steps in Configuring roles, such that Keycloak sends the roles of a user to ShinyPoxy
-
Change the ShinyProxy config to use OpenID (remove the keycloak config):
proxy: authentication: openid openid: # corresponds to {auth-server-url}/realms/{realm}/protocol/openid-connect/auth # where "{auth-server-url} and "{realm}" are the old Keycloak configuration properties auth-url: https://keycloak-demo.local/auth/realms/master/protocol/openid-connect/auth # corresponds to {auth-server-url}/realms/{realm}/protocol/openid-connect/token # where "{auth-server-url} and "{realm}" are the old Keycloak configuration properties token-url: https://keycloak-demo.local/auth/realms/master/protocol/openid-connect/token # corresponds to {auth-server-url}/realms/{realm}/protocol/openid-connect/certs # where "{auth-server-url} and "{realm}" are the old Keycloak configuration properties jwks-url: https://keycloak-demo.local/auth/realms/master/protocol/openid-connect/certs # corresponds to "resource" in the old Keycloak configuration properties client-id: shinyproxy-config-example # corresponds to "credentials-secret" in the old Keycloak configuration properties client-secret: example_secret # equivalent of proxy.keycloak.name-attribute # the Keycloak default is "name" username-attribute: name
-
Optionally: Configure the username
-
Restart ShinyProxy