This section describes how you can secure applications and services with OpenID Connect using Keycloak.
2.1. Available Endpoints
As a fully-compliant OpenID Connect Provider implementation, Keycloak exposes a set of endpoints that applicationsand services can use to authenticate and authorize their users.
This section describes some of the key endpoints that your application and service should use wheninteracting with Keycloak.
2.1.1. Endpoints
The most important endpoint to understand is the well-known
configuration endpoint. It lists endpoints and other configuration options relevant to the OpenID Connect implementation in Keycloak. The endpoint is:
/realms/{realm-name}/.well-known/openid-configuration
To obtain the full URL, add the base URL for Keycloak and replace {realm-name}
with the name of your realm. For example:
http://localhost:8080/realms/master/.well-known/openid-configuration
Some RP libraries retrieve all required endpoints from this endpoint, but for others you might need to list the endpoints individually.
Authorization endpoint
/realms/{realm-name}/protocol/openid-connect/auth
The authorization endpoint performs authentication of the end-user. This authentication is done by redirecting the user agent to this endpoint.
For more details see the Authorization Endpoint section in the OpenID Connect specification.
Token endpoint
/realms/{realm-name}/protocol/openid-connect/token
The token endpoint is used to obtain tokens. Tokens can either be obtained by exchanging an authorization code or by supplying credentials directly depending on what flow is used.The token endpoint is also used to obtain new access tokens when they expire.
For more details, see the Token Endpoint section in the OpenID Connect specification.
Userinfo endpoint
/realms/{realm-name}/protocol/openid-connect/userinfo
The userinfo endpoint returns standard claims about the authenticated user; this endpoint is protected by a bearer token.
For more details, see the Userinfo Endpoint section in the OpenID Connect specification.
Logout endpoint
/realms/{realm-name}/protocol/openid-connect/logout
The logout endpoint logs out the authenticated user.
The user agent can be redirected to the endpoint, which causes the active user session to be logged out. The user agent is then redirected back to the application.
The endpoint can also be invoked directly by the application. To invoke this endpoint directly, the refresh token needs to be included as well as the credentials required to authenticate the client.
Certificate endpoint
/realms/{realm-name}/protocol/openid-connect/certs
The certificate endpoint returns the public keys enabled by the realm, encoded as a JSON Web Key (JWK). Depending on the realm settings, one or more keys can be enabled for verifying tokens. For more information, see the Server Administration Guide and the JSON Web Key specification.
Introspection endpoint
/realms/{realm-name}/protocol/openid-connect/token/introspect
The introspection endpoint is used to retrieve the active state of a token. In other words, you can use it to validate an access or refresh token.This endpoint can only be invoked by confidential clients.
For more details on how to invoke on this endpoint, see OAuth 2.0 Token Introspection specification.
Introspection endpoint triggered with application/jwt header
You can invoke an introspection endpoint with the HTTP header Accept: application/jwt
instead of Accept: application/json
. In case of application/jwt
, the responsemay contain the additional claim jwt
with the full JWT access token, which can be useful especially if the token to be introspected was a lightweight access token. This requires that you enable Support JWT claim in Introspection Response
on the client advanced settings, which triggers the token introspection.
Dynamic Client Registration endpoint
/realms/{realm-name}/clients-registrations/openid-connect
The dynamic client registration endpoint is used to dynamically register clients.
For more details, see the Client Registration chapter and theOpenID Connect Dynamic Client Registration specification.
Token Revocation endpoint
/realms/{realm-name}/protocol/openid-connect/revoke
The token revocation endpoint is used to revoke tokens. Both refresh tokens and access tokens are supported by this endpoint. When revoking a refresh token, the user consent for the corresponding client is also revoked.
For more details on how to invoke on this endpoint, see OAuth 2.0 Token Revocation specification.
Device Authorization endpoint
/realms/{realm-name}/protocol/openid-connect/auth/device
The device authorization endpoint is used to obtain a device code and a user code. It can be invoked by confidential or public clients.
For more details on how to invoke on this endpoint, see OAuth 2.0 Device Authorization Grant specification.
Backchannel Authentication endpoint
/realms/{realm-name}/protocol/openid-connect/ext/ciba/auth
The backchannel authentication endpoint is used to obtain an auth_req_id that identifies the authentication request made by the client. It can only be invoked by confidential clients.
For more details on how to invoke on this endpoint, see OpenID Connect Client Initiated Backchannel Authentication Flow specification.
Also refer to other places of Keycloak documentation like Client Initiated Backchannel Authentication Grant section of this guide and Client Initiated Backchannel Authentication Grant section of Server Administration Guide.
2.2. Supported Grant Types
This section describes the different grant types available to relaying parties.
2.2.1. Authorization code
The Authorization Code flow redirects the user agent to Keycloak. Once the user has successfully authenticated with Keycloak, anAuthorization Code is created and the user agent is redirected back to the application. The application then uses the authorization code along with itscredentials to obtain an Access Token, Refresh Token and ID Token from Keycloak.
The flow is targeted towards web applications, but is also recommended for native applications, including mobile applications, where it is possible to embeda user agent.
For more details refer to the Authorization Code Flow in the OpenID Connect specification.
2.2.2. Implicit
The Implicit flow works similarly to the Authorization Code flow, but instead of returning an Authorization Code, the Access Token and ID Token isreturned. This approach reduces the need for the extra invocation to exchange the Authorization Code for an Access Token. However, it does not include a RefreshToken. This results in the need to permit Access Tokens with a long expiration; however, that approach is not practical because it is very hard to invalidate these tokens. Alternatively, you canrequire a new redirect to obtain a new Access Token once the initial Access Token has expired. The Implicit flow is useful if the application only wants toauthenticate the user and deals with logout itself.
You can instead use a Hybrid flow where both the Access Token and an Authorization Code are returned.
One thing to note is that both the Implicit flow and Hybrid flow have potential security risks as the Access Token may be leaked through web server logs andbrowser history. You can somewhat mitigate this problem by using short expiration for Access Tokens.
For more details, see the Implicit Flow in the OpenID Connect specification.
Per current OAuth 2.0 Security Best Current Practice, this flow should not be used.This flow is removed from the future OAuth 2.1 specification.
2.2.3. Resource Owner Password Credentials
Resource Owner Password Credentials, referred to as Direct Grant in Keycloak, allows exchanging user credentials for tokens.Per current OAuth 2.0 Security Best Practices,this flow should not be used, preferring alternative methods such as Device Authorization Grant or Authorization code.
The limitations of using this flow include:
User credentials are exposed to the application
Applications need login pages
Application needs to be aware of the authentication scheme
Changes to authentication flow requires changes to application
No support for identity brokering or social login
Flows are not supported (user self-registration, required actions, and so on.)
Security concerns with this flow include:
Involving more than Keycloak in handling of credentials
Increased vulnerable surface area where credential leaks can happen
Creating an ecosystem where users trust another application for entering their credentials and not Keycloak
For a client to be permitted to use the Resource Owner Password Credentials grant, the client has to have the Direct Access Grants Enabled
option enabled.
This flow is not included in OpenID Connect, but is a part of the OAuth 2.0 specification.It is removed from the future OAuth 2.1 specification.
For more details, see the Resource Owner Password Credentials Grant chapter in the OAuth 2.0 specification.
Example using CURL
The following example shows how to obtain an access token for a user in the realm master
with username user
and password password
. The example is usingthe confidential client myclient
:
curl \ -d "client_id=myclient" \ -d "client_secret=40cc097b-2a57-4c17-b36a-8fdf3fc2d578" \ -d "username=user" \ -d "password=password" \ -d "grant_type=password" \ "http://localhost:8080/realms/master/protocol/openid-connect/token"
2.2.4. Client credentials
Client Credentials are used when clients (applications and services) want to obtain access on behalf of themselves rather than on behalf of a user. For example, these credentials can be useful for background services that apply changes to the system in general rather than for a specific user.
Keycloak provides support for clients to authenticate either with a secret or with public/private keys.
This flow is not included in OpenID Connect, but is a part of the OAuth 2.0 specification.
For more details, see the Client Credentials Grant chapter in the OAuth 2.0 specification.
2.2.5. Device Authorization Grant
Device Authorization Grant is used by clients running on internet-connected devices that have limited input capabilities or lack a suitable browser.
The application requests that Keycloak provide a device code and a user code.
Keycloak creates a device code and a user code.
Keycloak returns a response including the device code and the user code to the application.
The application provides the user with the user code and the verification URI. The user accesses a verification URI to be authenticated by using another browser.
The application repeatedly polls Keycloak until Keycloak completes the user authorization.
If user authentication is complete, the application obtains the device code.
The application uses the device code along with its credentials to obtain an Access Token, Refresh Token and ID Token from Keycloak.
For more details, see the OAuth 2.0 Device Authorization Grant specification.
2.2.6. Client Initiated Backchannel Authentication Grant
Client Initiated Backchannel Authentication Grant is used by clients who want to initiate the authentication flow by communicating with the OpenID Provider directly without redirect through the user’s browser like OAuth 2.0’s authorization code grant.
The client requests from Keycloak an auth_req_id that identifies the authentication request made by the client. Keycloak creates the auth_req_id.
After receiving this auth_req_id, this client repeatedly needs to poll Keycloak to obtain an Access Token, Refresh Token, and ID Token from Keycloak in return for the auth_req_id until the user is authenticated.
In case that client uses ping
mode, it does not need to repeatedly poll the token endpoint, but it can wait for the notification sent by Keycloak to the specified Client Notification Endpoint.The Client Notification Endpoint can be configured in the Keycloak Admin Console. The details of the contract for Client Notification Endpoint are described in the CIBA specification.
For more details, see OpenID Connect Client Initiated Backchannel Authentication Flow specification.
Also refer to other places of Keycloak documentation such as Backchannel Authentication Endpoint of this guide and Client Initiated Backchannel Authentication Grant section of Server Administration Guide.For the details about FAPI CIBA compliance, see the FAPI section of this guide.
2.3. Keycloak specific errors
Keycloak server can send errors to the client application in the OIDC authentication response with parameters error=temporarily_unavailable
and error_description=authentication_expired
.Keycloak sends this error when a user is authenticated and has an SSO session, but the authentication session expired in the current browser tab and hence the Keycloak server cannot automatically do SSOre-authentication of the user and redirect back to client with a successful response. When a client application receives this type of error, it is ideal to retry authentication immediately and send a newOIDC authentication request to the Keycloak server, which should typically always authenticate the user due to the SSO session and redirect back. For more details, seethe Server Administration Guide.
2.4. Keycloak Java adapters
Keycloak Java Adapters were removed from Keycloak codebase and they are not supported anymore. For more details about how to integrate Keycloak with Java applications, consider looking at theKeycloak Quickstart GitHub Repository. |
2.5. Keycloak JavaScript adapter
Keycloak 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.
2.5.1. Installation
The adapter is distributed in several ways, but we recommend that you install the keycloak-js
package from NPM:
npm install keycloak-js
Alternatively, the library can be retrieved directly from the Keycloak server at /js/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.
2.5.2. Keycloak server configuration
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.
To use the adapter, create a client for your application in the Keycloak 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.
2.5.3. Using 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.
import Keycloak from 'keycloak-js';const keycloak = new Keycloak({ url: 'http://keycloak-server${kc_base_path}', realm: 'myrealm', 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);}
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.
login-required
authenticates the client if the user is logged in to Keycloak or displays the login page if the user is not logged in.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.
You can configure a silent check-sso
option. With this feature enabled, your browser will not perform a full redirect to the Keycloak 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 Keycloak to your application. This approach is particularly useful in case of SPAs (Single Page Applications).
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 Keycloak Admin Console:
keycloak.init({ onLoad: 'check-sso', 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 Keycloak server.It has no other task than sending the received tokens to the main application and should only look like this:
<!doctype html><html><body> <script> parent.postMessage(location.href, location.origin); </script></body></html>
Remember that this page must be served by your application at the specified location in silentCheckSsoRedirectUri
and is not part of the adapter.
Silent check-sso functionality is limited in some modern browsers. Please see the Modern Browsers with Tracking Protection Section. |
To enable login-required
set onLoad
to login-required
and pass to the init method:
keycloak.init({ onLoad: 'login-required'});
After the user is authenticated the application can make requests to RESTful services secured by Keycloak by including the bearer token in theAuthorization
header. For example:
async function fetchUsers() { const response = await fetch('/api/users', { headers: { accept: 'application/json', authorization: `Bearer ${keycloak.token}` } }); 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 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:
try { await keycloak.updateToken(30);} catch (error) { console.error('Failed to refresh token:', error);}const users = await fetchUsers();
Both access and refresh token are stored in memory and are not persisted in any kind of storage. Therefore, these tokens should never be persisted to prevent hijacking attacks. |
2.5.4. Session Status iframe
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.
You should not rely on looking at this cookie directly. Its format can change and it’s also associated with the URL of the Keycloak server, notyour application.
Session Status iframe functionality is limited in some modern browsers. Please see Modern Browsers with Tracking Protection Section. |
2.5.5. Implicit and hybrid flow
By default, the adapter uses the Authorization Code flow.
With this flow, the Keycloak 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.
Keycloak also supports the Implicit flow where an access token is sent immediately after successful authentication with Keycloak. 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.
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 orbrowser history.
To enable implicit flow, you enable the Implicit Flow Enabled flag for the client in the Keycloak Admin Console. You also pass the parameter flow
with the value implicit
to init
method:
keycloak.init({ flow: 'implicit'})
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 Keycloak again to obtain a new access token.
Keycloak also supports the Hybrid flow.
This flow requires the client to have both the Standard Flow and Implicit Flow enabled in the Admin Console. The Keycloak 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.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.
For the Hybrid flow, you need to pass the parameter flow
with value hybrid
to the init
method:
keycloak.init({ flow: 'hybrid'});
2.5.6. Hybrid Apps with Cordova
Keycloak supports hybrid mobile apps developed with Apache Cordova. The adapter has two modes for this: cordova
and cordova-native
:
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 InApp Browser that lets the user interact with Keycloak 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.
While this mode is easy to set up, it also has some disadvantages:
The InApp-Browser is a browser embedded in the app and is not the phone’s default browser. Therefore it will have different settings and stored credentials will not be available.
The InApp-Browser might also be slower, especially when rendering more complex themes.
There are security concerns to consider, before using this mode, such as that it is possible for the app to gain access to the credentials of the user, as it has full control of the browser rendering the login page, so do not allow its use in apps you do not trust.
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 Keycloak 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:
keycloak.init({ adapter: 'cordova-native'});
This adapter requires two additional plugins:
cordova-plugin-browsertab: allows the app to open webpages in the system’s browser
cordova-plugin-deeplinks: allow the browser to redirect back to your app by special URLs
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 deeplinks plugin documentation for further instructions.
Different kinds of links exist for opening apps:* custom schemes, such as myapp://login
or android-app://com.example.myapp/https/example.com/login
* Universal Links (iOS)) / Deep Links (Android).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 adapter:
Universal Links on iOS seem to work more reliably with
response-mode
set toquery
To prevent Android from opening a new instance of your app on redirect add the following snippet to
config.xml
:
<preference name="AndroidLaunchMode" value="singleTask" />
2.5.7. Custom Adapters
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:
import Keycloak from 'keycloak-js';import KeycloakCapacitorAdapter from 'keycloak-capacitor-adapter';const keycloak = new Keycloak();keycloak.init({ adapter: KeycloakCapacitorAdapter,});
This specific package does not exist, but it gives a pretty good example of how such an adapter could be passed into the client.
It’s also possible to make your own adapter, to do so you will have to implement the methods described in the KeycloakAdapter
interface. For example the following TypeScript code ensures that all the methods are properly implemented:
import Keycloak, { KeycloakAdapter } from 'keycloak-js';// Implement the 'KeycloakAdapter' interface so that all required methods are guaranteed to be present.const MyCustomAdapter: KeycloakAdapter = { login(options) { // Write your own implementation here. } // The other methods go here...};const keycloak = new Keycloak();keycloak.init({ adapter: MyCustomAdapter,});
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.
2.5.8. 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, 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.
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.
Browsers with "SameSite=Lax by Default" Policy
All features are supported if SSL / TLS connection is configured on the Keycloak side as well as on the application side. For example, Chrome is affected starting with version 84.
Browsers with Blocked Third-Party Cookies
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 Session and Token Timeouts.
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.
Regular check-sso
is affected as well. Since Session Status iframe is unsupported, an additional redirect to Keycloak 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.
An affected browser is for example Safari starting with version 13.1.
2.5.9. API Reference
Constructor
new Keycloak();new Keycloak('http://localhost/keycloak.json');new Keycloak({ url: 'http://localhost', realm: 'myrealm', clientId: 'myApp' });
Properties
- authenticated
Is
true
if the user is authenticated,false
otherwise.- token
The base64 encoded token that can be sent in the
Authorization
header in requests to services.- tokenParsed
The parsed token as a JavaScript object.
- subject
The user id.
- idToken
The base64 encoded ID token.
- idTokenParsed
The parsed id token as a JavaScript object.
- realmAccess
The realm roles associated with the token.
- resourceAccess
The resource roles associated with the token.
- refreshToken
The base64 encoded refresh token that can be used to retrieve a new token.
- refreshTokenParsed
The parsed refresh token as a JavaScript object.
- timeSkew
The estimated time difference between the browser time and the Keycloak server in seconds. This value is just an estimation, but is accurateenough when determining if a token is expired or not.
- responseMode
Response mode passed in init (default value is fragment).
- flow
Flow passed in init.
- adapter
Allows you to override the way that redirects and other browser-related functions will be handled by the library.Available options:
"default" - the library uses the browser api for redirects (this is the default)
"cordova" - the library will try to use the InAppBrowser cordova plugin to load keycloak login/registration pages (this is used automatically when the library is working in a cordova ecosystem)
"cordova-native" - the library tries to open the login and registration page using the phone’s system browser using the BrowserTabs cordova plugin. This requires extra setup for redirecting back to the app (see Hybrid Apps with Cordova).
"custom" - allows you to implement a custom adapter (only for advanced use cases)
- responseType
Response type sent to Keycloak with login requests. This is determined based on the flow value used during initialization, but can be overridden by setting this value.
Methods
init(options)
Called to initialize the adapter.
Options is an Object, where:
useNonce - Adds a cryptographic nonce to verify that the authentication response matches the request (default is
true
).onLoad - Specifies an action to do on load. Supported values are
login-required
orcheck-sso
.silentCheckSsoRedirectUri - Set the redirect uri for silent authentication check if onLoad is set to 'check-sso'.
silentCheckSsoFallback - Enables fall back to regular
check-sso
when silentcheck-sso
is not supported by the browser (default istrue
).token - Set an initial value for the token.
refreshToken - Set an initial value for the refresh token.
idToken - Set an initial value for the id token (only together with token or refreshToken).
scope - Set the default scope parameter to the Keycloak login endpoint. Use a space-delimited list of scopes. Those typicallyreference Client scopes defined on a particular client. Note that the scope
openid
willalways be added to the list of scopes by the adapter. For example, if you enter the scope optionsaddress phone
, then the requestto Keycloak will contain the scope parameterscope=openid address phone
. Note that the default scope specified here is overwritten if thelogin()
options specify scope explicitly.timeSkew - Set an initial value for skew between local time and Keycloak server in seconds (only together with token or refreshToken).
checkLoginIframe - Set to enable/disable monitoring login state (default is
true
).checkLoginIframeInterval - Set the interval to check login state (default is 5 seconds).
responseMode - Set the OpenID Connect response mode send to Keycloak server at login request. Valid values are
query
orfragment
. Default value isfragment
, which means that after successful authentication will Keycloak redirect to JavaScript application with OpenID Connect parameters added in URL fragment. This is generally safer and recommended overquery
.flow - Set the OpenID Connect flow. Valid values are
standard
,implicit
orhybrid
.enableLogging - Enables logging messages from Keycloak to the console (default is
false
).pkceMethod - The method for Proof Key Code Exchange (PKCE) to use. Configuring this value enables the PKCE mechanism. Available options:
"S256" - The SHA256 based PKCE method (default)
false - PKCE is disabled.
acrValues - Generates the
acr_values
parameter which refers to authentication context class reference and allows clients to declare the required assurance level requirements, e.g. authentication mechanisms. See Section 4. acr_values request values and level of assurance in OpenID Connect MODRNA Authentication Profile 1.0.messageReceiveTimeout - Set a timeout in milliseconds for waiting for message responses from the Keycloak server. This is used, for example, when waiting for a message during 3rd party cookies check. The default value is 10000.
locale - When onLoad is 'login-required', sets the 'ui_locales' query param in compliance with section 3.1.2.1 of the OIDC 1.0 specification.
Returns a promise that resolves when initialization completes.
login(options)
Redirects to login form.
Options is an optional Object, where:
redirectUri - Specifies the uri to redirect to after login.
prompt - This parameter allows to slightly customize the login flow on the Keycloak server side.For example, enforce displaying the login screen in case of value
login
. Or enforce displaying of consent screen for the valueconsent
in case that client hasConsent Required
.Finally it is possible use the valuenone
to make sure that login screen is not displayed to the user, which is useful just to check SSO for the case when user was alreadyauthenticated before (This is related to theonLoad
check with valuecheck-sso
described above).maxAge - Used just if user is already authenticated. Specifies maximum time since the authentication of user happened. If user is already authenticated for longer time than
maxAge
, the SSO is ignored and he will need to re-authenticate again.loginHint - Used to pre-fill the username/email field on the login form.
scope - Override the scope configured in
init
with a different value for this specific login.idpHint - Used to tell Keycloak to skip showing the login page and automatically redirect to the specified identityprovider instead. More info in the Identity Provider documentation.
acr - Contains the information about
acr
claim, which will be sent insideclaims
parameter to the Keycloak server. Typical usageis for step-up authentication. Example of use{ values: ["silver", "gold"], essential: true }
. See OpenID Connect specificationand Step-up authentication documentation for more details.acrValues - Generates the
acr_values
parameter which refers to authentication context class reference and allows clients to declare the required assurance level requirements, e.g. authentication mechanisms. See Section 4. acr_values request values and level of assurance in OpenID Connect MODRNA Authentication Profile 1.0.action - If the value is
register
, the user is redirected to the registration page. See Registration requested by client section for more details.If the value isUPDATE_PASSWORD
or another supported required action, the user will be redirected to the reset password page or the other required action page. However, if the user is not authenticated, the user will be sent to the login page and redirected after authentication.See Application Initiated Action section for more details.locale - Sets the 'ui_locales' query param in compliance with section 3.1.2.1 of the OIDC 1.0 specification.
cordovaOptions - Specifies the arguments that are passed to the Cordova in-app-browser (if applicable). Options
hidden
andlocation
are not affected by these arguments. All available options are defined at https://cordova.apache.org/docs/en/latest/reference/cordova-plugin-inappbrowser/. Example of use:{ zoom: "no", hardwareback: "yes" }
;
createLoginUrl(options)
Returns the URL to login form.
Options is an optional Object, which supports same options as the function login
.
logout(options)
Redirects to logout.
Options is an Object, where:
redirectUri - Specifies the uri to redirect to after logout.
createLogoutUrl(options)
Returns the URL to log out the user.
Options is an Object, where:
redirectUri - Specifies the uri to redirect to after logout.
register(options)
Redirects to registration form. Shortcut for login with option action = 'register'
Options are same as for the login method but 'action' is set to 'register'
createRegisterUrl(options)
Returns the url to registration page. Shortcut for createLoginUrl with option action = 'register'
Options are same as for the createLoginUrl method but 'action' is set to 'register'
accountManagement()
Redirects to the Account Console.
createAccountUrl(options)
Returns the URL to the Account Console.
Options is an Object, where:
redirectUri - Specifies the uri to redirect to when redirecting back to the application.
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 a promise that resolves with the profile.
For example:
try { const profile = await keycloak.loadUserProfile(); console.log('Retrieved user profile:', profile);} catch (error) { console.error('Failed to load user profile:', 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 5 is used) the token is refreshed.If -1 is passed as the minValidity, the token will be forcibly refreshed.If the session status iframe is enabled, the session status is also checked.
Returns a promise that resolves with a boolean indicating whether or not the token has been refreshed.
For example:
try { const refreshed = await keycloak.updateToken(5); console.log(refreshed ? 'Token was refreshed' : 'Token is still valid');} catch (error) { console.error('Failed to refresh the token:', error);}
clearToken()
Clear authentication state, including tokens.This can be useful if application has detected the session was expired, for example if updating token fails.
Invoking this results in onAuthLogout callback listener being invoked.
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()
method.
For example:
keycloak.onAuthSuccess = () => console.log('Authenticated!');
The available events are:
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).
onTokenExpired - Called when the access token is expired. If a refresh token is available the token can be refreshed with updateToken, or in cases where it is not (that is, with implicit flow) you can redirect to the login screen to obtain a new access token.
2.6. Keycloak Node.js adapter
Keycloak provides a Node.js adapter built on top of Connect to protect server-side JavaScript apps - the goal was to be flexible enough to integrate with frameworks like Express.js.
The library can be downloaded directly from Keycloak organization and the source is available atGitHub.
To use the Node.js adapter, first you must create a client for your application in the Keycloak Admin Console. The adapter supports public, confidential, and bearer-only access type. Which one to choose depends on the use-case scenario.
Once the client is created, click Action at the top right and choose Download adapter config. For Format, choose *Keycloak OIDC JSON and click Download. The downloaded keycloak.json
file is at the root folder of your project.
2.6.1. Installation
Assuming you have already installed Node.js, create a folder for your application:
mkdir myapp && cd myapp
Use npm init
command to create a package.json
for your application. Now add the Keycloak connect adapter in the dependencies list:
"dependencies": { "keycloak-connect": "25.0.4" }
2.6.2. Usage
- Instantiate a Keycloak class
The
Keycloak
class provides a central point for configurationand integration with your application. The simplest creationinvolves no arguments.
In the root directory of your project create a file called server.js
and add the following code:
const session = require('express-session'); const Keycloak = require('keycloak-connect'); const memoryStore = new session.MemoryStore(); const keycloak = new Keycloak({ store: memoryStore });
Install the express-session
dependency:
npm install express-session
To start the server.js
script, add the following command in the 'scripts' section of the package.json
:
"scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "node server.js" },
Now we have the ability to run our server with following command:
npm run start
By default, this will locate a file named keycloak.json
alongsidethe main executable of your application, in our case on the root folder, to initialize Keycloak specificsettings such as public key, realm name, various URLs.
In that case a Keycloak deployment is necessary to access Keycloak admin console.
Please visit links on how to deploy a Keycloak admin console withPodman or Docker
Now we are ready to obtain the keycloak.json
file by visiting the Keycloak Admin Console → clients (left sidebar) → choose your client → Installation → Format Option → Keycloak OIDC JSON → Download
Paste the downloaded file on the root folder of our project.
Instantiation with this method results in all the reasonable defaultsbeing used. As alternative, it’s also possible to provide a configurationobject, rather than the keycloak.json
file:
const kcConfig = { clientId: 'myclient', bearerOnly: true, serverUrl: 'http://localhost:8080', realm: 'myrealm', realmPublicKey: 'MIIBIjANB...' }; const keycloak = new Keycloak({ store: memoryStore }, kcConfig);
Applications can also redirect users to their preferred identity provider by using:
const keycloak = new Keycloak({ store: memoryStore, idpHint: myIdP }, kcConfig);
- Configuring a web session store
If you want to use web sessions to manageserver-side state for authentication, you need to initialize the
Keycloak(…)
with at least astore
parameter, passing in the actualsession store thatexpress-session
is using.
const session = require('express-session'); const memoryStore = new session.MemoryStore(); // Configure session app.use( session({ secret: 'mySecret', resave: false, saveUninitialized: true, store: memoryStore, }) ); const keycloak = new Keycloak({ store: memoryStore });
- Passing a custom scope value
By default, the scope value
openid
is passed as a query parameter to Keycloak’s login URL, but you can add an additional custom value:
const keycloak = new Keycloak({ scope: 'offline_access' });
2.6.3. Installing middleware
Once instantiated, install the middleware into your connect-capable app:
In order to do so, first we have to install Express:
npm install express
then require Express in our project as outlined below:
const express = require('express'); const app = express();
and configure Keycloak middleware in Express, by adding at the code below:
app.use( keycloak.middleware() );
Last but not least, let’s set up our server to listen for HTTP requests on port 3000 by adding the following code to main.js
:
app.listen(3000, function () { console.log('App listening on port 3000'); });
2.6.4. Configuration for proxies
If the application is running behind a proxy that terminates an SSL connectionExpress must be configured per the express behind proxies guide.Using an incorrect proxy configuration can result in invalid redirect URIsbeing generated.
Example configuration:
const app = express(); app.set( 'trust proxy', true ); app.use( keycloak.middleware() );
2.6.5. Protecting resources
- Simple authentication
To enforce that a user must be authenticated before accessing a resource,simply use a no-argument version of
keycloak.protect()
:
app.get( '/complain', keycloak.protect(), complaintHandler );
- Role-based authorization
To secure a resource with an application role for the current app:
app.get( '/special', keycloak.protect('special'), specialHandler );
To secure a resource with an application role for a different app:
app.get( '/extra-special', keycloak.protect('other-app:special'), extraSpecialHandler );
To secure a resource with a realm role:
app.get( '/admin', keycloak.protect( 'realm:admin' ), adminHandler );
- Resource-Based Authorization
Resource-Based Authorization allows you to protect resources, and their specific methods/actions,** based on a set of policies defined in Keycloak, thus externalizing authorization from your application. This is achieved by exposing a
keycloak.enforcer
method which you can use to protect resources.*
app.get('/apis/me', keycloak.enforcer('user:profile'), userProfileHandler);
The keycloak-enforcer
method operates in two modes, depending on the value of the response_mode
configuration option.
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'token'}), userProfileHandler);
If response_mode
is set to token
, permissions are obtained from the server on behalf of the subject represented by the bearer token that was sent to your application. In this case, a new access token is issued by Keycloak with the permissions granted by the server. If the server did not respond with a token with the expected permissions, the request is denied. When using this mode, you should be able to obtain the token from the request as follows:
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'token'}), function (req, res) { const token = req.kauth.grant.access_token.content; const permissions = token.authorization ? token.authorization.permissions : undefined; // show user profile });
Prefer this mode when your application is using sessions and you want to cache previous decisions from the server, as well automatically handle refresh tokens. This mode is especially useful for applications acting as a client and resource server.
If response_mode
is set to permissions
(default mode), the server only returns the list of granted permissions, without issuing a new access token. In addition to not issuing a new token, this method exposes the permissions granted by the server through the request
as follows:
app.get('/apis/me', keycloak.enforcer('user:profile', {response_mode: 'permissions'}), function (req, res) { const permissions = req.permissions; // show user profile });
Regardless of the response_mode
in use, the keycloak.enforcer
method will first try to check the permissions within the bearer token that was sent to your application. If the bearer token already carries the expected permissions, there is no needto interact with the server to obtain a decision. This is specially useful when your clients are capable of obtaining access tokens from the server with the expected permissions before accessing a protected resource, so they can use some capabilities provided by Keycloak Authorization Services such as incremental authorization and avoid additional requests to the server when keycloak.enforcer
is enforcing access to the resource.
By default, the policy enforcer will use the client_id
defined to the application (for instance, via keycloak.json
) to reference a client in Keycloak that supports Keycloak Authorization Services. In this case, the client can not be public given that it is actually a resource server.
If your application is acting as both a public client(frontend) and resource server(backend), you can use the following configuration to reference a differentclient in Keycloak with the policies that you want to enforce:
keycloak.enforcer('user:profile', {resource_server_id: 'my-apiserver'})
It is recommended to use distinct clients in Keycloak to represent your frontend and backend.
If the application you are protecting is enabled with Keycloak authorization services and you have defined client credentials in keycloak.json
, you can push additional claims to the server and make them available to your policies in order to make decisions.For that, you can define a claims
configuration option which expects a function
that returns a JSON with the claims you want to push:
app.get('/protected/resource', keycloak.enforcer(['resource:view', 'resource:write'], { claims: function(request) { return { "http.uri": ["/protected/resource"], "user.agent": // get user agent from request } } }), function (req, res) { // access granted
For more details about how to configure Keycloak to protected your application resources, please take a look at the Authorization Services Guide.
- Advanced authorization
To secure resources based on parts of the URL itself, assuming a role existsfor each section:
function protectBySection(token, request) { return token.hasRole( request.params.section ); } app.get( '/:section/:page', keycloak.protect( protectBySection ), sectionHandler );
Advanced Login Configuration:
By default, all unauthorized requests will be redirected to the Keycloak login page unless your client is bearer-only.However, a confidential or public client may host both browsable and API endpoints. To prevent redirects on unauthenticatedAPI requests and instead return an HTTP 401, you can override the redirectToLogin function.
For example, this override checks if the URL contains /api/ and disables login redirects:
Keycloak.prototype.redirectToLogin = function(req) { const apiReqMatcher = /\/api\//i; return !apiReqMatcher.test(req.originalUrl || req.url); };
2.6.6. Additional URLs
- Explicit user-triggered logout
By default, the middleware catches calls to
/logout
to send the user through aKeycloak-centric logout workflow. This can be changed by specifying alogout
configuration parameter to themiddleware()
call:
app.use( keycloak.middleware( { logout: '/logoff' } ));
When the user-triggered logout is invoked a query parameter redirect_url
can be passed:
https://example.com/logoff?redirect_url=https%3A%2F%2Fexample.com%3A3000%2Flogged%2Fout
This parameter is then used as the redirect url of the OIDC logout endpoint and the user will be redirected tohttps://example.com/logged/out
.
- Keycloak Admin Callbacks
Also, the middleware supports callbacks from the Keycloak console to log out a singlesession or all sessions. By default, these type of admin callbacks occur relativeto the root URL of
/
but can be changed by providing anadmin
parameterto themiddleware()
call:
app.use( keycloak.middleware( { admin: '/callbacks' } );
2.6.7. Complete example
A complete example using the Node.js adapter usage can be found in Keycloak quickstarts for Node.js
2.7. mod_auth_openidc Apache HTTPD Module
Keycloak does not provide any official support to mod_auth_openidc. The instructions below are best-effort and may not be up-to-date.We recommend that you stick to official mod_auth_openidc documentation for more details. |
The mod_auth_openidc is an Apache HTTP plugin for OpenID Connect. If your language/environment supports using Apache HTTPDas a proxy, then you can use mod_auth_openidc to secure your web application with OpenID Connect. Configuration of this moduleis beyond the scope of this document. Please see the mod_auth_openidc GitHub repo for more details on configuration.
To configure mod_auth_openidc you’ll need
The client_id.
The client_secret.
The redirect_uri to your application.
The Keycloak openid-configuration url
mod_auth_openidc specific Apache HTTPD module config.
An example configuration would look like the following.
LoadModule auth_openidc_module modules/mod_auth_openidc.soServerName ${HOSTIP}<VirtualHost *:80> ServerAdmin webmaster@localhost DocumentRoot /var/www/html #this is required by mod_auth_openidc OIDCCryptoPassphrase a-random-secret-used-by-apache-oidc-and-balancer OIDCProviderMetadataURL ${KC_ADDR}/realms/${KC_REALM}/.well-known/openid-configuration OIDCClientID ${CLIENT_ID} OIDCClientSecret ${CLIENT_SECRET} OIDCRedirectURI http://${HOSTIP}/${CLIENT_APP_NAME}/redirect_uri # maps the preferred_username claim to the REMOTE_USER environment variable OIDCRemoteUserClaim preferred_username <Location /${CLIENT_APP_NAME}/> AuthType openid-connect Require valid-user </Location></VirtualHost>
Further information on how to configure mod_auth_openidc can be found on the mod_auth_openidcproject page.
2.8. Financial-grade API (FAPI) Support
Keycloak makes it easier for administrators to make sure that their clients are compliant with these specifications:
This compliance means that the Keycloak server will verify the requirementsfor the authorization server, which are mentioned in the specifications. Keycloak adapters do not have any specific support for the FAPI, hence the required validations on the client (application)side may need to be still done manually or through some other third-party solutions.
2.8.1. FAPI client profiles
To make sure that your clients are FAPI compliant, you can configure Client Policies in your realm as described in the Server Administration Guideand link them to the global client profiles for FAPI support, which are automatically available in each realm. You can use either fapi-1-baseline
or fapi-1-advanced
profile based on which FAPIprofile you need your clients to conform with. You can use also profiles fapi-2-security-profile
or fapi-2-message-signing
for the compliance with FAPI 2 Draft specifications.
In case you want to use Pushed Authorization Request (PAR), it is recommended that your client useboth the fapi-1-baseline
profile and fapi-1-advanced
for PAR requests. Specifically, the fapi-1-baseline
profile contains pkce-enforcer
executor, which makes surethat client use PKCE with secured S256 algorithm. This is not required for FAPI Advanced clients unless they use PAR requests.
In case you want to use CIBA in a FAPI compliant way, make sure that your clients use both fapi-1-advanced
and fapi-ciba
client profiles.There is a need to use the fapi-1-advanced
profile, or other client profile containing the requested executors, as the fapi-ciba
profile contains just CIBA-specific executors.When enforcing the requirements of the FAPI CIBA specification, there is a need for more requirements, such as enforcement of confidential clients or certificate-bound access tokens.
2.8.2. Open Finance Brasil Financial-grade API Security Profile
Keycloak is compliant with the Open Finance Brasil Financial-grade API Security Profile 1.0 Implementers Draft 3.This one is stricter in some requirements than the FAPI 1 Advanced specification and hence it may be needed to configure Client Policiesin the more strict way to enforce some of the requirements. Especially:
If your client does not use PAR, make sure that it uses encrypted OIDC request objects. This can be achieved by using a client profile with the
secure-request-object
executor configured withEncryption Required
enabled.Make sure that for JWS, the client uses the
PS256
algorithm. For JWE, the client should use theRSA-OAEP
withA256GCM
. This may need to be set in all the Client Settings where these algorithms are applicable.
2.8.3. Australia Consumer Data Right (CDR) Security Profile
Keycloak is compliant with the Australia Consumer Data Right Security Profile.
If you want to apply the Australia CDR security profile, you need to use fapi-1-advanced
profile because the Australia CDR security profile is based on FAPI 1.0 Advanced security profile. If your client also applies PAR, make sure that client applies RFC 7637 Proof Key for Code Exchange (PKCE) because the Australia CDR security profile requires that you apply PKCE when applying PAR. This can be achieved by using a client profile with the pkce-enforcer
executor.
2.8.4. TLS considerations
As confidential information is being exchanged, all interactions shall be encrypted with TLS (HTTPS). Moreover, there are some requirements in the FAPI specification forthe cipher suites and TLS protocol versions used. To match these requirements, you can consider configure allowed ciphers. This configuration can be done by settingthe https-protocols
and https-cipher-suites
options. Keycloak uses TLSv1.3
by default and hence it is possibly not needed to change the default settings. However itmay be needed to adjust ciphers if you need to fall back to lower TLS version for some reason. For more details, see Configuring TLS guide.
2.9. OAuth 2.1 Support
Keycloak makes it easier for administrators to make sure that their clients are compliant with these specifications:
This compliance means that the Keycloak server will verify the requirementsfor the authorization server, which are mentioned in the specifications. Keycloak adapters do not have any specific support for the OAuth 2.1, hence the required validations on the client (application)side may need to be still done manually or through some other third-party solutions.
2.9.1. OAuth 2.1 client profiles
To make sure that your clients are OAuth 2.1 compliant, you can configure Client Policies in your realm as described in the Server Administration Guideand link them to the global client profiles for OAuth 2.1 support, which are automatically available in each realm. You can use either oauth-2-1-for-confidential-client
profile for confidential clients or oauth-2-1-for-public-client
profile for public clients.
OAuth 2.1 specification is still a draft and it may change in the future. Hence the Keycloak built-in OAuth 2.1 client profiles can change as well. |
When using OAuth 2.1 profile for public clients, it is recommended to use DPoP preview feature as described in the Server Administration Guide because DPoP binds an access token and a refresh token together with the public part of a client’s key pair. This binding prevents an attacker from using stolen tokens. |
2.10. Recommendations
This section describes some recommendations when securing your applications with Keycloak.
2.10.1. Validating access tokens
If you need to manually validate access tokens issued by Keycloak, you can invoke the Introspection Endpoint.The downside to this approach is that you have to make a network invocation to the Keycloak server. This can be slow and possibly overload theserver if you have too many validation requests going on at the same time. Keycloak issued access tokens are JSON Web Tokens (JWT) digitally signed and encoded using JSON Web Signature (JWS).Because they are encoded in this way, you can locally validate access tokens using the public key of the issuing realm. You can either hard code therealm’s public key in your validation code, or lookup and cache the public key using the certificate endpoint with the Key ID (KID) embedded within theJWS. Depending on what language you code in, many third party libraries exist and they can help you with JWS validation.
2.10.2. Redirect URIs
When using the redirect based flows, be sure to use valid redirect uris for your clients. The redirect uris should be as specific as possible. Thisespecially applies to client-side (public clients) applications. Failing to do so could result in:
Open redirects - this can allow attackers to create spoof links that looks like they are coming from your domain
Unauthorized entry - when users are already authenticated with Keycloak, an attacker can use a public client where redirect uris have not be configured correctly to gain access by redirecting the user without the users knowledge
In production for web applications always use https
for all redirect URIs. Do not allow redirects to http.
A few special redirect URIs also exist:
http://127.0.0.1
This redirect URI is useful for native applications and allows the native application to create a web server on a random port that can be used to obtain theauthorization code. This redirect uri allows any port. Note that per OAuth 2.0 for Native Apps, the use of
localhost
is not recommended and the IP literal127.0.0.1
should be used instead.
urn:ietf:wg:oauth:2.0:oob
If you cannot start a web server in the client (or a browser is not available), you can use the special
urn:ietf:wg:oauth:2.0:oob
redirect uri.When this redirect uri is used, Keycloak displays a page with the code in the title and in a box on the page.The application can either detect that the browser title has changed, or the user can copy and paste the code manually to the application.With this redirect uri, a user can use a different device to obtain a code to paste back to the application.