[keycloak-dev] HTML5/JS applications

Stian Thorgersen stian at redhat.com
Tue Oct 8 09:38:27 EDT 2013


I'm working on a HTML5 SDK + example for Keycloak and would like some feedback on how it should work.

I've made the assumption that the application is a Keycloak resource, it uses fragments for navigation (i.e. no page reloads on navigation) and that the credentials for the application is not a secret.

I'd like to hide as much as of the complexity as possible in keycloak.js and make it nice and simple to use. keycloak.js will provide the following functions:

* init(config, async) - config is the configuration available from keycloak - async is optional (default is false)
* onAuthenticated(handler) - registers a handler for successful authentication - should be used if async is set to true in init
* onAuthenticationFailure(handler) - registers a handler if failed to authenticate - should be used if async is set to true in init

* login() - redirects to the keycloak login form
* register() - redirects to the keycloak registration form

* isAuthenticated() - returns true if user is authenticated
* getUsername() - returns the username (principal from token)
* getProfile() - returns the authenticated users profile
* getApplicationRoles() - returns the application roles
* getRealmRoles() - returns the realm roles
* getAccessToken() - returns the encoded access token
* isError() - returns if there was an authentication error
* getError() - returns the error query param

If the 'code' query parameter is present keycloak.init will remove it from the URL (using window.history.replaceState) and request an access token from the server.

We could store the access token in HTML5 storage, but that is risky due to XSS hacks (maybe it could be an optional feature to store in session or local storage). An alternative is to just keep it in memory. Storing it in memory means that a page refresh would loose the token so the user would have to click the login again. If cookies are permitted by the realm the user wouldn't have to actually login, the user would just be redirected back to the application. 

An optimization would be to add a feature to TokenService that returns an access code if the user is already logged in. This would also be useful for other types of applications to automatically login users that are logged in to the sso realm.

We need to enable CORS support for the TokenService at least. We also need one more feature in the TokenService to retrieve the user profile for the current user (supporting 'Authorization bearer' or keycloak identity cookie), again this is something all applications will need.

Config passed to init should contain one or more redirect uri's and keycloak.js should use the one that closest matches the current page for the redirect_uri param. Further we can support loading a specific fragment after the callback has been processed by keycloak.js. The specific fragment to load could be passed in to keycloak.login and encoded into the state param (for example keycloak.login('#/secretpage')).

For application configuration we need to add one or more valid redirect uris and one or more web origins. As the credentials for a HTML5 application is public it's even more important that we validate that the redirect_uri param matches one of the pre-configured redirect uris. In the past I proposed the idea of allowing a redirect uri to be a pattern, but this is explicitly not recommended by the oauth2 spec, so we should require the redirect_uri value to be an exact match of one of the pre-configured redirects.

We'd should probably also provide keycloak-angular.js that wraps keycloak.js up nicely for Angular apps.


More information about the keycloak-dev mailing list