Javascript Adapter The Keycloak Server comes with a Javascript library you can use to secure HTML/Javascript applications. This library is referencable directly from the keycloak server. You can also download the adapter from Keycloak's download site if you want a static copy of this library. It works in the same way as other application adapters except that your browser is driving the OAuth redirect protocol rather than the server. The disadvantage of using this approach is that you have a non-confidential, public client. This makes it more important that you register valid redirect URLs and make sure your domain name is secured. To use this adapter, you must first configure an application (or client) through the Keycloak Admin Console. You should select public for the Client Type field. As public clients can't be verified with a client secret you are required to configure one or more valid redirect uris as well. Once you've configured the application click on the Installation tab and download the keycloak.json file. This file should be hosted in your web-server at the same root as your HTML pages. Alternatively you can either specify the URL for this file, or manually configure the adapter. Next you have to initialize the adapter in your application. An example on how to do this is shown below. ]]> To specify the location of the keycloak.json file: Or finally to manually configure the adapter: You can also pass login-required or check-sso to the init function. Login required will redirect to the login form on the server, while check-sso will redirect to the auth server to check if the user is already logged in to the realm. For example: After you login, your application will be able to make REST calls using bearer token authentication. Here's an example pulled from the customer-portal-js example that comes with the distribution. var loadData = function () { document.getElementById('username').innerText = keycloak.username; var url = 'http://localhost:8080/database/customers'; var req = new XMLHttpRequest(); req.open('GET', url, true); req.setRequestHeader('Accept', 'application/json'); req.setRequestHeader('Authorization', 'Bearer ' + keycloak.token); req.onreadystatechange = function () { if (req.readyState == 4) { if (req.status == 200) { var users = JSON.parse(req.responseText); var html = ''; for (var i = 0; i < users.length; i++) { html += '

' + users[i] + '

'; } document.getElementById('customers').innerHTML = html; console.log('finished loading data'); } } } req.send(); }; var loadFailure = function () { document.getElementById('customers').innerHTML = 'Failed to load data. Check console log'; }; var reloadData = function () { keycloak.updateToken().success(loadData).error(loadFailure); } ]]>
The loadData() method builds an HTTP request setting the Authorization header to a bearer token. The keycloak.token points to the access token the browser obtained when it logged you in. The loadFailure() method is invoked on a failure. The reloadData() function calls keycloak.onValidAccessToken() passing in the loadData() and loadFailure() callbacks. The keycloak.onValidAcessToken() method checks to see if the access token hasn't expired. If it hasn't, and your oauth login returned a refresh token, this method will refresh the access token. Finally, if successful, it will invoke the success callback, which in this case is the loadData() method. To refresh the token if it's expired call the updateToken method. This method returns a promise object which can be used to invoke a function on success or failure. This method can be used to wrap functions that should only be called with a valid token. For example the following method will refresh the token if it expires within 30 seconds, and then invoke the specified function. If the token is valid for more than 30 seconds it will just call the specified function.
Session status iframe By default the JavaScript adapter creates a non-visible iframe that is used to detect if a single-sign out has occured. This does not require any network traffic, instead the status is retrieved from a special status cookie. This feature can be disabled by setting checkLoginIframe: false in the options passed to the init method.
Older browsers The JavaScript adapter depends on Base64 (window.btoa and window.atob) and HTML5 History API. If you need to support browsers that don't provide those (for example IE9) you'll need to add polyfillers. Example polyfill libraries: Base64 - https://github.com/davidchambers/Base64.js HTML5 History - https://github.com/devote/HTML5-History-API
JavaScript Adapter reference
Constructor
Properties authenticated - true if the user is authenticated token - the base64 encoded token that can be sent in the Authorization header in requests to services tokenParsed - the parsed token subject - the user id idToken - the id token if claims is enabled for the application, null otherwise idTokenParsed - the parsed id token realmAccess - the realm roles associated with the token resourceAccess - the resource roles assocaited with the token refreshToken - the base64 encoded token that can be used to retrieve a new token refreshTokenParsed - the parsed refresh token
Methods init(options) Called to initialize the adapter. Options is an Object, where: onLoad - specifies an action to do on load, can be either 'login-required' or 'check-sso' token - set an initial value for the token refreshToken - set an initial value for the refresh token checkLoginIframe - set to enable/disable monitoring login state (default is true) checkLoginIframeInterval - set the interval to check login state (default is 5 seconds) Returns promise to set functions to be invoked on success or error. login(options) Redirects to login form on (options is an optional object with redirectUri and/or prompt fields) Options is an Object, where: redirectUri - specifies the uri to redirect to after login prompt - can be set to 'none' to check if the user is logged in already (if not logged in a login form is not displayed) loginHint - used to pre-fill the username/email field on the login form createLoginUrl(options) Returns the url to login form on (options is an optional object with redirectUri and/or prompt fields) Options is an Object, where: redirectUri - specifies the uri to redirect to after login prompt - can be set to 'none' to check if the user is logged in already (if not logged in a login form is not displayed) logout(options) Redirects to logout Options is an Object, where: redirectUri - specifies the uri to redirect to after logout createLogoutUrl(options) Returns logout out Options is an Object, where: redirectUri - specifies the uri to redirect to after logout accountManagement() Redirects to account management createAccountUrl() Returns the url to account management hasRealmRole(role) Returns true if the token has the given realm role hasResourceRole(role, resource) Returns true if the token has the given role for the resource (resource is optional, if not specified clientId is used) loadUserProfile() Loads the users profile Returns promise to set functions to be invoked on success or error. isTokenExpired(minValidity) Returns true if the token has less than minValidity seconds left before it expires (minValidity is optional, if not specified 0 is used) updateToken(minValidity) If the token expires within minValidity seconds (minValidity is optional, if not specified 0 is used) the token is refreshed. If the session status iframe is enabled, the session status is also checked. Returns promise to set functions that can be invoked if the token is still valid, or if the token is no longer valid. For example:
Callback Events The adapter supports setting callback listeners for certain events. For example: onReady(authenticated) - called when the adapter is initialized onAuthSuccess - called when a user is successfully authenticated onAuthError - called if there was an error during authentication onAuthRefreshSuccess - called when the token is refreshed onAuthRefreshError - called if there was an error while trying to refresh the token onAuthLogout - called if the user is logged out (will only be called if the session status iframe is enabled, or in Cordova mode)