keycloak-rest-authenticator

Enable implementing custom Keycloak SPI authenticators in NodeJs microservices via the ScriptBasedAuthenticator. Focus on the business logic not the Keycloak complexity.

Usage no npm install needed!

<script type="module">
  import keycloakRestAuthenticator from 'https://cdn.skypack.dev/keycloak-rest-authenticator';
</script>

README

Find the repository page at https://gitlab.com/guenoledc-perso/keycloak/rest-authenticator.
Find the article on Medium here,

REST AUTHENTICATOR for Keycloak

It happens that you want to use keycloak and customize it's authentication workflow but

  • you do not want to use java and its heavy development framework
  • you want to use light microservices to implement authenticator business logic
  • you are happy to use typescript as a development language

REST Authenticator is simplifying keycloak authenticators for you

Get started

  1. run a keycloak instance with scripts profile feature enabled (but not necessarily the upload_script). Visit https://www.keycloak.org/docs/latest/server_installation/#profiles.
  2. create a simple express server
  3. npm install --save keycloak-rest-authenticator

Creating an authenticator

  1. create a class that implements interface KeycloakRestAuthenticator, let's call it MyAuthenticator
  2. using expressjs, bind the authenticator to a path: app.use(RestAuthenticator.declare("/myauth", new MyAuthenticator()))

Deploying the authenticator

  1. instantiate the KeycloakPackager: const packager = new KeycloakPackager({options});
  2. register the authenticator: packager.addRestAuthenticator("/myauth"); or pass the packager as the last parameter of RestAuthenticator.declare()
  3. deploy the jar file: packager.make();

A jar file is created with the description of the declared authenticators.

Adding the authenticator to keycloak

  1. first check that the authenticator is deployed in keycloak by going to the /auth/admin/master/console/#/server-info/providers page
  2. check that in the authenticators section you find the `script-/myauth/authenticator-rest.js``
  3. go to the Authentication Flow of a realm and duplicate a flow to be able to edit (https://www.keycloak.org/docs/latest/server_admin/#_authentication-flows)
  4. When adding an "execution", in the list of providers, look for http://yourhost:port/myauth that represents the authenticator you have mapped above.
  5. There is no configuration possible. If you need configuration, either do it in the microservice itself, or in the client or realm attributes (via custom means)

Changes on version 0.2.0

  • Enable returning the user info to feed keycloak user database
  • Enable KeycloakScriptPackager to use relative path in keycloakDeploymentLocation

Understanding the flow

When an authentication will happen in keycloak the flow defined in the Authentication flow structure will execute step by steps.
When your authenticator is reached (if not disabled) keycloak will submit an http post request to your endpoint

  1. POST /myauth and the body is a json object following the structure of the AuthenticationRequest type that contains the context of the request. In particular, the request.mode is first set to authenticate. The KeycloakRestAuthenticator.processNew implementation is called.
  2. Your service depending on the functionality should respond with an AuthenticationResponse json structure with either
    • a form to display to the user - this is called a challenge in keycloak terminology - and uses the freemarker templates that you can customize
    • a redirect url
    • an error code to tell keycloak that the authentication step has failed
    • none of the above to tell keycloak the authentication step succeded
  3. The response may also contains attributes to set to the user, to the user's session, to the authentication flow
  4. If you have responded above with a form, then you expect that, when the user submit the form, you receive the form data. Keycloak does exactly that and your service is called with a similar post request as above to the same endpoint.
  5. POST /myauth and the body is the same json object following the structure of the AuthenticationRequest. The request.mode is now set to action. The request.authSession.authNote contains all the info set during the previous response. The request.httpRequest.formParams contains the fields of the form presented to the user. The KeycloakRestAuthenticator.processInteraction implementation is called
  6. Your service, depending of the functionalities should respond with a AuthenticationResponse json structure like above.
  7. If the execution above takes a long time (maybe you have sent a push message to the user mobile and waiting for an acknowledgment) and in parallel the user refresh the form, or click on another button, the service is called again with a similar post to the endpoint but since the previous call has not returned, the KeycloakRestAuthenticator.processinterruption implementation is called.

Refer to the homepage to see the diagram