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.