@yordis @edewit hello all, I’ve been looking to solve a similar problem and found this thread.
It looks like many people had a hard time understanding the problem, so let me summarize:
- As part of the authentication protocol, a client redirects the user to, say auth.server/auth/realms/example/protocol/openid-connect/auth
- The user provides their credentials via HTTP POST to /auth/realms/example/login-actions/authenticate
- The user is redirected back to the client application
At no point in the process is any HTML, CSS, JS, or fancy responsive web UI explicitly part of the SAML or OpenID Connect flow. A user could fetch and type out the required HTTP requests in telnet, for example, but this would be very inconvenient.
To make this process easier, the Keycloak server kindly barfs out a HTML document, with some thoughtful <input/> tags, for your browser to automate the HTTP request part for you. (It also sets some cookies and provides some extra inputs to make sure someone didn’t trick your browser into doing this.)
If you wanted to handle the HTML part yourself, (and I do, because unfortunately the ones currently included by default are not very mobile-friendly, and customizing the .ftl files is cumbersome) there’s no fundamental reason you can’t, say, make an nginx proxy serve your own static files for /auth/realms/example/protocol/openid-connect/auth. However, Keycloak does make this difficult:
- Some of the required state for the login process is in httpOnly cookie values.
- There are additional required tokens that must be submitted, that are only provided when Keycloak renders the .ftl templates.
This could be solved if Keycloak had an API endpoint that provided the state tokens and metadata about the login process as e.g. JSON, and set the cookies it needs. This is not to implement a “resource owner password credentials grant” client, in the sense that a custom UI is part of the login process itself, and part of the identity provider service.
TL,DR the answer to what you’ve been asking this whole time:
The way to do this is not entirely painless, but gets you 95% to what you wanted.
- Create a new, base Keycloak theme
- Replace the HTML in the templates with a barebones HTML document. Maybe give it a
<div id="container"></div> tag if that’s what your JS app is expecting.
- Add a
<script> tag that includes your web app’s JS bundle from somewhere (you’re making this into what Webpack’s index.html does, essentially)
- Add a
<script> section that copies the .ftl context into a JS variable. There are unfortunately a lot of these, I am not sure if there’s a quick way to dump the entire FTL context into a JSON string, or if that has sensitive data in it. It would look like e.g.
<script>
var kcState = {loginAction: "${url.loginAction}"};
</script>
- Have your app implement the login/registration/etc. forms, submitting to
window.kcState.loginAction for example.
And there you have it, you can write a JS app that handles all of the HTML rendering, and only relies on Keycloak for tokens and cookies. In fact, this is what the keycloak.v2 theme for the self-service account console does. Be sure to check it out for a real example.