The code in this forked repository is based on/inspired by the following repositories:
- https://github.com/groupe-sii/keycloak-json-remote-claim
- https://github.com/tagirova/keycloak-json-remote-claim
- https://github.com/mschwartau/keycloak-custom-protocol-mapper-example
Cheers!
This module uses the unofficial Protocol Mapper SPI for keycloak.
It adds a new mapper type which retrieves a JSON claim from a remote HTTP endpoint (e.g. from a REST API). This endpoint may be a GraphQL endpoint that uses bearer (JWT) token authentication.
This module currently works with Keycloak 10.0.0.
It is compatible with Keycloak >= 4.6.0 , you may just need to change the keycloak version in the pom.xml
.
For version <= 4.5.0, the module will also work but a functionnality will be unavailable (see (1)).
Start by building the module:
mvn clean package
Build module and then copy the target/json-graphql-remote-claim.jar
file to /opt/jboss/keycloak/standalone/deployments/
.
Keycloak should pick it up automatically and deploy it.
No restart should be required.
To deploy automatically in docker, you can use this solution from Meinert Schwartau:
https://github.com/mschwartau/keycloak-custom-protocol-mapper-example
NOTE: For remote requests to work, your container's network setup has to allow outbound connections!
For local development localhost
is
available from within the container via host.docker.internal
(only on Docker Desktop for Windows/Mac,
see here).
For example, if you have development instance of your remote claim service running at localhost:8082
,
you can configure the URL parameter in the protocol mapper as http://host.docker.internal:8082/graphql
.
(Always use https
in production.)
To add a JSON claim from a remote HTTP / REST / GraphQL service, you just need to add a mapper from client (or client scope) configuration.
Step by step (for authorized GraphQL queries):
- After deployment of your custom protocol mapper (see above), open the Keycloak Admin UI of your realm.
- Go to clients and select the client whose authentication tokens you want to enrich with your custom remote claims.
- Go to "Mappers", click "Create" and select "JSON GraphQL Remote Claim" as "Mapper Type".
Token Claim Name
is the property name in the token that will contain the remote claim. Example:custom
URL
is the URL of the remote endpointSend Bearer Token
- If enabled, the protocol mapper will obtain an access token from Keycloak and
put it into the request headers as
Authorization: Bearer <token>
. Client Auth URL
will typically be the URL to Keycloaks token endpoint itself. Example:http://localhost:8080/auth/realms/demo/protocol/openid-connect/token
Client Id
refers to a keycloak client for which the protocol mapper obtains an access token. This client represents the remote endpoint and must not be the same as the client in step 2, to avoid infinite recursion! This client must haveAccess Type = confidential
andService Accounts Enabled = ON
.Client Secret
is the secret from the client credentials page.
- If enabled, the protocol mapper will obtain an access token from Keycloak and
put it into the request headers as
Send a GraphQL Query
-
If enabled, the protocol mapper will send the configured GraphQL query as a POST request.
-
GraphQL Query
is the query that should be sent. The variablesusername
andclient_id
can be used in the query if they are enabled.See example:
query myQuery($username: String!){ myQuery(userName: $username) {userName email role}}
-
GraphQL Query Result Path
is the result json path that will be mapped to the token claim name. Example:data.myQuery
-
- If
Send a GraphQL Query
is disabled, the protocol mapper will send a GET request with regular<key1>=<val1>&<key2>=<val2>&...
parameters.
Custom Headers and Parameters
In GraphQL mode, parameters are passed as GraphQL variables. In GET mode (GraphQL disabled), parameters are passed as regular query string
- Send the username as
username
query parameter (Send user name) - Send the client_id of the resource as
client_id
query parameter (Send client ID) - Add user attributes as parameters to the query (User attributes)
- Add custom query parameters to the request (Parameters)
- Add custom HTTP headers to the request (Headers)
For headers and query parameters, use =
to separate key and value. You can add multiple parameters (and headers) by separating them with &
.
- Integration as a protocol mapper in Keycloak dashboard
- Configurable claim path (= claim name)
- Handles any type of JSON object
- Sending username as an option
- Sending client_id as an option
- Custom query parameters
- Custom HTTP headers
- URL configuration
- Error handling:
- default behavior: no token delivered if claims are unavailable (error 500 will occur)
- with
Suppress all Errors
enabled: catches all errors and returnserror
as claim value
- Debugging Options
Disable Remote Requests (Debugging)
: disables all requests and simply returns "disabled" as claim valueReturn all Errors (Debugging)
: returns error message as claim value instead of throwing an Error/Exception back at Keycloak
- Configurable Keycloak Client
- will be used by protocol mapper to obtain access token at runtime.
- access token will then be sent to remote endpoint as
Authorization: Bearer <token>
. - Keycloak client must not be the one that this protocol mapper is used with. (would otherwise create infinite loop)
- Keycloak client should be confidential with only "service account flow" enabled, i.e., login with
grant_type
client_credentials
is enabled.
- Configurable GraphQL query
- will be sent as HTTP POST request.
- username, client_id, and other parameters will be sent as query variables, if enabled
- result json path is configurable, e.g.,
data.a.b.c
corresponds to a nested JSON document where the value of propertyc
will be mapped to the claim
- (1) Optimization when multiple tokens in the response: needs a single request (example: access_token and id_token in the response)
(1) Only with Keycloak >= 4.6.0