Custom/External Login Flow via Action Token SPI

We have specific requirements around the authentication flow and UI/UX that cannot be satisfied through Keycloak’s theming engine and extensions to the Authenticator SPI.

I looked into the Action Token SPI and it seems like an extension point that could be used to delegate (most of) the authentication flow to an external application. According to the keycloak quickstart action-token-authenticator example (https://github.com/keycloak/keycloak-quickstarts/tree/latest/action-token-authenticator), it seems like it can be used specifically for this purpose.

For a browser authentication flow, the idea would be that we would have keycloak initiate the flow by first verifying the username/password. If that is successful, we would redirect the user to the external application (supplying it the action-token and username/id of the user) to perform the supplemental authentication process - e.g. custom MFA. If the external application successfully performs the supplemental authentication, it will then redirect back to keycloak with the action-token, to resume and complete the authentication process that was initiated earlier. With this externalized login process, we would have full control on every aspect how it can be designed/implemented.

Any thoughts/comments on whether this approach is feasible, secure and proper use of Action Token SPI?

Thanks in advance.

We’ve thought the same. And yes we have implemented a project successfully as you describe. It’s feeling safe but not good.

(Edit) we have still some differences - we modified registration and password reset, not authentication.
Consider building your own Authenticator and look into IBMs example of adding MFA to understand how ugly the combination of UIs is.
They do exactly what you want to.

https://community.ibm.com/community/user/security/blogs/austin-bruch1/2019/11/22/cloud-identity-keycloak-integration

And yes it’s completely free, includes source code, and setup to see it in action is about 30 minutes following the great instructions after you found the PDF

(/edit)

We believe that the amount of work going into the custom handling is growing by any future requirement you are not yet aware of.

The whole concept of the IDP, being an instance managing users and passwords and authentication for one or more apps is suggesting to leverage it for its tasks.

I would recommend to first build the solution leveraging the IDP as designed, and then build a custom approach as you describe. This gives you a comparison.

(Edit)
For your case, try to integrate your extras first in the model of Keycloak by adding Authenticator a and creating custom flows leveraging them - and keep the ui hosted on keycloak. Then look again what you can get extra by leaving keycloak and returning…
(/edit)

So what are the requirements conceptually not allowing the idp to host the UI for its own tasks?

Apologies for my late reply. I appreciate all the info provided. The IBM example you linked is the kind of solution I was exploring, but as you said, it does look quite ugly.

Our preferred approach would be to do everything within Keycloak’s framework, as the general community suggests. Right now, we have a separate application that supports all the required authentication flows/features (e.g. MFA, security questions, etc.), built to a specific UI/UX spec. Ideally, we would like to move all those authentication components into Keycloak, rather than try to rebuild it. That application is a React SPA, so the entire authentication flow is exposed via a single-page, with dynamic JS - which, I imagine would not easily port to Keycloak’s templating and hook into Authenticator SPI.

Even if we cannot re-use what we have, a rebuild within Keycloak must still satisfy that same UI/UX spec. We do not want to refresh the page, on the inputs/credentials of each authenticator in the login flow.

Any suggestions/thoughts as to how we can support this type of SPA UI/UX through Keycloak’s standard Authenticator SPI/templating, would be greatly appreciated.

Thanks in advance.

I hope the following makes sense:
I believe you can do a single Authenticator which performs all things in one step as you claim as requirement. So you just loose the lego approach of combining Authenticators but stay within the design.

Thank you for your reply.

Yes, that makes sense, but I’m unclear how to actually implement the concept. e.g. for a single-page implementation of a multi-step flow, the username/pass needs to be validated first against the server before proceeding to prompt for further credentials (e.g. 2FA for the user). In a normal user/pass authenticator implementation, the authenticator would receive the form-variables if the entire form was posted to the server, and the action method of the authenticator can validate the input for that specific credential type. Now, if I wanted to support multiple steps without submitting the form, with each individual step requiring validation/interaction with the server-side, how can that be achieved with a single authenticator? What should the authenticator receive in the action method? Or should we implement a separate API to handle the interactions? If yes, would this API need to be (somehow) hosted within Keycloak in order have access to the required session and security context of the user?

Any pointers to how this should be designed is appreciated. Thanks in advance.

Ok got it.
So what you look for is a single ui that serves the user but interacts step by step with keycloak authenticators… here’s what I think:

Let’s put aside how to show the page (it could even be on a separate Webserver).
Look into the source of an Authenticator and you see how it returns the success. Implicitly there is then the next step, and keycloak will redirect the browser to the next page.
Your page can ignore that, and call the Authenticator anyway. You just need to verify if you get a success and go into your next step on the form .

To see it better look into the Cli, the kcadmin shell script. Most Authenticators support the Cli as well, but they don’t handle it special. So your page is like a custom browser based Cli