Modernize documentation of JavaScript adapter (#20081)

Closes #19792

Co-authored-by: Andrew Munro <amunro@redhat.com>
This commit is contained in:
Jon Koops 2023-05-08 12:21:53 +00:00 committed by GitHub
parent 6f4b9885ca
commit 1d2a98d747
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 94 additions and 174 deletions

View file

@ -1,90 +1,64 @@
[[_javascript_adapter]] [[_javascript_adapter]]
=== JavaScript adapter === JavaScript adapter
{project_name} comes with a client-side JavaScript library that can be used to secure HTML5/JavaScript applications. The JavaScript adapter has built-in support for Cordova applications. {project_name} comes with a client-side JavaScript library called `keycloak-js` that can be used to secure web applications. The adapter also comes with built-in support for Cordova applications.
A good practice is to include the JavaScript adapter in your application using a package manager like NPM or Yarn. The `keycloak-js` package is available on the following locations: ==== Installation
* NPM: https://www.npmjs.com/package/keycloak-js The adapter is distributed in several ways, but we recommend that you install the https://www.npmjs.com/package/keycloak-js[`keycloak-js`] package from NPM:
* Yarn: https://yarnpkg.com/package/keycloak-js
Alternatively, the library can be retrieved directly from the {project_name} server at `{kc_js_path}/keycloak.js` and is also distributed as a ZIP archive. [source,bash]
----
npm install keycloak-js
----
Alternatively, the library can be retrieved directly from the {project_name} server at `{kc_js_path}/keycloak.js` and is also distributed as a ZIP archive. We are however considering the inclusion of the adapter directly from the Keycloak server as deprecated, and this functionality might be removed in the future.
One important thing to note about using client-side applications is that the client has to be a public client as there is no secure way to store client ==== {project_name} server configuration
credentials in a client-side application. This makes it very important to make sure the redirect URIs you have configured for the client are correct and as specific as possible.
To use the JavaScript adapter you must first create a client for your application in the {project_name} Admin Console. Make sure `public` One important thing to consider about using client-side applications is that the client has to be a public client as there is no secure way to store client credentials in a client-side application. This consideration makes it very important to make sure the redirect URIs you have configured for the client are correct and as specific as possible.
is selected for `Access Type`. You achieve this in Capability config by turning OFF client authentication toggle.
To use the adapter, create a client for your application in the {project_name} Admin Console. Make the client public by toggling *Client authentication* to *Off* on the *Capability config* page.
You also need to configure `Valid Redirect URIs` and `Web Origins`. Be as specific as possible as failing to do so may result in a security vulnerability. You also need to configure `Valid Redirect URIs` and `Web Origins`. Be as specific as possible as failing to do so may result in a security vulnerability.
Once the client is created click on the `Action` tab in the upper right corner and select `Download adapter config`. ==== Using the adapter
Select `Keycloak OIDC JSON` for `Format Option` then click `Download`. The downloaded `keycloak.json` file should be
hosted on your web server at the same location as your HTML pages.
Alternatively, you can skip the configuration file and manually configure the adapter. The following example shows how to initialize the adapter. Make sure that you replace the options passed to the `Keycloak` constructor with those of the client you have configured.
The following example shows how to initialize the JavaScript adapter:
[source,html]
----
<html>
<head>
<script src="keycloak.js"></script>
<script>
function initKeycloak() {
const keycloak = new Keycloak();
keycloak.init().then(function(authenticated) {
alert(authenticated ? 'authenticated' : 'not authenticated');
}).catch(function() {
alert('failed to initialize');
});
}
</script>
</head>
<body onload="initKeycloak()">
<!-- your page content goes here -->
</body>
</html>
----
If the `keycloak.json` file is in a different location you can specify it:
[source,javascript] [source,javascript]
---- ----
const keycloak = new Keycloak('http://localhost:8080/myapp/keycloak.json'); import Keycloak from 'keycloak-js';
----
Alternatively, you can pass in a JavaScript object with the required configuration instead:
[source,javascript,subs="attributes+"]
----
const keycloak = new Keycloak({ const keycloak = new Keycloak({
url: 'http://keycloak-server${kc_base_path}', url: 'http://keycloak-server${kc_base_path}',
realm: 'myrealm', realm: 'myrealm',
clientId: 'myapp' clientId: 'myapp'
}); });
try {
const authenticated = await keycloak.init();
console.log(`User is ${authenticated ? 'authenticated' : 'not authenticated'}`);
} catch (error) {
console.error('Failed to initialize adapter:', error);
}
---- ----
By default to authenticate you need to call the `login` function. However, there are two options available to make the adapter automatically authenticate. You To authenticate, you call the `login` function. Two options exist to make the adapter automatically authenticate. You can pass `login-required` or `check-sso` to the `init()` function.
can pass `login-required` or `check-sso` to the init function. `login-required` will authenticate the client if the user is logged-in to {project_name}
or display the login page if not. `check-sso` will only authenticate the client if the user is already logged-in, if the user is not logged-in the browser will be
redirected back to the application and remain unauthenticated.
You can configure a _silent_ `check-sso` option. * `login-required` authenticates the client if the user is logged in to {project_name} or displays the login page if the user is not logged in.
With this feature enabled, your browser won't do a full redirect to the {project_name} server and back to your application, but this action will be performed in a hidden iframe, so your application resources only need to be loaded and parsed once by the browser when the app is initialized and not again after the redirect back from {project_name} to your app. * `check-sso` only authenticates the client if the user is already logged in. If the user is not logged in, the browser is redirected back to the application and remains unauthenticated.
This is particularly useful in case of SPAs (Single Page Applications).
To enable the _silent_ `check-sso`, you have to provide a `silentCheckSsoRedirectUri` attribute in the init method. You can configure a _silent_ `check-sso` option. With this feature enabled, your browser will not perform a full redirect to the {project_name} server and back to your application, but this action will be performed in a hidden iframe. Therefore, your application resources are only loaded and parsed once by the browser, namely when the application is initialized and not again after the redirect back from {project_name} to your application. This approach is particularly useful in case of SPAs (Single Page Applications).
This URI needs to be a valid endpoint in the application (and of course it must be configured as a valid redirect for the client in the {project_name} Admin Console):
To enable the _silent_ `check-sso`, you provide a `silentCheckSsoRedirectUri` attribute in the init method. Make sure this URI is a valid endpoint in the application; it must be configured as a valid redirect for the client in the {project_name} Admin Console:
[source,javascript] [source,javascript]
---- ----
keycloak.init({ keycloak.init({
onLoad: 'check-sso', onLoad: 'check-sso',
silentCheckSsoRedirectUri: window.location.origin + '/silent-check-sso.html' silentCheckSsoRedirectUri: `${location.origin}/silent-check-sso.html`
}) });
---- ----
The page at the silent check-sso redirect uri is loaded in the iframe after successfully checking your authentication state and retrieving the tokens from the {project_name} server. The page at the silent check-sso redirect uri is loaded in the iframe after successfully checking your authentication state and retrieving the tokens from the {project_name} server.
@ -92,16 +66,17 @@ It has no other task than sending the received tokens to the main application an
[source,html] [source,html]
---- ----
<!doctype html>
<html> <html>
<body> <body>
<script> <script>
parent.postMessage(location.href, location.origin) parent.postMessage(location.href, location.origin);
</script> </script>
</body> </body>
</html> </html>
---- ----
Please keep in mind that this page at the specified location must be provided by the application itself and is _not_ part of the JavaScript adapter! Remember that this page must be served by your application at the specified location in `silentCheckSsoRedirectUri` and is _not_ part of the adapter.
WARNING: _Silent_ `check-sso` functionality is limited in some modern browsers. Please see the <<_modern_browsers,Modern Browsers with Tracking Protection Section>>. WARNING: _Silent_ `check-sso` functionality is limited in some modern browsers. Please see the <<_modern_browsers,Modern Browsers with Tracking Protection Section>>.
@ -111,7 +86,7 @@ To enable `login-required` set `onLoad` to `login-required` and pass to the init
---- ----
keycloak.init({ keycloak.init({
onLoad: 'login-required' onLoad: 'login-required'
}) });
---- ----
After the user is authenticated the application can make requests to RESTful services secured by {project_name} by including the bearer token in the After the user is authenticated the application can make requests to RESTful services secured by {project_name} by including the bearer token in the
@ -119,48 +94,34 @@ After the user is authenticated the application can make requests to RESTful ser
[source,javascript] [source,javascript]
---- ----
const loadData = function () { async function fetchUsers() {
document.getElementById('username').innerText = keycloak.subject; const response = await fetch('/api/users', {
headers: {
const url = 'http://localhost:8080/restful-service'; accept: 'application/json',
authorization: `Bearer ${keycloak.token}`
const 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) {
alert('Success');
} else if (req.status == 403) {
alert('Forbidden');
}
}
} }
});
req.send(); return response.json();
}; }
---- ----
One thing to keep in mind is that the access token by default has a short life expiration so you may need to refresh the access token prior to sending the One thing to keep in mind is that the access token by default has a short life expiration so you may need to refresh the access token prior to sending the request. You refresh this token by calling the `updateToken()` method. This method returns a Promise, which makes it easy to invoke the service only if the token was successfully refreshed and displays an error to the user if it was not refreshed. For example:
request. You can do this by the `updateToken` method. The `updateToken` method returns a promise which makes it easy to invoke the service only if the
token was successfully refreshed and display an error to the user if it wasn't. For example:
[source,javascript] [source,javascript]
---- ----
keycloak.updateToken(30).then(function() { try {
loadData(); await keycloak.updateToken(30);
}).catch(function() { } catch (error) {
alert('Failed to refresh token'); console.error('Failed to refresh token:', error);
}); }
const users = await fetchUsers();
---- ----
==== Session Status iframe ==== Session Status iframe
By default, the JavaScript adapter creates a hidden iframe that is used to detect if a Single-Sign Out has occurred. By default, the adapter creates a hidden iframe that is used to detect if a Single-Sign Out has occurred. This iframe does not require any network traffic. Instead the status is retrieved by looking at a special status cookie. This feature can be disabled by setting `checkLoginIframe: false` in the options passed to the `init()` method.
This does not require any network traffic, instead the status is retrieved by looking at a special status cookie.
This feature can be disabled by setting `checkLoginIframe: false` in the options passed to the `init` method.
You should not rely on looking at this cookie directly. Its format can change and it's also associated with the URL of the {project_name} server, not You should not rely on looking at this cookie directly. Its format can change and it's also associated with the URL of the {project_name} server, not
your application. your application.
@ -170,20 +131,16 @@ WARNING: Session Status iframe functionality is limited in some modern browsers.
[[_javascript_implicit_flow]] [[_javascript_implicit_flow]]
==== Implicit and hybrid flow ==== Implicit and hybrid flow
By default, the JavaScript adapter uses the https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[Authorization Code] flow. By default, the adapter uses the https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[Authorization Code] flow.
With this flow the {project_name} server returns an authorization code, not an authentication token, to the application. The JavaScript adapter exchanges With this flow, the {project_name} server returns an authorization code, not an authentication token, to the application. The JavaScript adapter exchanges the `code` for an access token and a refresh token after the browser is redirected back to the application.
the `code` for an access token and a refresh token after the browser is redirected back to the application.
{project_name} also supports the https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth[Implicit] flow where an access token {project_name} also supports the https://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth[Implicit] flow where an access token is sent immediately after successful authentication with {project_name}. This flow may have better performance than the standard flow because no additional request exists to exchange the code for tokens, but it has implications when the access token expires.
is sent immediately after successful authentication with {project_name}. This may have better performance than standard flow, as there is no additional
request to exchange the code for tokens, but it has implications when the access token expires.
However, sending the access token in the URL fragment can be a security vulnerability. For example the token could be leaked through web server logs and or However, sending the access token in the URL fragment can be a security vulnerability. For example the token could be leaked through web server logs and or
browser history. browser history.
To enable implicit flow, you need to enable the `Implicit Flow Enabled` flag for the client in the {project_name} Admin Console. To enable implicit flow, you enable the *Implicit Flow Enabled* flag for the client in the {project_name} Admin Console. You also pass the parameter `flow` with the value `implicit` to `init` method:
You also need to pass the parameter `flow` with value `implicit` to `init` method:
[source,javascript] [source,javascript]
---- ----
@ -192,15 +149,11 @@ keycloak.init({
}) })
---- ----
One thing to note is that only an access token is provided and there is no refresh token. This means that once the access token has expired the application Note that only an access token is provided and no refresh token exists. This situation means that once the access token has expired, the application has to redirect to {project_name} again to obtain a new access token.
has to do the redirect to the {project_name} again to obtain a new access token.
{project_name} also supports the https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth[Hybrid] flow. {project_name} also supports the https://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth[Hybrid] flow.
This requires the client to have both the `Standard Flow Enabled` and `Implicit Flow Enabled` flags enabled in the admin console. This flow requires the client to have both the *Standard Flow* and *Implicit Flow* enabled in the Admin Console. The {project_name} server then sends both the code and tokens to your application. The access token can be used immediately while the code can be exchanged for access and refresh tokens. Similar to the implicit flow, the hybrid flow is good for performance because the access token is available immediately.
The {project_name} server will then send both the code and tokens to your application.
The access token can be used immediately while the code can be exchanged for access and refresh tokens.
Similar to the implicit flow, the hybrid flow is good for performance because the access token is available immediately.
But, the token is still sent in the URL, and the security vulnerability mentioned earlier may still apply. But, the token is still sent in the URL, and the security vulnerability mentioned earlier may still apply.
One advantage in the Hybrid flow is that the refresh token is made available to the application. One advantage in the Hybrid flow is that the refresh token is made available to the application.
@ -211,16 +164,15 @@ For the Hybrid flow, you need to pass the parameter `flow` with value `hybrid` t
---- ----
keycloak.init({ keycloak.init({
flow: 'hybrid' flow: 'hybrid'
}) });
---- ----
[#hybrid-apps-with-cordova] [#hybrid-apps-with-cordova]
==== Hybrid Apps with Cordova ==== Hybrid Apps with Cordova
Keycloak support hybrid mobile apps developed with https://cordova.apache.org/[Apache Cordova]. The JavaScript adapter has two modes for this: `cordova` and `cordova-native`: {project_name} supports hybrid mobile apps developed with https://cordova.apache.org/[Apache Cordova]. The adapter has two modes for this: `cordova` and `cordova-native`:
The default is cordova, which the adapter will automatically select if no adapter type has been configured and window.cordova is present. The default is `cordova`, which the adapter automatically selects if no adapter type has been explicitly configured and `window.cordova` is present. When logging in, it opens an https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-inappbrowser/[InApp Browser] that lets the user interact with {project_name} and afterwards returns to the app by redirecting to `http://localhost`. Because of this behavior, you whitelist this URL as a valid redirect-uri in the client configuration section of the Admin Console.
When logging in, it will open an https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-inappbrowser/[InApp Browser] that lets the user interact with {project_name} and afterwards returns to the app by redirecting to `http://localhost`. Because of this, you must whitelist this URL as a valid redirect-uri in the client configuration section of the Admin Console.
While this mode is easy to set up, it also has some disadvantages: While this mode is easy to set up, it also has some disadvantages:
@ -230,21 +182,18 @@ While this mode is easy to set up, it also has some disadvantages:
Use this example app to help you get started: https://github.com/keycloak/keycloak/tree/master/examples/cordova Use this example app to help you get started: https://github.com/keycloak/keycloak/tree/master/examples/cordova
The alternative mode `cordova-native` takes a different approach. The alternative mode is`cordova-native`, which takes a different approach. It opens the login page using the system's browser. After the user has authenticated, the browser redirects back into the application using a special URL. From there, the {project_name} adapter can finish the login by reading the code or token from the URL.
It opens the login page using the system's browser.
After the user has authenticated, the browser redirects back into the app using a special URL.
From there, the {project_name} adapter can finish the login by reading the code or token from the URL.
You can activate the native mode by passing the adapter type `cordova-native` to the `init` method: You can activate the native mode by passing the adapter type `cordova-native` to the `init()` method:
[source,javascript] [source,javascript]
---- ----
keycloak.init({ keycloak.init({
adapter: 'cordova-native' adapter: 'cordova-native'
}) });
---- ----
This adapter required two additional plugins: This adapter requires two additional plugins:
* https://github.com/google/cordova-plugin-browsertab[cordova-plugin-browsertab]: allows the app to open webpages in the system's browser * https://github.com/google/cordova-plugin-browsertab[cordova-plugin-browsertab]: allows the app to open webpages in the system's browser
* https://github.com/e-imaxina/cordova-plugin-deeplinks[cordova-plugin-deeplinks]: allow the browser to redirect back to your app by special URLs * https://github.com/e-imaxina/cordova-plugin-deeplinks[cordova-plugin-deeplinks]: allow the browser to redirect back to your app by special URLs
@ -252,12 +201,12 @@ This adapter required two additional plugins:
The technical details for linking to an app differ on each platform and special setup is needed. The technical details for linking to an app differ on each platform and special setup is needed.
Please refer to the Android and iOS sections of the https://github.com/e-imaxina/cordova-plugin-deeplinks/blob/master/README.md[deeplinks plugin documentation] for further instructions. Please refer to the Android and iOS sections of the https://github.com/e-imaxina/cordova-plugin-deeplinks/blob/master/README.md[deeplinks plugin documentation] for further instructions.
There are different kinds of links for opening apps: custom schemes (i.e. `myapp://login` or `android-app://com.example.myapp/https/example.com/login`) and https://developer.apple.com/ios/universal-links/[Universal Links (iOS)]) / https://developer.android.com/training/app-links/deep-linking[Deep Links (Android)]. Different kinds of links exist for opening apps:
While the former are easier to set up and tend to work more reliably, the later offer extra security as they are unique and only the owner of a domain can register them. * custom schemes, such as `myapp://login` or `android-app://com.example.myapp/https/example.com/login`
Custom-URLs are deprecated on iOS. * https://developer.apple.com/ios/universal-links/[Universal Links (iOS)]) / https://developer.android.com/training/app-links/deep-linking[Deep Links (Android)].
We recommend that you use universal links, combined with a fallback site with a custom-url link on it for best reliability. While the former are easier to set up and tend to work more reliably, the latter offer extra security because they are unique and only the owner of a domain can register them. Custom-URLs are deprecated on iOS. For best reliability, we recommend that you use universal links combined with a fallback site that uses a custom-url link.
Furthermore, we recommend the following steps to improve compatibility with the Keycloak Adapter: Furthermore, we recommend the following steps to improve compatibility with the adapter:
* Universal Links on iOS seem to work more reliably with `response-mode` set to `query` * Universal Links on iOS seem to work more reliably with `response-mode` set to `query`
* To prevent Android from opening a new instance of your app on redirect add the following snippet to `config.xml`: * To prevent Android from opening a new instance of your app on redirect add the following snippet to `config.xml`:
@ -272,7 +221,7 @@ There is an example app that shows how to use the native-mode: https://github.co
[#custom-adapters] [#custom-adapters]
==== Custom Adapters ==== Custom Adapters
Sometimes it's necessary to run the JavaScript client in environments that are not supported by default (such as Capacitor). To make it possible to use the JavasScript client in these kind of unknown environments is possible to pass a custom adapter. For example a 3rd party library could provide such an adapter to make it possible to run the JavaScript client without issues: In some situations, you may need to run the adapter in environments that are not supported by default, such as Capacitor. To use the JavasScript client in these environments, you can pass a custom adapter. For example, a third-party library could provide such an adapter to make it possible to reliably run the adapter:
[source,javascript] [source,javascript]
---- ----
@ -312,52 +261,25 @@ keycloak.init({
Naturally you can also do this without TypeScript by omitting the type information, but ensuring implementing the interface properly will then be left entirely up to you. Naturally you can also do this without TypeScript by omitting the type information, but ensuring implementing the interface properly will then be left entirely up to you.
==== Earlier Browsers
The JavaScript adapter depends on Base64 (window.btoa and window.atob), HTML5 History API and optionally the Promise API.
If you need to support browsers that do not have these available (for example, IE9) you need to add polyfillers.
Example polyfill libraries:
* Base64 - https://github.com/davidchambers/Base64.js
* HTML5 History - https://github.com/devote/HTML5-History-API
* Promise - https://github.com/stefanpenner/es6-promise
[[_modern_browsers]] [[_modern_browsers]]
==== Modern Browsers with Tracking Protection ==== Modern Browsers with Tracking Protection
In the latest versions of some browsers various cookies policies are applied to prevent tracking of the users by third-parties, In the latest versions of some browsers, various cookies policies are applied to prevent tracking of the users by third parties, such as SameSite in Chrome or completely blocked third-party cookies. Those policies are likely to become more restrictive and adopted by other browsers over time. Eventually cookies in third-party contexts may become completely unsupported and blocked by the browsers. As a result, the affected adapter features might ultimately be deprecated.
like SameSite in Chrome or completely blocked third-party cookies. It is expected that those policies will become even
more restrictive and adopted by other browsers over time, eventually leading to cookies in third-party contexts to be
completely unsupported and blocked by the browsers. The adapter features affected by this might get deprecated in the
future.
Javascript adapter relies on third-party cookies for Session Status iframe, _silent_ `check-sso` and partially also for The adapter relies on third-party cookies for Session Status iframe, _silent_ `check-sso` and partially also for regular (non-silent) `check-sso`. Those features have limited functionality or are completely disabled based on how restrictive the browser is regarding cookies. The adapter tries to detect this setting and reacts accordingly.
regular (non-silent) `check-sso`. Those features have limited functionality or are completely disabled based on how
the browser is restrictive regarding cookies. The adapter tries to detect this setting and reacts accordingly.
===== Browsers with "SameSite=Lax by Default" Policy ===== Browsers with "SameSite=Lax by Default" Policy
All features are supported if SSL / TLS connection is configured on the {project_name} side as well as on the application All features are supported if SSL / TLS connection is configured on the {project_name} side as well as on the application side. For example, Chrome is affected starting with version 84.
side. Affected is for example Chrome starting with
version 84.
===== Browsers with Blocked Third-Party Cookies ===== Browsers with Blocked Third-Party Cookies
Session Status iframe is not supported and is automatically disabled if such browser behavior is detected by the JS adapter. Session Status iframe is not supported and is automatically disabled if such browser behavior is detected by the adapter. This means the adapter cannot use a session cookie for Single Sign-Out detection and must rely purely on tokens. As a result, when a user logs out in another window, the application using the adapter will not be logged out until the application tries to refresh the Access Token. Therefore, consider setting the Access Token Lifespan to a relatively short time, so that the logout is detected as soon as possible. For more details, see link:{adminguide_link}#_timeouts[Session and Token Timeouts].
This means the adapter cannot use session cookie for Single Sign-Out detection and have to rely purely on tokens. This
implies that when user logs out in another window, the application using JavaScript adapter won't be logged out until it
tries to refresh the Access Token. Therefore, it is recommended to set Access Token Lifespan to relatively short time, so
that the logout is detected rather sooner than later. Please see link:{adminguide_link}#_timeouts[Session and Token Timeouts].
_Silent_ `check-sso` is not supported and falls back to regular (non-silent) `check-sso` by default. This behaviour can _Silent_ `check-sso` is not supported and falls back to regular (non-silent) `check-sso` by default. This behavior can be changed by setting `silentCheckSsoFallback: false` in the options passed to the `init` method. In this case, `check-sso` will be completely disabled if restrictive browser behavior is detected.
be changed by setting `silentCheckSsoFallback: false` in the options passed to the `init` method. In this case, `check-sso`
will be completely disabled if restrictive browser behavior is detected.
Regular `check-sso` is affected as well. Since Session Status iframe is unsupported, an additional redirect to {project_name} Regular `check-sso` is affected as well. Since Session Status iframe is unsupported, an additional redirect to {project_name} has to be made when the adapter is initialized to check the user's login status. This check is different from the standard behavior when the iframe is used to tell whether the user is logged in, and the redirect is performed only when the user is logged out.
has to be made when the adapter is initialized to check user's login status. This is different from standard behavior when
the iframe is used to tell whether the user is logged in, and the redirect is performed only when logged out.
An affected browser is for example Safari starting with version 13.1. An affected browser is for example Safari starting with version 13.1.
==== JavaScript Adapter Reference ==== API Reference
===== Constructor ===== Constructor
@ -542,12 +464,12 @@ For example:
[source,javascript] [source,javascript]
---- ----
keycloak.loadUserProfile() try {
.then(function(profile) { const profile = await keycloak.loadUserProfile();
alert(JSON.stringify(profile, null, " ")) console.log('Retrieved user profile:', profile);
}).catch(function() { } catch (error) {
alert('Failed to load user profile'); console.error('Failed to load user profile:', error);
}); }
---- ----
*isTokenExpired(minValidity)* *isTokenExpired(minValidity)*
@ -566,16 +488,12 @@ For example:
[source,javascript] [source,javascript]
---- ----
keycloak.updateToken(5) try {
.then(function(refreshed) { const refreshed = await keycloak.updateToken(5);
if (refreshed) { console.log(refreshed ? 'Token was refreshed' : 'Token is still valid');
alert('Token was successfully refreshed'); } catch (error) {
} else { console.error('Failed to refresh the token:', error);
alert('Token is still valid');
} }
}).catch(function() {
alert('Failed to refresh the token, or the session has expired');
});
---- ----
*clearToken()* *clearToken()*
@ -587,12 +505,12 @@ Invoking this results in onAuthLogout callback listener being invoked.
===== Callback Events ===== Callback Events
The adapter supports setting callback listeners for certain events. Keep in mind that these have to be set before the call to the `init` function. The adapter supports setting callback listeners for certain events. Keep in mind that these have to be set before the call to the `init()` method.
For example: For example:
[source,javascript] [source,javascript]
---- ----
keycloak.onAuthSuccess = function() { alert('authenticated'); } keycloak.onAuthSuccess = () => console.log('Authenticated!');
---- ----
The available events are: The available events are:

View file

@ -26,3 +26,5 @@ $evaluation.grant()
{&quot;\n&quot; {&quot;\n&quot;
{end {end
{$v {$v
location.origin
keycloak.token