move stuff
This commit is contained in:
parent
64d41decc7
commit
d3018c6335
22 changed files with 0 additions and 2808 deletions
20
SUMMARY.adoc
20
SUMMARY.adoc
|
@ -8,26 +8,9 @@
|
||||||
.. link:topics/overview_key_concepts.adoc[Key Concepts in Keycloak]
|
.. link:topics/overview_key_concepts.adoc[Key Concepts in Keycloak]
|
||||||
.. link:topics/overview_How_Security_Work_in_Keycloak.adoc[How Security Work in Keycloak?]
|
.. link:topics/overview_How_Security_Work_in_Keycloak.adoc[How Security Work in Keycloak?]
|
||||||
... link:topics/overview_permission_scopes.adoc[Permission Scopes]
|
... link:topics/overview_permission_scopes.adoc[Permission Scopes]
|
||||||
. link:topics/server-installation.adoc[Installation and Configuration of Keycloak Server]
|
|
||||||
. link:topics/providers.adoc[Providers and SPIs]
|
. link:topics/providers.adoc[Providers and SPIs]
|
||||||
. link:topics/openshift.adoc[Running Keycloak Server on OpenShift]
|
|
||||||
. link:topics/admin-permissions.adoc[Master Admin Access Control]
|
. link:topics/admin-permissions.adoc[Master Admin Access Control]
|
||||||
. link:topics/per-realm-admin-permissions.adoc[Per Realm Admin Access Control]
|
. link:topics/per-realm-admin-permissions.adoc[Per Realm Admin Access Control]
|
||||||
. link:topics/adapter-config.adoc[Adapters]
|
|
||||||
.. link:topics/jboss-adapter.adoc[JBoss/Wildfly Adapter]
|
|
||||||
.. link:topics/tomcat-adapter.adoc[Tomcat 6, 7 and 8 Adapters]
|
|
||||||
.. link:topics/jetty9-adapter.adoc[Jetty 9.x Adapters]
|
|
||||||
.. link:topics/jetty8-adapter.adoc[Jetty 8.1.x Adapter]
|
|
||||||
.. link:topics/servlet-filter-adapter.adoc[Java Servlet Filter Adapter]
|
|
||||||
.. link:topics/fuse-adapter.adoc[JBoss Fuse and Apache Karaf Adapter]
|
|
||||||
.. link:topics/javascript-adapter.adoc[Javascript Adapter]
|
|
||||||
.. link:topics/spring-boot-adapter.adoc[Spring Boot Adapter]
|
|
||||||
.. link:topics/spring-security-adapter.adoc[Spring Security Adapter]
|
|
||||||
.. link:topics/installed-applications.adoc[Installed Applications]
|
|
||||||
.. link:topics/logout.adoc[Logout]
|
|
||||||
.. link:topics/adapter_error_handling.adoc[Error Handling]
|
|
||||||
.. link:topics/multi-tenancy.adoc[ Multi Tenancy]
|
|
||||||
.. link:topics/jaas.adoc[JAAS plugin]
|
|
||||||
. link:topics/client-registration.adoc[Client Registration]
|
. link:topics/client-registration.adoc[Client Registration]
|
||||||
. link:topics/identity-broker.adoc[Identity Broker]
|
. link:topics/identity-broker.adoc[Identity Broker]
|
||||||
. link:topics/themes.adoc[Themes]
|
. link:topics/themes.adoc[Themes]
|
||||||
|
@ -48,9 +31,6 @@
|
||||||
. link:topics/cache.adoc[Server Cache]
|
. link:topics/cache.adoc[Server Cache]
|
||||||
. link:topics/saml.adoc[SAML SSO]
|
. link:topics/saml.adoc[SAML SSO]
|
||||||
. link:topics/security-vulnerabilities.adoc[Security Vulnerabilities]
|
. link:topics/security-vulnerabilities.adoc[Security Vulnerabilities]
|
||||||
. link:topics/clustering.adoc[Clustering]
|
|
||||||
. link:topics/application-clustering.adoc[Application Clustering]
|
|
||||||
. link:topics/proxy.adoc[Keycloak Security Proxy]
|
|
||||||
. link:topics/custom-attributes.adoc[Custom User Attributes]
|
. link:topics/custom-attributes.adoc[Custom User Attributes]
|
||||||
. link:topics/protocol-mappers.adoc[OIDC Token and SAML Assertion Mappings]
|
. link:topics/protocol-mappers.adoc[OIDC Token and SAML Assertion Mappings]
|
||||||
. link:topics/auth-spi.adoc[Custom Authentication, Registration, and Required Actions]
|
. link:topics/auth-spi.adoc[Custom Authentication, Registration, and Required Actions]
|
||||||
|
|
|
@ -1,220 +0,0 @@
|
||||||
|
|
||||||
[[_adapter_config]]
|
|
||||||
|
|
||||||
= Adapters
|
|
||||||
|
|
||||||
Keycloak can secure a wide variety of application types.
|
|
||||||
This section defines which application types are supported and how to configure and install them so that you can use Keycloak to secure your applications.
|
|
||||||
|
|
||||||
These client adapters use an extension of the OpenID Connect protocol (a derivate of OAuth 2.0). This extension provides support for clustering, backchannel logout, and other non-standard adminstrative functions.
|
|
||||||
The Keycloak project also provides a separate, standalone, generic, SAML client adapter.
|
|
||||||
But that is describe in a separate document and has a different download.
|
|
||||||
|
|
||||||
|
|
||||||
== General Adapter Config
|
|
||||||
|
|
||||||
Each adapter supported by Keycloak can be configured by a simple JSON text file.
|
|
||||||
This is what one might look like:
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
{
|
|
||||||
"realm" : "demo",
|
|
||||||
"resource" : "customer-portal",
|
|
||||||
"realm-public-key" : "MIGfMA0GCSqGSIb3D...31LwIDAQAB",
|
|
||||||
"auth-server-url" : "https://localhost:8443/auth",
|
|
||||||
"ssl-required" : "external",
|
|
||||||
"use-resource-role-mappings" : false,
|
|
||||||
"enable-cors" : true,
|
|
||||||
"cors-max-age" : 1000,
|
|
||||||
"cors-allowed-methods" : "POST, PUT, DELETE, GET",
|
|
||||||
"bearer-only" : false,
|
|
||||||
"enable-basic-auth" : false,
|
|
||||||
"expose-token" : true,
|
|
||||||
"credentials" : {
|
|
||||||
"secret" : "234234-234234-234234"
|
|
||||||
},
|
|
||||||
|
|
||||||
"connection-pool-size" : 20,
|
|
||||||
"disable-trust-manager": false,
|
|
||||||
"allow-any-hostname" : false,
|
|
||||||
"truststore" : "path/to/truststore.jks",
|
|
||||||
"truststore-password" : "geheim",
|
|
||||||
"client-keystore" : "path/to/client-keystore.jks",
|
|
||||||
"client-keystore-password" : "geheim",
|
|
||||||
"client-key-password" : "geheim"
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
Some of these configuration switches may be adapter specific and some are common across all adapters.
|
|
||||||
For Java adapters you can use `${...}` enclosure as System property replacement.
|
|
||||||
For example `${jboss.server.config.dir}`.
|
|
||||||
Also, you can obtain a template for this config file from the admin console.
|
|
||||||
Go to the realm and select the application you want a template for.
|
|
||||||
Go to the `Installation` tab and this will provide you with a template that includes the public key of the realm.
|
|
||||||
|
|
||||||
Here is a description of each item:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
realm::
|
|
||||||
Name of the realm representing the users of your distributed applications and services.
|
|
||||||
This is _REQUIRED._
|
|
||||||
|
|
||||||
resource::
|
|
||||||
Username of the application.
|
|
||||||
Each application has a username that is used when the application connects with the Keycloak server to turn an access code into an access token (part of the OAuth 2.0 protocol). This is _REQUIRED._
|
|
||||||
|
|
||||||
realm-public-key::
|
|
||||||
PEM format of public key.
|
|
||||||
You can obtain this from the administration console.
|
|
||||||
This is _REQUIRED._
|
|
||||||
|
|
||||||
auth-server-url::
|
|
||||||
The base URL of the Keycloak Server.
|
|
||||||
All other Keycloak pages and REST services are derived from this.
|
|
||||||
It is usually of the form `https://host:port/auth` This is _REQUIRED._
|
|
||||||
|
|
||||||
ssl-required::
|
|
||||||
Ensures that all communication to and from the Keycloak server from the adapter is over HTTPS.
|
|
||||||
This is _OPTIONAL_.
|
|
||||||
The default value is _external_ meaning that HTTPS is required by default for external requests.
|
|
||||||
Valid values are 'all', 'external' and 'none'.
|
|
||||||
|
|
||||||
use-resource-role-mappings::
|
|
||||||
If set to true, the adapter will look inside the token for application level role mappings for the user.
|
|
||||||
If false, it will look at the realm level for user role mappings.
|
|
||||||
This is _OPTIONAL_.
|
|
||||||
The default value is _false_.
|
|
||||||
|
|
||||||
public-client::
|
|
||||||
If set to true, the adapter will not send credentials for the client to Keycloak.
|
|
||||||
The default value is _false_.
|
|
||||||
|
|
||||||
enable-cors::
|
|
||||||
This enables CORS support.
|
|
||||||
It will handle CORS preflight requests.
|
|
||||||
It will also look into the access token to determine valid origins.
|
|
||||||
This is _OPTIONAL_.
|
|
||||||
The default value is _false_.
|
|
||||||
|
|
||||||
cors-max-age::
|
|
||||||
If CORS is enabled, this sets the value of the `Access-Control-Max-Age` header.
|
|
||||||
This is _OPTIONAL_.
|
|
||||||
If not set, this header is not returned in CORS responses.
|
|
||||||
|
|
||||||
cors-allowed-methods::
|
|
||||||
If CORS is enabled, this sets the value of the `Access-Control-Allow-Methods` header.
|
|
||||||
This should be a comma-separated string.
|
|
||||||
This is _OPTIONAL_.
|
|
||||||
If not set, this header is not returned in CORS responses.
|
|
||||||
|
|
||||||
cors-allowed-headers::
|
|
||||||
If CORS is enabled, this sets the value of the `Access-Control-Allow-Headers` header.
|
|
||||||
This should be a comma-separated string.
|
|
||||||
This is _OPTIONAL_.
|
|
||||||
If not set, this header is not returned in CORS responses.
|
|
||||||
|
|
||||||
bearer-only::
|
|
||||||
This tells the adapter to only do bearer token authentication.
|
|
||||||
That is, it will not do OAuth 2.0 redirects, but only accept bearer tokens through the `Authorization` header.
|
|
||||||
This is _OPTIONAL_.
|
|
||||||
The default value is _false_.
|
|
||||||
|
|
||||||
enable-basic-auth::
|
|
||||||
This tells the adapter to also support basic authentication.
|
|
||||||
If this option is enabled, then _secret_ must also be provided.
|
|
||||||
This is _OPTIONAL_.
|
|
||||||
The default value is _false_.
|
|
||||||
|
|
||||||
expose-token::
|
|
||||||
If `true`, an authenticated browser client (via a Javascript HTTP invocation) can obtain the signed access token via the URL `root/k_query_bearer_token`.
|
|
||||||
This is _OPTIONAL_.
|
|
||||||
The default value is _false_.
|
|
||||||
|
|
||||||
credentials::
|
|
||||||
Specify the credentials of the application.
|
|
||||||
This is an object notation where the key is the credential type and the value is the value of the credential type.
|
|
||||||
Currently only `password` is supported.
|
|
||||||
This is _REQUIRED_.
|
|
||||||
|
|
||||||
connection-pool-size::
|
|
||||||
Adapters will make separate HTTP invocations to the Keycloak Server to turn an access code into an access token.
|
|
||||||
This config option defines how many connections to the Keycloak Server should be pooled.
|
|
||||||
This is _OPTIONAL_.
|
|
||||||
The default value is `20`.
|
|
||||||
|
|
||||||
disable-trust-manager::
|
|
||||||
If the Keycloak Server requires HTTPS and this config option is set to `true` you do not have to specify a truststore.
|
|
||||||
While convenient, this setting is not recommended as you will not be verifying the host name of the Keycloak Server.
|
|
||||||
This is _OPTIONAL_.
|
|
||||||
The default value is `false`.
|
|
||||||
|
|
||||||
allow-any-hostname::
|
|
||||||
If the Keycloak Server requires HTTPS and this config option is set to `true` the Keycloak Server's certificate is validated via the truststore, but host name validation is not done.
|
|
||||||
This is not a recommended.
|
|
||||||
This seting may be useful in test environments This is _OPTIONAL_.
|
|
||||||
The default value is `false`.
|
|
||||||
|
|
||||||
truststore::
|
|
||||||
This setting is for Java adapters.
|
|
||||||
The value is the file path to a Java keystore file.
|
|
||||||
If you prefix the path with `classpath:`, then the truststore will be obtained from the deployment's classpath instead.
|
|
||||||
Used for outgoing HTTPS communications to the Keycloak server.
|
|
||||||
Client making HTTPS requests need a way to verify the host of the server they are talking to.
|
|
||||||
This is what the trustore does.
|
|
||||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
|
||||||
You can create this truststore by extracting the public certificate of the Keycloak server's SSL keystore.
|
|
||||||
This is _OPTIONAL_ if `ssl-required` is `none` or `disable-trust-manager` is `true`.
|
|
||||||
|
|
||||||
truststore-password::
|
|
||||||
Password for the truststore keystore.
|
|
||||||
This is _REQUIRED_ if `truststore` is set.
|
|
||||||
|
|
||||||
client-keystore::
|
|
||||||
_Not supported yet, but we will support in future versions._ This setting is for Java adapters.
|
|
||||||
This is the file path to a Java keystore file.
|
|
||||||
This keystore contains client certificate for two-way SSL when the adapter makes HTTPS requests to the Keycloak server.
|
|
||||||
This is _OPTIONAL_.
|
|
||||||
|
|
||||||
client-keystore-password::
|
|
||||||
_Not supported yet, but we will support in future versions._ Password for the client keystore.
|
|
||||||
This is _REQUIRED_ if `client-keystore` is set.
|
|
||||||
|
|
||||||
client-key-password::
|
|
||||||
_Not supported yet, but we will support in future versions._ Password for the client's key.
|
|
||||||
This is _REQUIRED_ if `client-keystore` is set.
|
|
||||||
|
|
||||||
auth-server-url-for-backend-requests::
|
|
||||||
Alternative location of auth-server-url used just for backend requests.
|
|
||||||
It must be absolute URI.
|
|
||||||
Useful especially in cluster (see <<_relative_uri_optimization,Relative URI Optimization>>) or if you would like to use _https_ for browser requests but stick with _http_ for backend requests etc.
|
|
||||||
|
|
||||||
always-refresh-token::
|
|
||||||
If _true_, Keycloak will refresh token in every request.
|
|
||||||
More info in <<_refresh_token_each_req,Refresh token in each request>> .
|
|
||||||
|
|
||||||
register-node-at-startup::
|
|
||||||
If _true_, then adapter will send registration request to Keycloak.
|
|
||||||
It's _false_ by default and useful just in cluster (See <<_registration_app_nodes,Registration of application nodes to Keycloak>>)
|
|
||||||
|
|
||||||
register-node-period::
|
|
||||||
Period for re-registration adapter to Keycloak.
|
|
||||||
Useful in cluster.
|
|
||||||
See <<_registration_app_nodes,Registration of application nodes to Keycloak>> for details.
|
|
||||||
|
|
||||||
token-store::
|
|
||||||
Possible values are _session_ and _cookie_.
|
|
||||||
Default is _session_, which means that adapter stores account info in HTTP Session.
|
|
||||||
Alternative _cookie_ means storage of info in cookie.
|
|
||||||
See <<_stateless_token_store,Stateless token store>> for details.
|
|
||||||
|
|
||||||
principal-attribute::
|
|
||||||
OpenID Connection ID Token attribute to populate the UserPrincipal name with.
|
|
||||||
If token attribute is null, defaults to `sub`.
|
|
||||||
Possible values are `sub`, `preferred_username`, `email`, `name`, `nickname`, `given_name`, `family_name`.
|
|
||||||
|
|
||||||
turn-off-change-session-id-on-login::
|
|
||||||
The session id is changed by default on a successful login on some platforms to plug a security attack vector (Tomcat 8, Jetty9, Undertow/Wildfly). Change this to true if you want to turn this off This is _OPTIONAL_.
|
|
||||||
The default value is _false_.
|
|
|
@ -1,18 +0,0 @@
|
||||||
= KeycloakSecurityContext
|
|
||||||
:doctype: book
|
|
||||||
:sectnums:
|
|
||||||
:toc: left
|
|
||||||
:icons: font
|
|
||||||
:experimental:
|
|
||||||
:sourcedir: .
|
|
||||||
|
|
||||||
The `KeycloakSecurityContext` interface is available if you need to look at the access token directly.
|
|
||||||
This context is also useful if you need to get the encoded access token so you can make additional REST invocations.
|
|
||||||
In servlet environments it is available in secured invocations as an attribute in HttpServletRequest.
|
|
||||||
Or, it is available in secure and insecure requests in the HttpSession for browser apps.
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
httpServletRequest.getAttribute(KeycloakSecurityContext.class.getName());
|
|
||||||
httpServletRequest.getSession().getAttribute(KeycloakSecurityContext.class.getName());
|
|
||||||
----
|
|
|
@ -1,60 +0,0 @@
|
||||||
|
|
||||||
[[_adapter_error_handling]]
|
|
||||||
= Error Handling
|
|
||||||
|
|
||||||
Keycloak has some error handling facilities for servlet based client adapters.
|
|
||||||
When an error is encountered in authentication, keycloak will call `HttpServletResponse.sendError()`.
|
|
||||||
You can set up an error-page within your `web.xml` file to handle the error however you want.
|
|
||||||
Keycloak may throw 400, 401, 403, and 500 errors.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
<error-page>
|
|
||||||
<error-code>404</error-code>
|
|
||||||
<location>/ErrorHandler</location>
|
|
||||||
</error-page>
|
|
||||||
----
|
|
||||||
|
|
||||||
Keycloak also sets an `HttpServletRequest` attribute that you can retrieve.
|
|
||||||
The attribute name is `org.keycloak.adapters.spi.AuthenticationError`.
|
|
||||||
Typecast this object to: `org.keycloak.adapters.OIDCAuthenticationError`.
|
|
||||||
This class can tell you exactly what happened.
|
|
||||||
If this attribute is not set, then the adapter was not responsible for the error code.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
public class OIDCAuthenticationError implements AuthenticationError {
|
|
||||||
public static enum Reason {
|
|
||||||
NO_BEARER_TOKEN,
|
|
||||||
NO_REDIRECT_URI,
|
|
||||||
INVALID_STATE_COOKIE,
|
|
||||||
OAUTH_ERROR,
|
|
||||||
SSL_REQUIRED,
|
|
||||||
CODE_TO_TOKEN_FAILURE,
|
|
||||||
INVALID_TOKEN,
|
|
||||||
STALE_TOKEN,
|
|
||||||
NO_AUTHORIZATION_HEADER
|
|
||||||
}
|
|
||||||
|
|
||||||
private Reason reason;
|
|
||||||
private String description;
|
|
||||||
|
|
||||||
public OIDCAuthenticationError(Reason reason, String description) {
|
|
||||||
this.reason = reason;
|
|
||||||
this.description = description;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Reason getReason() {
|
|
||||||
return reason;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getDescription() {
|
|
||||||
return description;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
|
@ -1,131 +0,0 @@
|
||||||
[[_applicationclustering]]
|
|
||||||
= Application Clustering
|
|
||||||
|
|
||||||
This chapter is focused on clustering support for your own AS7, EAP6 or Wildfly applications, which are secured by Keycloak.
|
|
||||||
We support various deployment scenarios according if your application is:
|
|
||||||
|
|
||||||
* stateless or stateful
|
|
||||||
* distributable (replicated http session) or non-distributable and just relying on sticky sessions provided by loadbalancer
|
|
||||||
* deployed on same or different cluster hosts where keycloak servers are deployed
|
|
||||||
|
|
||||||
The situation is a bit tricky as application communicates with Keycloak directly within user's browser (for example redirecting to login screen), but there is also backend (out-of-bound) communication between keycloak and application, which is hidden from end-user and his browser and hence can't rely on sticky sessions.
|
|
||||||
|
|
||||||
NOTE: To enable distributable (replicated) HTTP Sessions in your application, you may need to do some additional steps.
|
|
||||||
Usually you need to put tag into `WEB-INF/web.xml` file of your application and possibly do some additional steps to configure underlying cluster cache (In case of Wildfly, the implementation of cluster cache is based on Infinispan). These steps are server specific, so consult documentation of your application server for more details.
|
|
||||||
|
|
||||||
== Stateless token store
|
|
||||||
|
|
||||||
By default, the servlet web application secured by Keycloak uses HTTP session to store information about authenticated user account.
|
|
||||||
This means that this info could be replicated across cluster and your application will safely survive failover of some cluster node.
|
|
||||||
|
|
||||||
However if you don't need or don't want to use HTTP Session, you may alternatively save all info about authenticated account into cookie.
|
|
||||||
This is useful especially if your application is:
|
|
||||||
|
|
||||||
* stateless application without need of HTTP Session, but with requirement to be safe to failover of some cluster node
|
|
||||||
* stateful application, but you don't want sensitive token data to be saved in HTTP session
|
|
||||||
* stateless application relying on loadbalancer, which is not aware of sticky sessions (in this case cookie is your only way)
|
|
||||||
|
|
||||||
To configure this, you can add this line to configuration of your adapter in `WEB-INF/keycloak.json` of your application:
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
"token-store": "cookie"
|
|
||||||
----
|
|
||||||
|
|
||||||
Default value of `token-store` is `session`, hence saving data in HTTP session.
|
|
||||||
|
|
||||||
One limitation of cookie store is, that whole info about account is passed in cookie KEYCLOAK_ADAPTER_STATE in each HTTP request.
|
|
||||||
Hence it's not the best for network performance.
|
|
||||||
Another small limitation is limited support for Single-Sign out.
|
|
||||||
It works without issues if you init servlet logout (HttpServletRequest.logout) from this application itself as the adapter will delete the KEYCLOAK_ADAPTER_STATE cookie.
|
|
||||||
But back-channel logout initialized from different application can't be propagated by Keycloak to this application with cookie store.
|
|
||||||
Hence it's recommended to use very short value of access token timeout (1 minute for example).
|
|
||||||
|
|
||||||
== Relative URI optimization
|
|
||||||
|
|
||||||
In many deployment scenarios will be Keycloak and secured applications deployed on same cluster hosts.
|
|
||||||
For this case Keycloak already provides option to use relative URI as value of option _auth-server-url_ in `WEB-INF/keycloak.json` . In this case, the URI of Keycloak server is resolved from the URI of current request.
|
|
||||||
|
|
||||||
For example if your loadbalancer is on _https://loadbalancer.com/myapp_ and auth-server-url is _/auth_, then relative URI of Keycloak is resolved to be _https://loadbalancer.com/auth_ .
|
|
||||||
|
|
||||||
For cluster setup, it may be even better to use option _auth-server-url-for-backend-request_ . This allows to configure that backend requests between Keycloak and your application will be sent directly to same cluster host without additional round-trip through loadbalancer.
|
|
||||||
So for this, it's good to configure values in `WEB-INF/keycloak.json` like this:
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
"auth-server-url": "/auth",
|
|
||||||
"auth-server-url-for-backend-requests": "http://${jboss.host.name}:8080/auth"
|
|
||||||
----
|
|
||||||
|
|
||||||
This would mean that browser requests (like redirecting to Keycloak login screen) will be still resolved relatively to current request URI like _https://loadbalancer.com/myapp_, but backend (out-of-bound) requests between keycloak and your app are sent always to same cluster host with application .
|
|
||||||
|
|
||||||
Note that additionally to network optimization, you may not need "https" in this case as application and keycloak are communicating directly within same cluster host.
|
|
||||||
|
|
||||||
== Admin URL configuration
|
|
||||||
|
|
||||||
Admin URL for particular application can be configured in Keycloak admin console.
|
|
||||||
It's used by Keycloak server to send backend requests to application for various tasks, like logout users or push revocation policies.
|
|
||||||
|
|
||||||
For example logout of user from Keycloak works like this:
|
|
||||||
|
|
||||||
. User sends logout request from one of applications where he is logged.
|
|
||||||
. Then application will send logout request to Keycloak
|
|
||||||
. Keycloak server logout user in itself, and then it re-sends logout request by backend channel to all applications where user is logged.
|
|
||||||
Keycloak is using admin URL for this.
|
|
||||||
So logout is propagated to all apps.
|
|
||||||
|
|
||||||
You may again use relative values for admin URL, but in cluster it may not be the best similarly like in <<_relative_uri_optimization,previous section>> .
|
|
||||||
|
|
||||||
Some examples of possible values of admin URL are:
|
|
||||||
|
|
||||||
http://${jboss.host.name}:8080/myapp::
|
|
||||||
This is best choice if "myapp" is deployed on same cluster hosts like Keycloak and is distributable.
|
|
||||||
In this case Keycloak server sends logout request to itself, hence no communication with loadbalancer or other cluster nodes and no additional network traffic.
|
|
||||||
|
|
||||||
http://${application.session.host}:8080/myapp::
|
|
||||||
Keycloak will track hosts where is particular HTTP Session served and it will send session invalidation message to proper cluster node.
|
|
||||||
|
|
||||||
[[_registration_app_nodes]]
|
|
||||||
== Registration of application nodes to Keycloak
|
|
||||||
|
|
||||||
Previous section describes how can Keycloak send logout request to proper application node.
|
|
||||||
However in some cases admin may want to propagate admin tasks to all registered cluster nodes, not just one of them.
|
|
||||||
For example push new notBefore for realm or application, or logout all users from all applications on all cluster nodes.
|
|
||||||
|
|
||||||
In this case Keycloak should be aware of all application cluster nodes, so it could send event to all of them.
|
|
||||||
To achieve this, we support auto-discovery mechanism:
|
|
||||||
|
|
||||||
. Once new application node joins cluster, it sends registration request to Keycloak server
|
|
||||||
. The request may be re-sent to Keycloak in configured periodic intervals
|
|
||||||
. If Keycloak won't receive re-registration request within specified timeout (should be greater than period from point 2) then it automatically unregister particular node
|
|
||||||
. Node is also unregistered in Keycloak when it sends unregistration request, which is usually during node shutdown or application undeployment.
|
|
||||||
This may not work properly for forced shutdown when undeployment listeners are not invoked, so here you need to rely on automatic unregistration from point 3 .
|
|
||||||
|
|
||||||
Sending startup registrations and periodic re-registration is disabled by default, as it's main usecase is just cluster deployment.
|
|
||||||
In `WEB-INF/keycloak.json` of your application, you can specify:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
"register-node-at-startup": true,
|
|
||||||
"register-node-period": 600,
|
|
||||||
----
|
|
||||||
which means that registration is sent at startup (accurately when 1st request is served by the application node) and then it's resent each 10 minutes.
|
|
||||||
|
|
||||||
In Keycloak admin console you can specify the maximum node re-registration timeout (makes sense to have it bigger than _register-node-period_ from adapter configuration for particular application). Also you can manually add and remove cluster nodes in admin console, which is useful if you don't want to rely on adapter's automatic registration or if you want to remove stale application nodes, which weren't unregistered (for example due to forced shutdown).
|
|
||||||
|
|
||||||
[[_refresh_token_each_req]]
|
|
||||||
== Refresh token in each request
|
|
||||||
|
|
||||||
By default, application adapter tries to refresh access token when it's expired (period can be specified as <<_token_timeouts,Access Token Lifespan>>) . However if you don't want to rely on the fact, that Keycloak is able to successfully propagate admin events like logout to your application nodes, then you have possibility to configure adapter to refresh access token in each HTTP request.
|
|
||||||
|
|
||||||
In `WEB-INF/keycloak.json` you can configure:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
"always-refresh-token": true
|
|
||||||
----
|
|
||||||
|
|
||||||
Note that this has big performance impact.
|
|
||||||
It's useful just if performance is not priority, but security is critical and you can't rely on logout and push notBefore propagation from Keycloak to applications.
|
|
|
@ -1,58 +0,0 @@
|
||||||
= Server Cache
|
|
||||||
|
|
||||||
By default, Keycloak caches realm metadata and users.
|
|
||||||
There are two separate caches, one for realm metadata (realm, application, client, roles, etc...) and one for users.
|
|
||||||
These caches greatly improves the performance of the server.
|
|
||||||
|
|
||||||
== Eviction and Expiration
|
|
||||||
|
|
||||||
By default the user cache contains a maximum of 10000 entries.
|
|
||||||
This is not 10000 users, but 10000 entries in the cache.
|
|
||||||
You can change the maximum number of entries by editing the server configuration `standalone.xml` or `standalone-ha.xml`.
|
|
||||||
Locate the element `cache-container name="keycloak"` and change the eviction policy for the `users` cache.
|
|
||||||
For more information see https://docs.jboss.org/author/display/WFLY10/Infinispan+Subsystem[Infinispan Subsystem documentation].
|
|
||||||
|
|
||||||
== Disabling Caches
|
|
||||||
|
|
||||||
To disable the realm or user cache, you must edit the `keycloak-server.json` file in your distribution.
|
|
||||||
Here's what the config looks like initially.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
"userCache": {
|
|
||||||
"infinispan" : {
|
|
||||||
"enabled": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"realmCache": {
|
|
||||||
"infinispan" : {
|
|
||||||
"enabled": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
----
|
|
||||||
|
|
||||||
To disable the cache set the enabled field to false for the cache you want to disable:
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
"userCache": {
|
|
||||||
"infinispan" : {
|
|
||||||
"enabled": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"realmCache": {
|
|
||||||
"infinispan" : {
|
|
||||||
"enabled": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
----
|
|
||||||
|
|
||||||
== Clear Caches
|
|
||||||
|
|
||||||
To clear the realm or user cache, go to the Keycloak admin console Realm Settings->Cache Config page.
|
|
||||||
On this page you can clear the realm cache or the user cache.
|
|
||||||
This will clear the caches for all realms and not only the selected realm.
|
|
|
@ -1,17 +0,0 @@
|
||||||
|
|
||||||
[[_fuse_adapter]]
|
|
||||||
= JBoss Fuse and Apache Karaf Adapter
|
|
||||||
|
|
||||||
Currently Keycloak supports securing your web applications running inside http://www.jboss.org/products/fuse/overview/[JBoss Fuse] or http://karaf.apache.org/[Apache Karaf] . It leverages <<_jetty8_adapter,Jetty 8 adapter>> as both JBoss Fuse 6.1 and Apache Karaf 3 are bundled with http://eclipse.org/jetty/[Jetty 8.1 server] under the covers and Jetty is used for running various kinds of web applications.
|
|
||||||
|
|
||||||
What is supported for Fuse/Karaf is:
|
|
||||||
|
|
||||||
* Security for classic WAR applications deployed on Fuse/Karaf with https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+War[Pax Web War Extender].
|
|
||||||
* Security for servlets deployed on Fuse/Karaf as OSGI services with https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+Whiteboard[Pax Web Whiteboard Extender].
|
|
||||||
* Security for http://camel.apache.org/[Apache Camel] Jetty endpoints running with http://camel.apache.org/jetty.html[Camel Jetty] component.
|
|
||||||
* Security for http://cxf.apache.org/[Apache CXF] endpoints running on their own separate http://cxf.apache.org/docs/jetty-configuration.html[Jetty engine].
|
|
||||||
* Security for http://cxf.apache.org/[Apache CXF] endpoints running on default engine provided by CXF servlet.
|
|
||||||
* Security for SSH and JMX admin access.
|
|
||||||
* Security for http://hawt.io/[Hawt.io admin console] .
|
|
||||||
|
|
||||||
The best place to start is look at Fuse demo bundled as part of Keycloak examples in directory `examples/fuse` .
|
|
|
@ -1,23 +0,0 @@
|
||||||
|
|
||||||
= Installed Applications
|
|
||||||
|
|
||||||
Keycloak provides two special redirect uris for installed applications.
|
|
||||||
|
|
||||||
[[_installed_applications_url]]
|
|
||||||
== Installed Applications url
|
|
||||||
|
|
||||||
http://localhost
|
|
||||||
|
|
||||||
This returns the code to a web server on the client as a query parameter.
|
|
||||||
Any port number is allowed.
|
|
||||||
This makes it possible to start a web server for the installed application on any free port number without requiring changes in the `Admin Console`.
|
|
||||||
|
|
||||||
[[_installed_applications_urn]]
|
|
||||||
== Installed Applications urn
|
|
||||||
|
|
||||||
`urn:ietf:wg:oauth:2.0:oob`
|
|
||||||
|
|
||||||
If its not possible to start a web server in the client (or a browser is not available) it is possible to 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/paste the code manually to the application.
|
|
||||||
With this redirect uri it is also possible for a user to use a different device to obtain a code to paste back to the application.
|
|
|
@ -1,27 +0,0 @@
|
||||||
|
|
||||||
[[_jaas_adapter]]
|
|
||||||
= JAAS plugin
|
|
||||||
|
|
||||||
It's generally not needed to use JAAS for most of the applications, especially if they are HTTP based, but directly choose one of our adapters.
|
|
||||||
However some applications and systems may still rely on pure legacy JAAS solution.
|
|
||||||
Keycloak provides couple of login modules to help with such use cases.
|
|
||||||
Some login modules provided by Keycloak are:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
org.keycloak.adapters.jaas.DirectAccessGrantsLoginModule::
|
|
||||||
This login module allows to authenticate with username/password from Keycloak database.
|
|
||||||
It's using <<_direct_access_grants,Direct Access Grants>> Keycloak endpoint to validate on Keycloak side if provided username/password is valid.
|
|
||||||
It's useful especially for non-web based systems, which need to rely on JAAS and want to use Keycloak credentials, but can't use classic browser based authentication flow due to their non-web nature.
|
|
||||||
Example of such application could be messaging application or SSH system.
|
|
||||||
|
|
||||||
org.keycloak.adapters.jaas.BearerTokenLoginModule::
|
|
||||||
This login module allows to authenticate with Keycloak access token passed to it through CallbackHandler as password.
|
|
||||||
It may be useful for example in case, when you have Keycloak access token from classic web based authentication flow and your web application then needs to talk to external non-web based system, which rely on JAAS.
|
|
||||||
For example to JMS/messaging system.
|
|
||||||
|
|
||||||
Both login modules have configuration property `keycloak-config-file` where you need to provide location of keycloak.json configuration file.
|
|
||||||
It could be either provided from filesystem or from classpath (in that case you may need value like `classpath:/folder-on-classpath/keycloak.json` ).
|
|
||||||
|
|
||||||
Second property `role-principal-class` allows to specify alternative class for Role principals attached to JAAS Subject.
|
|
||||||
Default value for Role principal is `org.keycloak.adapters.jaas.RolePrincipal` . Note that class should have constructor with single String argument.
|
|
|
@ -1,363 +0,0 @@
|
||||||
|
|
||||||
= Javascript Adapter
|
|
||||||
|
|
||||||
The Keycloak Server comes with a Javascript library you can use to secure HTML/Javascript applications.
|
|
||||||
This library is referenceable directly from the keycloak server.
|
|
||||||
You can also download the adapter from Keycloak's download site if you want a static copy.
|
|
||||||
It works in the same way as other application adapters except that your browser is driving the OAuth redirect protocol rather than the server.
|
|
||||||
|
|
||||||
The disadvantage of using this approach is that you have a non-confidential, public client.
|
|
||||||
This makes it more important that you register valid redirect URLs and make sure your domain name is secured.
|
|
||||||
|
|
||||||
To use this adapter, you must first configure an application (or client) through the `Keycloak Admin Console`.
|
|
||||||
You should select `public` for the `Access Type` field.
|
|
||||||
As public clients can't be verified with a client secret, you are required to configure one or more valid redirect uris.
|
|
||||||
Once you've configured the application, click on the `Installation` tab and download the `keycloak.json` file.
|
|
||||||
This file should be hosted on your web-server at the same root as your HTML pages.
|
|
||||||
Alternatively, you can manually configure the adapter and specify the URL for this file.
|
|
||||||
|
|
||||||
Next, you have to initialize the adapter in your application.
|
|
||||||
An example is shown below.
|
|
||||||
|
|
||||||
[source,html]
|
|
||||||
----
|
|
||||||
<head>
|
|
||||||
<script src="http://<keycloak server>/auth/js/keycloak.js"></script>
|
|
||||||
<script>
|
|
||||||
var keycloak = Keycloak();
|
|
||||||
keycloak.init().success(function(authenticated) {
|
|
||||||
alert(authenticated ? 'authenticated' : 'not authenticated');
|
|
||||||
}).error(function() {
|
|
||||||
alert('failed to initialize');
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
----
|
|
||||||
To specify the location of the keycloak.json file:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
var keycloak = Keycloak('http://localhost:8080/myapp/keycloak.json'));
|
|
||||||
----
|
|
||||||
Or finally to manually configure the adapter:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
var keycloak = Keycloak({
|
|
||||||
url: 'http://keycloak-server/auth',
|
|
||||||
realm: 'myrealm',
|
|
||||||
clientId: 'myapp'
|
|
||||||
});
|
|
||||||
----
|
|
||||||
You can also pass `login-required` or `check-sso` to the init function.
|
|
||||||
Login required will cause a redirect to the login form on the server, while check-sso will simply redirect to the auth server to check if the user is already logged in to the realm.
|
|
||||||
For example:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
keycloak.init({ onLoad: 'login-required' })
|
|
||||||
----
|
|
||||||
|
|
||||||
After you login, your application will be able to make REST calls using bearer token authentication.
|
|
||||||
Here's an example pulled from the `customer-portal-js` example that comes with the distribution.
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
<script>
|
|
||||||
var loadData = function () {
|
|
||||||
document.getElementById('username').innerText = keycloak.username;
|
|
||||||
|
|
||||||
var url = 'http://localhost:8080/database/customers';
|
|
||||||
|
|
||||||
var req = new XMLHttpRequest();
|
|
||||||
req.open('GET', url, true);
|
|
||||||
req.setRequestHeader('Accept', 'application/json');
|
|
||||||
req.setRequestHeader('Authorization', 'Bearer ' + keycloak.token);
|
|
||||||
|
|
||||||
req.onreadystatechange = function () {
|
|
||||||
if (req.readyState == 4) {
|
|
||||||
if (req.status == 200) {
|
|
||||||
var users = JSON.parse(req.responseText);
|
|
||||||
var html = '';
|
|
||||||
for (var i = 0; i < users.length; i++) {
|
|
||||||
html += '<p>' + users[i] + '</p>';
|
|
||||||
}
|
|
||||||
document.getElementById('customers').innerHTML = html;
|
|
||||||
console.log('finished loading data');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req.send();
|
|
||||||
};
|
|
||||||
|
|
||||||
var loadFailure = function () {
|
|
||||||
document.getElementById('customers').innerHTML = '<b>Failed to load data. Check console log</b>';
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
var reloadData = function () {
|
|
||||||
keycloak.updateToken().success(loadData).error(loadFailure);
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<button onclick="reloadData()">Submit</button>
|
|
||||||
----
|
|
||||||
|
|
||||||
The `loadData()` method builds an HTTP request setting the `Authorization` header to a bearer token.
|
|
||||||
The `keycloak.token` points to the access token the browser obtained when it logged you in.
|
|
||||||
The `loadFailure()` method is invoked on a failure.
|
|
||||||
The `reloadData()` function calls `keycloak.updateToken()` passing in the `loadData()` and `loadFailure()` callbacks.
|
|
||||||
The `keycloak.updateToken()` method checks to see if the access token hasn't expired.
|
|
||||||
If it hasn't, and your oauth login returned a refresh token, this method will refresh the access token.
|
|
||||||
Finally, if successful, it will invoke the success callback, which in this case is the `loadData()` method.
|
|
||||||
|
|
||||||
To refresh the token when it is expired, call the `updateToken` method.
|
|
||||||
This method returns a promise object, which can be used to invoke a function on success or failure.
|
|
||||||
This method can be used to wrap functions that should only be called with a valid token.
|
|
||||||
For example, the following method will refresh the token if it expires within 30 seconds, and then invoke the specified function.
|
|
||||||
If the token is valid for more than 30 seconds it will just call the specified function.
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
keycloak.updateToken(30).success(function() {
|
|
||||||
// send request with valid token
|
|
||||||
}).error(function() {
|
|
||||||
alert('failed to refresh token');
|
|
||||||
);
|
|
||||||
----
|
|
||||||
|
|
||||||
== Session status iframe
|
|
||||||
|
|
||||||
By default, the JavaScript adapter creates a non-visible iframe that is used to detect if a single-sign out has occurred.
|
|
||||||
This does not require any network traffic, instead the status is retrieved from a special status cookie.
|
|
||||||
This feature can be disabled by setting `checkLoginIframe: false` in the options passed to the `init` method.
|
|
||||||
|
|
||||||
[[_javascript_implicit_flow]]
|
|
||||||
== Implicit and Hybrid Flow
|
|
||||||
|
|
||||||
By default, the JavaScript adapter uses http://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth[OpenID Connect standard (Authorization code) flow], which means that after authentication, the Keycloak server redirects the user back to your application, where the JavaScript adapter will exchange the `code` for an access token and a refresh token.
|
|
||||||
|
|
||||||
However, Keycloak also supports http://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth[OpenID Connect Implicit flow] where an access token is sent immediately after successful authentication with Keycloak (there is no additional request for exchange code). This could have better performance than standard flow, as there is no additional request to exchange the code for tokens.
|
|
||||||
However, sending the access token in the URL fragment could pose a security issue in some environments (access logs might expose tokens located in the URL).
|
|
||||||
|
|
||||||
To enable implicit flow, you need to enable the `Implicit Flow Enabled` flag for the client in the Keycloak admin console.
|
|
||||||
You also need to pass the parameter `flow` with value `implicit` to `init` method.
|
|
||||||
An example is below:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
keycloak.init({ flow: 'implicit' })
|
|
||||||
----
|
|
||||||
Note that with implicit flow, you are not given a refresh token after authentication.
|
|
||||||
|
|
||||||
This makes it harder for your application to periodically update the access token in background (without browser redirection). It's recommended that you implement an `onTokenExpired` callback method on the keycloak object, so you are notified after the token is expired (For example you can call keycloak.login, which will redirect browser to Keycloak login screen and it will immediately redirect you back if the SSO session is still valid and the user is still logged.
|
|
||||||
However, make sure to save the application state before performing a redirect.)
|
|
||||||
|
|
||||||
Keycloak also has support for http://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth[OpenID Connect Hybrid flow].
|
|
||||||
|
|
||||||
This requires the client to have both the `Standard Flow Enabled` and `Implicit Flow Enabled` flags enabled in the admin console.
|
|
||||||
The Keycloak 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 security risks might still apply.
|
|
||||||
However, one advantage over the implicit flow is that a refresh token is made available to the application (after the code-to-token request is finished).
|
|
||||||
|
|
||||||
For hybrid flow, you need to pass the parameter `flow` with value `hybrid` to `init` method.
|
|
||||||
|
|
||||||
== Older browsers
|
|
||||||
|
|
||||||
The JavaScript adapter depends on Base64 (window.btoa and window.atob) and HTML5 History API.
|
|
||||||
If you need to support browsers that don't provide those (for example IE9) you'll need to add polyfillers.
|
|
||||||
Example polyfill libraries:
|
|
||||||
|
|
||||||
* https://github.com/davidchambers/Base64.js
|
|
||||||
* https://github.com/devote/HTML5-History-API
|
|
||||||
|
|
||||||
== JavaScript Adapter reference
|
|
||||||
|
|
||||||
=== Constructor
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
new Keycloak();
|
|
||||||
new Keycloak('http://localhost/keycloak.json');
|
|
||||||
new Keycloak({ url: 'http://localhost/auth', realm: 'myrealm', clientId: 'myApp' });
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Properties
|
|
||||||
|
|
||||||
* authenticated - true if the user is authenticated
|
|
||||||
* Authorization
|
|
||||||
* tokenParsed - the parsed token
|
|
||||||
* subject - the user id
|
|
||||||
* idToken - the id token if claims is enabled for the application, null otherwise
|
|
||||||
* idTokenParsed - the parsed id token
|
|
||||||
* realmAccess - the realm roles associated with the token
|
|
||||||
* resourceAccess - the resource roles assocaited with the token
|
|
||||||
* refreshToken - the base64 encoded token that can be used to retrieve a new token
|
|
||||||
* refreshTokenParsed - the parsed refresh token
|
|
||||||
* timeSkew - estimated skew between local time and Keycloak server in seconds
|
|
||||||
* fragment
|
|
||||||
* Implicit flow
|
|
||||||
* flow
|
|
||||||
|
|
||||||
=== Methods
|
|
||||||
|
|
||||||
==== init(options)
|
|
||||||
|
|
||||||
Called to initialize the adapter.
|
|
||||||
|
|
||||||
Options is an Object, where:
|
|
||||||
|
|
||||||
* onLoad - specifies an action to do on load, can be either 'login-required' or 'check-sso'
|
|
||||||
* token - set an initial value for the token
|
|
||||||
* refreshToken - set an initial value for the refresh token
|
|
||||||
* idToken - set an initial value for the id token (only together with token or refreshToken)
|
|
||||||
* 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)
|
|
||||||
* query
|
|
||||||
+`fragment`
|
|
||||||
+`fragment`
|
|
||||||
+`query`
|
|
||||||
* standard
|
|
||||||
+`implicit`
|
|
||||||
+`hybrid`<<_javascript_implicit_flow,+Implicit flow>>
|
|
||||||
|
|
||||||
|
|
||||||
Returns promise to set functions to be invoked on success or error.
|
|
||||||
|
|
||||||
==== login(options)
|
|
||||||
|
|
||||||
Redirects to login form on (options is an optional object with redirectUri and/or prompt fields)
|
|
||||||
|
|
||||||
Options is an Object, where:
|
|
||||||
|
|
||||||
* redirectUri - specifies the uri to redirect to after login
|
|
||||||
* prompt - can be set to 'none' to check if the user is logged in already (if not logged in, a login form is not displayed)
|
|
||||||
* loginHint - used to pre-fill the username/email field on the login form
|
|
||||||
* action - if value is 'register' then user is redirected to registration page, otherwise to login page
|
|
||||||
* locale - specifies the desired locale for the UI
|
|
||||||
|
|
||||||
==== createLoginUrl(options)
|
|
||||||
|
|
||||||
Returns the url to login form on (options is an optional object with redirectUri and/or prompt fields)
|
|
||||||
|
|
||||||
Options is an Object, where:
|
|
||||||
|
|
||||||
* redirectUri - specifies the uri to redirect to after login
|
|
||||||
* prompt - can be set to 'none' to check if the user is logged in already (if not logged in, a login form is not displayed)
|
|
||||||
|
|
||||||
==== logout(options)
|
|
||||||
|
|
||||||
Redirects to logout
|
|
||||||
|
|
||||||
Options is an Object, where:
|
|
||||||
|
|
||||||
* redirectUri - specifies the uri to redirect to after logout
|
|
||||||
|
|
||||||
==== createLogoutUrl(options)
|
|
||||||
|
|
||||||
Returns logout out
|
|
||||||
|
|
||||||
Options is an Object, where:
|
|
||||||
|
|
||||||
* redirectUri - specifies the uri to redirect to after logout
|
|
||||||
|
|
||||||
==== register(options)
|
|
||||||
|
|
||||||
Redirects to registration form.
|
|
||||||
It's a shortcut for doing login with option action = 'register'
|
|
||||||
|
|
||||||
Options are same as login method but 'action' is overwritten to 'register'
|
|
||||||
|
|
||||||
==== createRegisterUrl(options)
|
|
||||||
|
|
||||||
Returns the url to registration page.
|
|
||||||
It's a shortcut for doing createRegisterUrl with option action = 'register'
|
|
||||||
|
|
||||||
Options are same as createLoginUrl method but 'action' is overwritten to 'register'
|
|
||||||
|
|
||||||
==== accountManagement()
|
|
||||||
|
|
||||||
Redirects to account management
|
|
||||||
|
|
||||||
==== createAccountUrl()
|
|
||||||
|
|
||||||
Returns the url to account management
|
|
||||||
|
|
||||||
==== hasRealmRole(role)
|
|
||||||
|
|
||||||
Returns true if the token has the given realm role
|
|
||||||
|
|
||||||
==== hasResourceRole(role, resource)
|
|
||||||
|
|
||||||
Returns true if the token has the given role for the resource (resource is optional, if not specified clientId is used)
|
|
||||||
|
|
||||||
==== loadUserProfile()
|
|
||||||
|
|
||||||
Loads the users profile
|
|
||||||
|
|
||||||
Returns promise to set functions to be invoked on success or error.
|
|
||||||
|
|
||||||
==== isTokenExpired(minValidity)
|
|
||||||
|
|
||||||
Returns true if the token has less than minValidity seconds left before it expires (minValidity is optional, if not specified 0 is used)
|
|
||||||
|
|
||||||
==== updateToken(minValidity)
|
|
||||||
|
|
||||||
If the token expires within minValidity seconds (minValidity is optional, if not specified 0 is used) the token is refreshed.
|
|
||||||
If the session status iframe is enabled, the session status is also checked.
|
|
||||||
|
|
||||||
Returns promise to set functions that can be invoked if the token is still valid, or if the token is no longer valid.
|
|
||||||
For example:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
keycloak.updateToken(5).success(function(refreshed) {
|
|
||||||
if (refreshed) {
|
|
||||||
alert('token was successfully refreshed');
|
|
||||||
} else {
|
|
||||||
alert('token is still valid');
|
|
||||||
}
|
|
||||||
}).error(function() {
|
|
||||||
alert('failed to refresh the token, or the session has expired');
|
|
||||||
});
|
|
||||||
----
|
|
||||||
|
|
||||||
==== clearToken()
|
|
||||||
|
|
||||||
Clear authentication state, including tokens.
|
|
||||||
This can be useful if application has detected the session has expired, for example if updating token fails.
|
|
||||||
Invoking this results in onAuthLogout callback listener being invoked.
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
keycloak.updateToken(5).error(function() {
|
|
||||||
keycloak.clearToken();
|
|
||||||
});
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Callback Events
|
|
||||||
|
|
||||||
The adapter supports setting callback listeners for certain events.
|
|
||||||
For example:
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
keycloak.onAuthSuccess = function() { alert('authenticated'); }
|
|
||||||
----
|
|
||||||
|
|
||||||
* 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 access token expired. When this happens you can for example refresh token, or if refresh not available (ie. with implicit flow) you can redirect to login screen
|
|
|
@ -1,277 +0,0 @@
|
||||||
|
|
||||||
[[_jboss_adapter]]
|
|
||||||
= JBoss/Wildfly Adapter
|
|
||||||
|
|
||||||
To be able to secure WAR apps deployed on JBoss AS 7.1.1, JBoss EAP 6.x, or Wildfly, you must install and configure the Keycloak Subsystem.
|
|
||||||
You then have two options to secure your WARs.
|
|
||||||
You can provide a keycloak config file in your WAR and change the auth-method to KEYCLOAK within web.xml.
|
|
||||||
Alternatively, you don't have to crack open your WARs at all and can apply Keycloak via the Keycloak Subsystem configuration in standalone.xml.
|
|
||||||
Both methods are described in this section.
|
|
||||||
|
|
||||||
[[_jboss_adapter_installation]]
|
|
||||||
== Adapter Installation
|
|
||||||
|
|
||||||
Adapters are no longer included with the appliance or war distribution.
|
|
||||||
Each adapter is a separate download on the Keycloak download site.
|
|
||||||
They are also available as a maven artifact.
|
|
||||||
|
|
||||||
Install on Wildfly 9 or 10:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ cd $WILDFLY_HOME
|
|
||||||
$ unzip keycloak-wildfly-adapter-dist.zip
|
|
||||||
----
|
|
||||||
Install on Wildfly 8:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ cd $WILDFLY_HOME
|
|
||||||
$ unzip keycloak-wf8-adapter-dist.zip
|
|
||||||
----
|
|
||||||
Install on JBoss EAP 6.x:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ cd $JBOSS_HOME
|
|
||||||
$ unzip keycloak-eap6-adapter-dist.zip
|
|
||||||
----
|
|
||||||
Install on JBoss AS 7.1.1:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ cd $JBOSS_HOME
|
|
||||||
$ unzip keycloak-as7-adapter-dist.zip
|
|
||||||
----
|
|
||||||
|
|
||||||
This zip file creates new JBoss Modules specific to the Wildfly Keycloak Adapter within your Wildfly distro.
|
|
||||||
|
|
||||||
After adding the Keycloak modules, you must then enable the Keycloak Subsystem within your app server's server configuration: `domain.xml` or `standalone.xml`.
|
|
||||||
|
|
||||||
There is a CLI script that will help you modify your server configuration.
|
|
||||||
Start the server and run the script from the server's bin directory:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ cd $JBOSS_HOME/bin
|
|
||||||
$ jboss-cli.sh -c --file=adapter-install.cli
|
|
||||||
----
|
|
||||||
The script will add the extension, subsystem, and optional security-domain as described below.
|
|
||||||
|
|
||||||
For more recent versions of WildFly there's also a offline CLI script that can be used to install the adapter while the server is not running:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ cd $JBOSS_HOME/bin
|
|
||||||
$ jboss-cli.sh -c --file=adapter-install-offline.cli
|
|
||||||
----
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
<server xmlns="urn:jboss:domain:1.4">
|
|
||||||
|
|
||||||
<extensions>
|
|
||||||
<extension module="org.keycloak.keycloak-adapter-subsystem"/>
|
|
||||||
...
|
|
||||||
</extensions>
|
|
||||||
|
|
||||||
<profile>
|
|
||||||
<subsystem xmlns="urn:jboss:domain:keycloak:1.1"/>
|
|
||||||
...
|
|
||||||
</profile>
|
|
||||||
----
|
|
||||||
|
|
||||||
The keycloak security domain should be used with EJBs and other components when you need the security context created in the secured web tier to be propagated to the EJBs (other EE component) you are invoking.
|
|
||||||
Otherwise this configuration is optional.
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
<server xmlns="urn:jboss:domain:1.4">
|
|
||||||
<subsystem xmlns="urn:jboss:domain:security:1.2">
|
|
||||||
<security-domains>
|
|
||||||
...
|
|
||||||
<security-domain name="keycloak">
|
|
||||||
<authentication>
|
|
||||||
<login-module code="org.keycloak.adapters.jboss.KeycloakLoginModule"
|
|
||||||
flag="required"/>
|
|
||||||
</authentication>
|
|
||||||
</security-domain>
|
|
||||||
</security-domains>
|
|
||||||
----
|
|
||||||
|
|
||||||
For example, if you have a JAX-RS service that is an EJB within your WEB-INF/classes directory, you'll want to annotate it with the @SecurityDomain annotation as follows:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
import org.jboss.ejb3.annotation.SecurityDomain;
|
|
||||||
import org.jboss.resteasy.annotations.cache.NoCache;
|
|
||||||
|
|
||||||
import javax.annotation.security.RolesAllowed;
|
|
||||||
import javax.ejb.EJB;
|
|
||||||
import javax.ejb.Stateless;
|
|
||||||
import javax.ws.rs.GET;
|
|
||||||
import javax.ws.rs.Path;
|
|
||||||
import javax.ws.rs.Produces;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Path("customers")
|
|
||||||
@Stateless
|
|
||||||
@SecurityDomain("keycloak")
|
|
||||||
public class CustomerService {
|
|
||||||
|
|
||||||
@EJB
|
|
||||||
CustomerDB db;
|
|
||||||
|
|
||||||
@GET
|
|
||||||
@Produces("application/json")
|
|
||||||
@NoCache
|
|
||||||
@RolesAllowed("db_user")
|
|
||||||
public List<String> getCustomers() {
|
|
||||||
return db.getCustomers();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
We hope to improve our integration in the future so that you don't have to specify the @SecurityDomain annotation when you want to propagate a keycloak security context to the EJB tier.
|
|
||||||
|
|
||||||
== Required Per WAR Configuration
|
|
||||||
|
|
||||||
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
|
|
||||||
|
|
||||||
The first thing you must do is create a `keycloak.json` adapter config file within the `WEB-INF` directory of your WAR.
|
|
||||||
The format of this config file is describe in the <<_adapter_config,general adapter configuration>> section.
|
|
||||||
|
|
||||||
Next you must set the `auth-method` to `KEYCLOAK` in `web.xml`.
|
|
||||||
You also have to use standard servlet security to specify role-base constraints on your URLs.
|
|
||||||
Here's an example pulled from one of the examples that comes distributed with Keycloak.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
|
||||||
version="3.0">
|
|
||||||
|
|
||||||
<module-name>customer-portal</module-name>
|
|
||||||
|
|
||||||
<security-constraint>
|
|
||||||
<web-resource-collection>
|
|
||||||
<web-resource-name>Admins</web-resource-name>
|
|
||||||
<url-pattern>/admin/*</url-pattern>
|
|
||||||
</web-resource-collection>
|
|
||||||
<auth-constraint>
|
|
||||||
<role-name>admin</role-name>
|
|
||||||
</auth-constraint>
|
|
||||||
<user-data-constraint>
|
|
||||||
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
|
|
||||||
</user-data-constraint>
|
|
||||||
</security-constraint>
|
|
||||||
<security-constraint>
|
|
||||||
<web-resource-collection>
|
|
||||||
<web-resource-name>Customers</web-resource-name>
|
|
||||||
<url-pattern>/customers/*</url-pattern>
|
|
||||||
</web-resource-collection>
|
|
||||||
<auth-constraint>
|
|
||||||
<role-name>user</role-name>
|
|
||||||
</auth-constraint>
|
|
||||||
<user-data-constraint>
|
|
||||||
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
|
|
||||||
</user-data-constraint>
|
|
||||||
</security-constraint>
|
|
||||||
|
|
||||||
<login-config>
|
|
||||||
<auth-method>KEYCLOAK</auth-method>
|
|
||||||
<realm-name>this is ignored currently</realm-name>
|
|
||||||
</login-config>
|
|
||||||
|
|
||||||
<security-role>
|
|
||||||
<role-name>admin</role-name>
|
|
||||||
</security-role>
|
|
||||||
<security-role>
|
|
||||||
<role-name>user</role-name>
|
|
||||||
</security-role>
|
|
||||||
</web-app>
|
|
||||||
----
|
|
||||||
|
|
||||||
== Securing WARs via Keycloak Subsystem
|
|
||||||
|
|
||||||
You do not have to crack open a WAR to secure it with Keycloak.
|
|
||||||
Alternatively, you can externally secure it via the Keycloak Adapter Subsystem.
|
|
||||||
While you don't have to specify KEYCLOAK as an `auth-method`, you still have to define the `security-constraints` in `web.xml`.
|
|
||||||
You do not, however, have to create a `WEB-INF/keycloak.json` file.
|
|
||||||
This metadata is instead defined within XML in your server's `domain.xml` or `standalone.xml` subsystem configuration section.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
<extensions>
|
|
||||||
<extension module="org.keycloak.keycloak-adapter-subsystem"/>
|
|
||||||
</extensions>
|
|
||||||
|
|
||||||
<profile>
|
|
||||||
<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
|
|
||||||
<secure-deployment name="WAR MODULE NAME.war">
|
|
||||||
<realm>demo</realm>
|
|
||||||
<realm-public-key>MIGfMA0GCSqGSIb3DQEBAQUAA</realm-public-key>
|
|
||||||
<auth-server-url>http://localhost:8081/auth</auth-server-url>
|
|
||||||
<ssl-required>external</ssl-required>
|
|
||||||
<resource>customer-portal</resource>
|
|
||||||
<credential name="secret">password</credential>
|
|
||||||
</secure-deployment>
|
|
||||||
</subsystem>
|
|
||||||
</profile>
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
The `secure-deployment` `name` attribute identifies the WAR you want to secure.
|
|
||||||
Its value is the `module-name` defined in `web.xml` with `.war` appended.
|
|
||||||
The rest of the configuration corresponds pretty much one to one with the `keycloak.json` configuration options defined in <<_adapter_config,general adapter configuration>>.
|
|
||||||
The exception is the `credential` element.
|
|
||||||
|
|
||||||
To make it easier for you, you can go to the Keycloak Adminstration Console and go to the Application/Installation tab of the application this WAR is aligned with.
|
|
||||||
It provides an example XML file you can cut and paste.
|
|
||||||
|
|
||||||
There is an additional convenience format for this XML if you have multiple WARs you are deployment that are secured by the same domain.
|
|
||||||
This format allows you to define common configuration items in one place under the `realm` element.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
<subsystem xmlns="urn:jboss:domain:keycloak:1.1">
|
|
||||||
<realm name="demo">
|
|
||||||
<realm-public-key>MIGfMA0GCSqGSIb3DQEBA</realm-public-key>
|
|
||||||
<auth-server-url>http://localhost:8080/auth</auth-server-url>
|
|
||||||
<ssl-required>external</ssl-required>
|
|
||||||
</realm>
|
|
||||||
<secure-deployment name="customer-portal.war">
|
|
||||||
<realm>demo</realm>
|
|
||||||
<resource>customer-portal</resource>
|
|
||||||
<credential name="secret">password</credential>
|
|
||||||
</secure-deployment>
|
|
||||||
<secure-deployment name="product-portal.war">
|
|
||||||
<realm>demo</realm>
|
|
||||||
<resource>product-portal</resource>
|
|
||||||
<credential name="secret">password</credential>
|
|
||||||
</secure-deployment>
|
|
||||||
<secure-deployment name="database.war">
|
|
||||||
<realm>demo</realm>
|
|
||||||
<resource>database-service</resource>
|
|
||||||
<bearer-only>true</bearer-only>
|
|
||||||
</secure-deployment>
|
|
||||||
</subsystem>
|
|
||||||
----
|
|
|
@ -1,47 +0,0 @@
|
||||||
|
|
||||||
[[_jetty8_adapter]]
|
|
||||||
= Jetty 8.1.x Adapter
|
|
||||||
|
|
||||||
Keycloak has a separate adapter for Jetty 8.1.x that you will have to install into your Jetty installation.
|
|
||||||
You then have to provide some extra configuration in each WAR you deploy to Jetty.
|
|
||||||
Let's go over these steps.
|
|
||||||
|
|
||||||
[[_jetty8_adapter_installation]]
|
|
||||||
== Adapter Installation
|
|
||||||
|
|
||||||
Adapters are no longer included with the appliance or war distribution.Each adapter is a separate download on the Keycloak download site.
|
|
||||||
They are also available as a maven artifact.
|
|
||||||
|
|
||||||
You must unzip the Jetty 8.1.x distro into Jetty 8.1.x's root directory.
|
|
||||||
Including adapter's jars within your WEB-INF/lib directory will not work!
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ cd $JETTY_HOME
|
|
||||||
$ unzip keycloak-jetty81-adapter-dist.zip
|
|
||||||
----
|
|
||||||
|
|
||||||
Next, you will have to enable the keycloak option.
|
|
||||||
Edit start.ini and add keycloak to the options
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
#===========================================================
|
|
||||||
# Start classpath OPTIONS.
|
|
||||||
# These control what classes are on the classpath
|
|
||||||
# for a full listing do
|
|
||||||
# java -jar start.jar --list-options
|
|
||||||
#-----------------------------------------------------------
|
|
||||||
OPTIONS=Server,jsp,jmx,resources,websocket,ext,plus,annotations,keycloak
|
|
||||||
----
|
|
||||||
|
|
||||||
== Required Per WAR Configuration
|
|
||||||
|
|
||||||
Enabling Keycloak for your WARs is the same as the Jetty 9.x adapter.
|
|
||||||
Our 8.1.x adapter supports both keycloak.json and the jboss-web.xml advanced configuration.
|
|
||||||
See <<_jetty9_per_war,Required Per WAR Configuration>>
|
|
|
@ -1,148 +0,0 @@
|
||||||
|
|
||||||
[[_jetty9_adapter]]
|
|
||||||
= Jetty 9.x Adapters
|
|
||||||
|
|
||||||
Keycloak has a separate adapter for Jetty 9.1.x and Jetty 9.2.x that you will have to install into your Jetty installation.
|
|
||||||
You then have to provide some extra configuration in each WAR you deploy to Jetty.
|
|
||||||
Let's go over these steps.
|
|
||||||
|
|
||||||
[[_jetty9_adapter_installation]]
|
|
||||||
== Adapter Installation
|
|
||||||
|
|
||||||
Adapters are no longer included with the appliance or war distribution.Each adapter is a separate download on the Keycloak download site.
|
|
||||||
They are also available as a maven artifact.
|
|
||||||
|
|
||||||
You must unzip the Jetty 9.x distro into Jetty 9.x's root directory.
|
|
||||||
Including adapter's jars within your WEB-INF/lib directory will not work!
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ cd $JETTY_HOME
|
|
||||||
$ unzip keycloak-jetty92-adapter-dist.zip
|
|
||||||
----
|
|
||||||
|
|
||||||
Next, you will have to enable the keycloak module for your jetty.base.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ cd your-base
|
|
||||||
$ java -jar $JETTY_HOME/start.jar --add-to-startd=keycloak
|
|
||||||
----
|
|
||||||
|
|
||||||
[[_jetty9_per_war]]
|
|
||||||
== Required Per WAR Configuration
|
|
||||||
|
|
||||||
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
|
|
||||||
|
|
||||||
The first thing you must do is create a `WEB-INF/jetty-web.xml` file in your WAR package.
|
|
||||||
This is a Jetty specific config file and you must define a Keycloak specific authenticator within it.
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
|
||||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
|
||||||
<Get name="securityHandler">
|
|
||||||
<Set name="authenticator">
|
|
||||||
<New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
|
|
||||||
</New>
|
|
||||||
</Set>
|
|
||||||
</Get>
|
|
||||||
</Configure>
|
|
||||||
----
|
|
||||||
|
|
||||||
Next you must create a `keycloak.json` adapter config file within the `WEB-INF` directory of your WAR.
|
|
||||||
The format of this config file is describe in the <<_adapter_config,general adapter configuration>> section.
|
|
||||||
|
|
||||||
WARNING: The Jetty 9.1.x adapter will not be able to find the `keycloak.json` file.
|
|
||||||
You will have to define all adapter settings within the `jetty-web.xml` file as described below.
|
|
||||||
|
|
||||||
Instead of using keycloak.json, you can define everything within the `jetty-web.xml`.
|
|
||||||
You'll just have to figure out how the json settings match to the `org.keycloak.representations.adapters.config.AdapterConfig` class.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
<?xml version="1.0"?>
|
|
||||||
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_0.dtd">
|
|
||||||
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
|
|
||||||
<Get name="securityHandler">
|
|
||||||
<Set name="authenticator">
|
|
||||||
<New class="org.keycloak.adapters.jetty.KeycloakJettyAuthenticator">
|
|
||||||
<Set name="adapterConfig">
|
|
||||||
<New class="org.keycloak.representations.adapters.config.AdapterConfig">
|
|
||||||
<Set name="realm">tomcat</Set>
|
|
||||||
<Set name="resource">customer-portal</Set>
|
|
||||||
<Set name="authServerUrl">http://localhost:8081/auth</Set>
|
|
||||||
<Set name="sslRequired">external</Set>
|
|
||||||
<Set name="credentials">
|
|
||||||
<Map>
|
|
||||||
<Entry>
|
|
||||||
<Item>secret</Item>
|
|
||||||
<Item>password</Item>
|
|
||||||
</Entry>
|
|
||||||
</Map>
|
|
||||||
</Set>
|
|
||||||
<Set name="realmKey">MIGfMA0GCSqGSIb3DQEBAQUAA4</Set>
|
|
||||||
</New>
|
|
||||||
</Set>
|
|
||||||
</New>
|
|
||||||
</Set>
|
|
||||||
</Get>
|
|
||||||
</Configure>
|
|
||||||
----
|
|
||||||
|
|
||||||
You do not have to crack open your WAR to secure it with keycloak.
|
|
||||||
Instead create the jetty-web.xml file in your webapps directory with the name of yourwar.xml.
|
|
||||||
Jetty should pick it up.
|
|
||||||
In this mode, you'll have to declare keycloak.json configuration directly within the xml file.
|
|
||||||
|
|
||||||
Finally you must specify both a `login-config` and use standard servlet security to specify role-base constraints on your URLs.
|
|
||||||
Here's an example:
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
|
||||||
version="3.0">
|
|
||||||
|
|
||||||
<module-name>customer-portal</module-name>
|
|
||||||
|
|
||||||
<security-constraint>
|
|
||||||
<web-resource-collection>
|
|
||||||
<web-resource-name>Customers</web-resource-name>
|
|
||||||
<url-pattern>/*</url-pattern>
|
|
||||||
</web-resource-collection>
|
|
||||||
<auth-constraint>
|
|
||||||
<role-name>user</role-name>
|
|
||||||
</auth-constraint>
|
|
||||||
<user-data-constraint>
|
|
||||||
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
|
|
||||||
</user-data-constraint>
|
|
||||||
</security-constraint>
|
|
||||||
|
|
||||||
<login-config>
|
|
||||||
<auth-method>BASIC</auth-method>
|
|
||||||
<realm-name>this is ignored currently</realm-name>
|
|
||||||
</login-config>
|
|
||||||
|
|
||||||
<security-role>
|
|
||||||
<role-name>admin</role-name>
|
|
||||||
</security-role>
|
|
||||||
<security-role>
|
|
||||||
<role-name>user</role-name>
|
|
||||||
</security-role>
|
|
||||||
</web-app>
|
|
||||||
----
|
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
= Logout
|
|
||||||
|
|
||||||
There are multiple ways you can logout from a web application.
|
|
||||||
For Java EE servlet containers, you can call HttpServletRequest.logout(). For any other browser application, you can point the browser at the url `http://auth-server/auth/realms/{realm-name}/tokens/logout?redirect_uri=encodedRedirectUri`.
|
|
||||||
This will log you out if you have an SSO session with your browser.
|
|
|
@ -1,28 +0,0 @@
|
||||||
|
|
||||||
= Multi Tenancy
|
|
||||||
|
|
||||||
Multi Tenancy, in our context, means that one single target application (WAR) can be secured by a single (or clustered) Keycloak server, authenticating its users against different realms.
|
|
||||||
In practice, this means that one application needs to use different `keycloak.json` files.
|
|
||||||
For this case, there are two possible solutions:
|
|
||||||
|
|
||||||
* The same WAR file deployed under two different names, each with its own Keycloak configuration (probably via the Keycloak Subsystem).
|
|
||||||
This scenario is suitable when the number of realms is known in advance or when there's a dynamic provision of application instances.
|
|
||||||
One example would be a service provider that dynamically creates servers/deployments for their clients, like a PaaS.
|
|
||||||
* client1.acme.com
|
|
||||||
+`client2.acme.com`
|
|
||||||
+`/app/client1/`
|
|
||||||
+`/app/client2/` This chapter of the reference guide focus on this second scenario.
|
|
||||||
|
|
||||||
Keycloak provides an extension point for applications that need to evaluate the realm on a request basis.
|
|
||||||
During the authentication and authorization phase of the incoming request, Keycloak queries the application via this extension point and expects the application to return a complete representation of the realm.
|
|
||||||
With this, Keycloak then proceeds the authentication and authorization process, accepting or refusing the request based on the incoming credentials and on the returned realm.
|
|
||||||
For this scenario, an application needs to:
|
|
||||||
|
|
||||||
* web.xml
|
|
||||||
+`keycloak.config.resolver`
|
|
||||||
+`org.keycloak.adapters.KeycloakConfigResolver`
|
|
||||||
* org.keycloak.adapters.KeycloakConfigResolver
|
|
||||||
+`resolve(org.keycloak.adapters.spi.HttpFacade.Request)`
|
|
||||||
+`org.keycloak.adapters.KeycloakDeployment`
|
|
||||||
|
|
||||||
An implementation of this feature can be found in the examples.
|
|
|
@ -1,44 +0,0 @@
|
||||||
[[_openshift]]
|
|
||||||
|
|
||||||
= Running Keycloak Server on OpenShift
|
|
||||||
|
|
||||||
Keycloak provides a OpenShift cartridge to make it easy to get it running on OpenShift.
|
|
||||||
If you don't already have an account or don't know how to create applications go to https://www.openshift.com/ first.
|
|
||||||
You can create the Keycloak instance either with the web tool or the command line tool, both approaches are described below.
|
|
||||||
|
|
||||||
WARNING: It's important that immediately after creating a Keycloak instance you open the `Administration Console` and login to reset the password.
|
|
||||||
If this is not done anyone can easily gain admin rights to your Keycloak instance.
|
|
||||||
|
|
||||||
== Create Keycloak instance with the web tool
|
|
||||||
|
|
||||||
. Open https://openshift.redhat.com/app/console/applications and click on `Add Application`.
|
|
||||||
. Scroll down to the bottom of the page to find the `Code Anything` section.
|
|
||||||
. Insert `http://cartreflect-claytondev.rhcloud.com/github/keycloak/openshift-keycloak-cartridge` into the `URL to a cartridge definition` field and click on `Next`.
|
|
||||||
. Fill in the following form and click on `Create Application`.
|
|
||||||
. Click on `Continue to the application overview page`.
|
|
||||||
. Under the list of applications you should find your Keycloak instance and the status should be `Started`.
|
|
||||||
. Click on it to open the Keycloak servers homepage.
|
|
||||||
|
|
||||||
== Create Keycloak instance with the command-line tool
|
|
||||||
|
|
||||||
. Run the following command from a terminal:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
rhc app create <APPLICATION NAME> http://cartreflect-claytondev.rhcloud.com/github/keycloak/openshift-keycloak-cartridge
|
|
||||||
----
|
|
||||||
|
|
||||||
. Replace `<APPLICATION NAME>` with the name you want (for example keycloak).
|
|
||||||
|
|
||||||
Once the instance is created the rhc tool outputs details about it.
|
|
||||||
Open the returned `URL` in a browser to open the Keycloak servers homepage.
|
|
||||||
|
|
||||||
== Next steps
|
|
||||||
|
|
||||||
The Keycloak servers homepage shows the Keycloak logo and `Welcome to Keycloak`.
|
|
||||||
There is also a link to the `Administration Console`.
|
|
||||||
Open that and log in using username `admin` and password `admin`.
|
|
||||||
On the first login you are required to change the password.
|
|
||||||
|
|
||||||
TIP: On OpenShift Keycloak has been configured to only accept requests over https.
|
|
||||||
If you try to use http you will be redirected to https.
|
|
|
@ -1,238 +0,0 @@
|
||||||
[[_proxy]]
|
|
||||||
= Keycloak Security Proxy
|
|
||||||
|
|
||||||
Keycloak has an HTTP(S) proxy that you can put in front of web applications and services where it is not possible to install the keycloak adapter.
|
|
||||||
You can set up URL filters so that certain URLs are secured either by browser login and/or bearer token authentication.
|
|
||||||
You can also define role constraints for URL patterns within your applications.
|
|
||||||
|
|
||||||
== Proxy Install and Run
|
|
||||||
|
|
||||||
Download the keycloak proxy distribution from the Keycloak download pages and unzip it.
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ unzip keycloak-proxy-dist.zip
|
|
||||||
----
|
|
||||||
|
|
||||||
To run it you must have a proxy config file (which we'll discuss in a moment).
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ java -jar bin/launcher.jar [your-config.json]
|
|
||||||
----
|
|
||||||
|
|
||||||
If you do not specify a path to the proxy config file, the launcher will look in the current working directory for the file named `proxy.json`
|
|
||||||
|
|
||||||
== Proxy Configuration
|
|
||||||
|
|
||||||
Here's an example configuration file.
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
{
|
|
||||||
"target-url": "http://localhost:8082",
|
|
||||||
"send-access-token": true,
|
|
||||||
"bind-address": "localhost",
|
|
||||||
"http-port": "8080",
|
|
||||||
"https-port": "8443",
|
|
||||||
"keystore": "classpath:ssl.jks",
|
|
||||||
"keystore-password": "password",
|
|
||||||
"key-password": "password",
|
|
||||||
"applications": [
|
|
||||||
{
|
|
||||||
"base-path": "/customer-portal",
|
|
||||||
"error-page": "/error.html",
|
|
||||||
"adapter-config": {
|
|
||||||
"realm": "demo",
|
|
||||||
"resource": "customer-portal",
|
|
||||||
"realm-public-key": "MIGfMA0GCSqGSIb",
|
|
||||||
"auth-server-url": "http://localhost:8081/auth",
|
|
||||||
"ssl-required" : "external",
|
|
||||||
"principal-attribute": "name",
|
|
||||||
"credentials": {
|
|
||||||
"secret": "password"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
,
|
|
||||||
"constraints": [
|
|
||||||
{
|
|
||||||
"pattern": "/users/*",
|
|
||||||
"roles-allowed": [
|
|
||||||
"user"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pattern": "/admins/*",
|
|
||||||
"roles-allowed": [
|
|
||||||
"admin"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pattern": "/users/permit",
|
|
||||||
"permit": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"pattern": "/users/deny",
|
|
||||||
"deny": true
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Basic Config
|
|
||||||
|
|
||||||
The basic configuration options for the server are as follows:
|
|
||||||
|
|
||||||
target-url::
|
|
||||||
The URL this server is proxying _REQUIRED._.
|
|
||||||
|
|
||||||
send-access-token::
|
|
||||||
Boolean flag.
|
|
||||||
If true, this will send the access token via the KEYCLOAK_ACCESS_TOKEN header to the proxied server. _OPTIONAL._.
|
|
||||||
Default is false.
|
|
||||||
|
|
||||||
bind-address::
|
|
||||||
DNS name or IP address to bind the proxy server's sockets to. _OPTIONAL._.
|
|
||||||
The default value is _localhost_
|
|
||||||
|
|
||||||
http-port::
|
|
||||||
Port to listen for HTTP requests.
|
|
||||||
If you do not specify this value, then the proxy will not listen for regular HTTP requests. _OPTIONAL._.
|
|
||||||
|
|
||||||
https-port::
|
|
||||||
Port to listen for HTTPS requests.
|
|
||||||
If you do not specify this value, then the proxy will not listen for HTTPS requests. _OPTIONAL._.
|
|
||||||
|
|
||||||
keystore::
|
|
||||||
Path to a Java keystore file that contains private key and certificate for the server to be able to handle HTTPS requests.
|
|
||||||
Can be a file path, or, if you prefix it with `classpath:` it will look for this file in the classpath. _OPTIONAL._.
|
|
||||||
If you have enabled HTTPS, but have not defined a keystore, the proxy will auto-generate a self-signed certificate and use that.
|
|
||||||
|
|
||||||
buffer-size::
|
|
||||||
HTTP server socket buffer size.
|
|
||||||
Usually the default is good enough. _OPTIONAL._.
|
|
||||||
|
|
||||||
buffers-per-region::
|
|
||||||
HTTP server socket buffers per region.
|
|
||||||
Usually the default is good enough. _OPTIONAL._.
|
|
||||||
|
|
||||||
io-threads::
|
|
||||||
Number of threads to handle IO.
|
|
||||||
Usually default is good enough.
|
|
||||||
_OPTIONAL._.
|
|
||||||
The default is the number of available processors * 2.
|
|
||||||
|
|
||||||
worker-threads::
|
|
||||||
Number of threads to handle requests.
|
|
||||||
Usually the default is good enough. _OPTIONAL._.
|
|
||||||
The default is the number of available processors * 16.
|
|
||||||
|
|
||||||
=== Application Config
|
|
||||||
|
|
||||||
Next under the `applications` array attribute, you can define one or more applications per host you are proxying.
|
|
||||||
|
|
||||||
base-path::
|
|
||||||
The base context root for the application.
|
|
||||||
Must start with '/' _REQUIRED._.
|
|
||||||
|
|
||||||
error-page::
|
|
||||||
If the proxy has an error, it will display the target application's error page relative URL _OPTIONAL._.
|
|
||||||
This is a relative path to the base-path.
|
|
||||||
In the example above it would be `/customer-portal/error.html`.
|
|
||||||
|
|
||||||
adapter-config::
|
|
||||||
_REQUIRED._.
|
|
||||||
Same configuration as any other keycloak adapter.
|
|
||||||
See <<_adapter_config,Adapter Config>>
|
|
||||||
|
|
||||||
==== Constraint Config
|
|
||||||
|
|
||||||
Next under each application you can define one or more constraints in the `constraints` array attribute.
|
|
||||||
A constraint defines a URL pattern relative to the base-path.
|
|
||||||
You can deny, permit, or require authentication for a specific URL pattern.
|
|
||||||
You can specify roles allowed for that path as well.
|
|
||||||
More specific constraints will take precedence over more general ones.
|
|
||||||
|
|
||||||
pattern::
|
|
||||||
URL pattern to match relative to the base-path of the application.
|
|
||||||
Must start with '/' _REQUIRED._.
|
|
||||||
You may only have one wildcard and it must come at the end of the pattern.
|
|
||||||
Valid `/foo/bar/*` and `/foo/*.txt` Not valid: `/*/foo/*`.
|
|
||||||
|
|
||||||
roles-allowed::
|
|
||||||
Array of strings of roles allowed to access this url pattern. _OPTIONAL._.
|
|
||||||
|
|
||||||
methods::
|
|
||||||
Array of strings of HTTP methods that will exclusively match this pattern and HTTP request. _OPTIONAL._.
|
|
||||||
|
|
||||||
excluded-methods::
|
|
||||||
Array of strings of HTTP methods that will be ignored when match this pattern. _OPTIONAL._.
|
|
||||||
|
|
||||||
deny::
|
|
||||||
Deny all access to this URL pattern. _OPTIONAL._.
|
|
||||||
|
|
||||||
permit::
|
|
||||||
Permit all access without requiring authentication or a role mapping. _OPTIONAL._.
|
|
||||||
|
|
||||||
permit-and-inject::
|
|
||||||
Permit all access, but inject the headers, if user is already authenticated._OPTIONAL._.
|
|
||||||
|
|
||||||
authenticate::
|
|
||||||
Require authentication for this pattern, but no role mapping. _OPTIONAL._.
|
|
||||||
|
|
||||||
=== Header Names Config
|
|
||||||
|
|
||||||
Next under the list of applications you can override the defaults for the names of the header fields injected by the proxy (see Keycloak Identity Headers). This mapping is optional.
|
|
||||||
|
|
||||||
keycloak-subject::
|
|
||||||
e.g.
|
|
||||||
MYAPP_USER_ID
|
|
||||||
|
|
||||||
keycloak-username::
|
|
||||||
e.g.
|
|
||||||
MYAPP_USER_NAME
|
|
||||||
|
|
||||||
keycloak-email::
|
|
||||||
e.g.
|
|
||||||
MYAPP_USER_EMAIL
|
|
||||||
|
|
||||||
keycloak-name::
|
|
||||||
e.g.
|
|
||||||
MYAPP_USER_ID
|
|
||||||
|
|
||||||
keycloak-access-token::
|
|
||||||
e.g.
|
|
||||||
MYAPP_ACCESS_TOKEN
|
|
||||||
|
|
||||||
== Keycloak Identity Headers
|
|
||||||
|
|
||||||
When forwarding requests to the proxied server, Keycloak Proxy will set some additional headers with values from the OIDC identity token it received for authentication.
|
|
||||||
|
|
||||||
KEYCLOAK_SUBJECT::
|
|
||||||
User id.
|
|
||||||
Corresponds to JWT `sub` and will be the user id Keycloak uses to store this user.
|
|
||||||
|
|
||||||
KEYCLOAK_USERNAME::
|
|
||||||
Username.
|
|
||||||
Corresponds to JWT `preferred_username`
|
|
||||||
|
|
||||||
KEYCLOAK_EMAIL::
|
|
||||||
Email address of user if set.
|
|
||||||
|
|
||||||
KEYCLOAK_NAME::
|
|
||||||
Full name of user if set.
|
|
||||||
|
|
||||||
KEYCLOAK_ACCESS_TOKEN::
|
|
||||||
Send the access token in this header if the proxy was configured to send it.
|
|
||||||
This token can be used to make bearer token requests. Header field names can be configured using a map of `header-names` in configuration file:
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
{
|
|
||||||
"header-names" {
|
|
||||||
"keycloak-subject": "MY_SUBJECT"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
|
@ -1,610 +0,0 @@
|
||||||
[[_server_installation]]
|
|
||||||
|
|
||||||
= Installation and Configuration of Keycloak Server
|
|
||||||
|
|
||||||
== Installation
|
|
||||||
|
|
||||||
Keycloak Server has three downloadable distributions.
|
|
||||||
To run the Keycloak server you need to have Java 8 already installed.
|
|
||||||
|
|
||||||
* keycloak-.[zip|tar.gz]
|
|
||||||
* keycloak-overlay-.[zip|tar.gz]
|
|
||||||
* keycloak-demo-.[zip|tar.gz]
|
|
||||||
|
|
||||||
[[_server_install]]
|
|
||||||
=== Install Standalone Server
|
|
||||||
|
|
||||||
For production and for non-JavaEE developers we recommend using the standalone Keycloak server.
|
|
||||||
All you need to do is to download `keycloak-.zip` or `keycloak-.tar.gz`, unpackage and start to have a Keycloak server up and running.
|
|
||||||
|
|
||||||
To install first download either the zip or tar.gz and extract.
|
|
||||||
Then start by running either:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
keycloak-/bin/standalone.sh
|
|
||||||
----
|
|
||||||
or:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
keycloak-/bin/standalone.bat
|
|
||||||
----
|
|
||||||
|
|
||||||
[[_overlay_install]]
|
|
||||||
=== Install on existing WildFly or JBoss EAP
|
|
||||||
|
|
||||||
Keycloak can be installed into an existing installations of WildFly or JBoss EAP . To do this download `keycloak-overlay-.zip` or `keycloak-overlay-.tar.gz`.
|
|
||||||
Once downloaded extract into the root directory of your installation.
|
|
||||||
|
|
||||||
To add Keycloak to existing standalone.xml server config run:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
bin/jboss-cli.sh --file=bin/keycloak-install.cli
|
|
||||||
----
|
|
||||||
To add Keycloak to existing standalone-ha.xml server config run:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
bin/jboss-cli.sh --file=bin/keycloak-install-ha.cli
|
|
||||||
----
|
|
||||||
If you want to add Keycloak to a different server config edit `keycloak-install.cli` or `keycloak-install-ha.cli` and change the name of the server config.
|
|
||||||
|
|
||||||
=== Install Development Bundle
|
|
||||||
|
|
||||||
The demo bundle contains everything you need to get started with Keycloak including documentation and examples.
|
|
||||||
To install it first download `keycloak-demo-.zip` or `keycloak-demo-.tar.gz`.
|
|
||||||
Once downloaded extract it inside `keycloak-demo-` you'll find `keycloak` which contains a full WildFly server with Keycloak Server and Adapters included.
|
|
||||||
You'll also find `docs` and `examples` which contains everything you need to get started developing applications that use Keycloak.
|
|
||||||
|
|
||||||
To start WildFly with Keycloak run:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
keycloak-/bin/standalone.sh
|
|
||||||
----
|
|
||||||
or:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
keycloak-/bin/standalone.bat
|
|
||||||
----
|
|
||||||
|
|
||||||
== Configuring the Server
|
|
||||||
|
|
||||||
Although the Keycloak Server is designed to run out of the box, there's some things you'll need to configure before you go into production.
|
|
||||||
Specifically:
|
|
||||||
|
|
||||||
* Configuring Keycloak to use a production database
|
|
||||||
* Setting up SSL/HTTPS
|
|
||||||
* Enforcing HTTPS connections
|
|
||||||
|
|
||||||
=== Admin User
|
|
||||||
|
|
||||||
To access the admin console to configure Keycloak you need an account to login.
|
|
||||||
There is no built in user, instead you have to first create an admin account.
|
|
||||||
This can done either by opening http://localhost:8080/auth (creating a user through the browser can only be done through localhost) or you can use the add-user script from the command-line.
|
|
||||||
|
|
||||||
The `add-user` script creates a temporary file with the details of the user, which are imported at startup.
|
|
||||||
To add a user with this script run:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
bin/add-user.[sh|bat] -r master -u <username> -p <password>
|
|
||||||
----
|
|
||||||
Then restart the server.
|
|
||||||
For `keycloak-overlay`, please make sure to use:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
bin/add-user-keycloak.[sh|bat] -r master -u <username> -p <password>
|
|
||||||
----
|
|
||||||
|
|
||||||
=== Relational Database Configuration
|
|
||||||
|
|
||||||
You might want to use a better relational database for Keycloak like PostgreSQL or MySQL.
|
|
||||||
You might also want to tweak the configuration settings of the datasource.
|
|
||||||
Please see the https://docs.jboss.org/author/display/WFLY8/DataSource+configuration[Wildfly] documentation on how to do this.
|
|
||||||
|
|
||||||
Keycloak runs on a Hibernate/JPA backend which is configured in the `standalone/configuration/keycloak-server.json`.
|
|
||||||
By default the setting is like this:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
"connectionsJpa": {
|
|
||||||
"default": {
|
|
||||||
"dataSource": "java:jboss/datasources/KeycloakDS",
|
|
||||||
"databaseSchema": "update"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
----
|
|
||||||
Possible configuration options are:
|
|
||||||
|
|
||||||
dataSource::
|
|
||||||
JNDI name of the dataSource
|
|
||||||
|
|
||||||
jta::
|
|
||||||
boolean property to specify if datasource is JTA capable
|
|
||||||
|
|
||||||
driverDialect::
|
|
||||||
Value of Hibernate dialect.
|
|
||||||
In most cases you don't need to specify this property as dialect will be autodetected by Hibernate.
|
|
||||||
|
|
||||||
databaseSchema::
|
|
||||||
Specify if schema should be updated or validated.
|
|
||||||
Valid values are "update" and "validate" ("update is default).
|
|
||||||
|
|
||||||
showSql::
|
|
||||||
Specify whether Hibernate should show all SQL commands in the console (false by default)
|
|
||||||
|
|
||||||
formatSql::
|
|
||||||
Specify whether Hibernate should format SQL commands (true by default)
|
|
||||||
|
|
||||||
globalStatsInterval::
|
|
||||||
Will log global statistics from Hibernate about executed DB queries and other things.
|
|
||||||
Statistics are always reported to server log at specified interval (in seconds) and are cleared after each report.
|
|
||||||
|
|
||||||
schema::
|
|
||||||
Specify the database schema to use
|
|
||||||
|
|
||||||
===== Tested databases
|
|
||||||
|
|
||||||
Here is list of RDBMS databases and corresponding JDBC drivers, which were tested with Keycloak.
|
|
||||||
Note that Hibernate dialect is usually set automatically according to your database, but you have possibility to override if default dialect doesn't work correctly.
|
|
||||||
You can setup dialect by adding property `driverDialect` to the `keycloak-server.json` into `connectionsJpa` section (see above).
|
|
||||||
|
|
||||||
.Tested databases
|
|
||||||
[cols="1,1,1", frame="all", options="header"]
|
|
||||||
|===
|
|
||||||
| Database
|
|
||||||
| JDBC driver
|
|
||||||
| Hibernate Dialect
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|===
|
|
||||||
|
|
||||||
=== MongoDB based model
|
|
||||||
|
|
||||||
Keycloak provides http://www.mongodb.com[MongoDB] based model implementation, which means that your identity data will be saved in MongoDB instead of traditional RDBMS.
|
|
||||||
To configure Keycloak to use Mongo open `standalone/configuration/keycloak-server.json` in your favourite editor, then change:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
"eventsStore": {
|
|
||||||
"provider": "jpa",
|
|
||||||
"jpa": {
|
|
||||||
"exclude-events": [ "REFRESH_TOKEN" ]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"realm": {
|
|
||||||
"provider": "jpa"
|
|
||||||
},
|
|
||||||
|
|
||||||
"user": {
|
|
||||||
"provider": "${keycloak.user.provider:jpa}"
|
|
||||||
},
|
|
||||||
----
|
|
||||||
to:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
"eventsStore": {
|
|
||||||
"provider": "mongo",
|
|
||||||
"mongo": {
|
|
||||||
"exclude-events": [ "REFRESH_TOKEN" ]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"realm": {
|
|
||||||
"provider": "mongo"
|
|
||||||
},
|
|
||||||
|
|
||||||
"user": {
|
|
||||||
"provider": "mongo"
|
|
||||||
},
|
|
||||||
----
|
|
||||||
And at the end of the file add the snippet like this where you can configure details about your Mongo database:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
"connectionsMongo": {
|
|
||||||
"default": {
|
|
||||||
"host": "127.0.0.1",
|
|
||||||
"port": "27017",
|
|
||||||
"db": "keycloak",
|
|
||||||
"connectionsPerHost": 100,
|
|
||||||
"databaseSchema": "update"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
||||||
All configuration options are optional.
|
|
||||||
Default values for host and port are localhost and 27017.
|
|
||||||
Default name of database is `keycloak` . You can also specify properties `user` and `password` if you want authenticate against your MongoDB.
|
|
||||||
If user and password are not specified, Keycloak will connect unauthenticated to your MongoDB.
|
|
||||||
|
|
||||||
Finally there is set of optional configuration options, which can be used to specify connection-pooling capabilities of Mongo client.
|
|
||||||
Supported int options are: `connectionsPerHost`, `threadsAllowedToBlockForConnectionMultiplier`, `maxWaitTime`, `connectTimeout` `socketTimeout`.
|
|
||||||
Supported boolean options are: `socketKeepAlive`, `autoConnectRetry`.
|
|
||||||
Supported long option is `maxAutoConnectRetryTime`.
|
|
||||||
See http://api.mongodb.org/java/2.11.4/com/mongodb/MongoClientOptions.html[Mongo documentation] for details about those options and their default values.
|
|
||||||
|
|
||||||
Alternatively, you can configure MongoDB using a MongoDB http://docs.mongodb.org/manual/reference/connection-string/[connection URI].
|
|
||||||
In this case, you define all information concerning the connection and authentication within the URI, as described in the MongoDB documentation.
|
|
||||||
Please note that the database specified within the URI is only used for authentication.
|
|
||||||
To change the database used by keycloak you have to set `db` property as before.
|
|
||||||
Therefore, a configuration like the following
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
"connectionsMongo": {
|
|
||||||
"default": {
|
|
||||||
"uri": "mongodb://user:password@127.0.0.1/authentication",
|
|
||||||
"db": "keycloak"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
||||||
will authenticate the user against the authentication database, but store all keycloak related data in the keycloak database.
|
|
||||||
|
|
||||||
==== MongoDB Replica Sets
|
|
||||||
|
|
||||||
In order to use a mongo replica set for Keycloak, one has to use URI based configuration, which supports the definition of replica sets out of the box: `mongodb://host1:27017,host2:27017,host3:27017/`.
|
|
||||||
|
|
||||||
=== Outgoing Server HTTP Requests
|
|
||||||
|
|
||||||
Keycloak server needs to invoke on remote HTTP endpoints to do things like backchannel logouts and other management functions.
|
|
||||||
Keycloak maintains a HTTP client connection pool which has various configuration settings you can specify before boot time.
|
|
||||||
This is configured in the `standalone/configuration/keycloak-server.json`.
|
|
||||||
By default the setting is like this:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
"connectionsHttpClient": {
|
|
||||||
"default": {}
|
|
||||||
},
|
|
||||||
----
|
|
||||||
Possible configuration options are:
|
|
||||||
|
|
||||||
establish-connection-timeout-millis::
|
|
||||||
Timeout for establishing a socket connection.
|
|
||||||
|
|
||||||
socket-timeout-millis::
|
|
||||||
If an outgoing request does not receive data for this amount of time, timeout the connection.
|
|
||||||
|
|
||||||
connection-pool-size::
|
|
||||||
How many connections can be in the pool (128 by default).
|
|
||||||
|
|
||||||
max-pooled-per-route::
|
|
||||||
How many connections can be pooled per host (64 by default).
|
|
||||||
|
|
||||||
connection-ttl-millis::
|
|
||||||
Maximum connection time to live in milliseconds.
|
|
||||||
Not set by default.
|
|
||||||
|
|
||||||
max-connection-idle-time-millis::
|
|
||||||
Maximum time the connection might stay idle in the connection pool (900 seconds by default). Will start background cleaner thread of Apache HTTP client.
|
|
||||||
Set to -1 to disable this checking and the background thread.
|
|
||||||
|
|
||||||
disable-cookies::
|
|
||||||
`true` by default.
|
|
||||||
When set to true, this will disable any cookie caching.
|
|
||||||
|
|
||||||
client-keystore::
|
|
||||||
This is the file path to a Java keystore file.
|
|
||||||
This keystore contains client certificate for two-way SSL.
|
|
||||||
|
|
||||||
client-keystore-password::
|
|
||||||
Password for the client keystore.
|
|
||||||
This is _REQUIRED_ if `client-keystore` is set.
|
|
||||||
|
|
||||||
client-key-password::
|
|
||||||
_Not supported yet, but we will support in future versions. Password for the client's key.
|
|
||||||
This is _REQUIRED_ if `client-keystore` is set.
|
|
||||||
|
|
||||||
[[_truststore]]
|
|
||||||
=== Securing Outgoing Server HTTP Requests
|
|
||||||
|
|
||||||
When Keycloak connects out to remote HTTP endpoints over secure https connection, it has to validate the other server's certificate in order to ensure it is connecting to a trusted server.
|
|
||||||
That is necessary in order to prevent man-in-the-middle attacks.
|
|
||||||
|
|
||||||
How certificates are validated is configured in the `standalone/configuration/keycloak-server.json`.
|
|
||||||
By default truststore provider is not configured, and any https connections fall back to standard java truststore configuration as described in https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html[
|
|
||||||
Java's JSSE Reference Guide] - using `javax.net.ssl.trustStore system property`, otherwise `cacerts` file that comes with java is used.
|
|
||||||
|
|
||||||
Truststore is used when connecting securely to identity brokers, LDAP identity providers, when sending emails, and for backchannel communication with client applications.
|
|
||||||
Some of these facilities may - in case when no trusted certificate is found in your configured truststore - fallback to using the JSSE provided truststore.
|
|
||||||
The default JavaMail API implementation used to send out emails behaves in this way, for example.
|
|
||||||
|
|
||||||
You can add your truststore configuration by using the following template:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
"truststore": {
|
|
||||||
"file": {
|
|
||||||
"file": "path to your .jks file containing public certificates",
|
|
||||||
"password": "password",
|
|
||||||
"hostname-verification-policy": "WILDCARD",
|
|
||||||
"disabled": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
Possible configuration options are:
|
|
||||||
|
|
||||||
file::
|
|
||||||
The value is the file path to a Java keystore file.
|
|
||||||
HTTPS requests need a way to verify the host of the server they are talking to.
|
|
||||||
This is what the trustore does.
|
|
||||||
The keystore contains one or more trusted host certificates or certificate authorities.
|
|
||||||
Truststore file should only contain public certificates of your secured hosts.
|
|
||||||
This is _REQUIRED_ if `disabled` is not true.
|
|
||||||
|
|
||||||
password::
|
|
||||||
Password for the truststore.
|
|
||||||
This is _REQUIRED_ if `disabled` is not true.
|
|
||||||
|
|
||||||
hostname-verification-policy::
|
|
||||||
`WILDCARD` by default.
|
|
||||||
For HTTPS requests, this verifies the hostname of the server's certificate.
|
|
||||||
`ANY` means that the hostname is not verified. `WILDCARD` Allows wildcards in subdomain names i.e.
|
|
||||||
*.foo.com. `STRICT` CN must match hostname exactly.
|
|
||||||
|
|
||||||
disabled::
|
|
||||||
If true (default value), truststore configuration will be ignored, and certificate checking will fall back to JSSE configuration as described.
|
|
||||||
If set to false, you must configure `file`, and `password` for the truststore.
|
|
||||||
|
|
||||||
You can use _keytool_ to create a new truststore file and add trusted host certificates to it:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ keytool -import -alias HOSTDOMAIN -keystore truststore.jks -file host-certificate.cer
|
|
||||||
----
|
|
||||||
|
|
||||||
[[_ssl_modes]]
|
|
||||||
=== SSL/HTTPS Requirement/Modes
|
|
||||||
|
|
||||||
WARNING: Keycloak is not set up by default to handle SSL/HTTPS.
|
|
||||||
It is highly recommended that you either enable SSL on the Keycloak server itself or on a reverse proxy in front of the Keycloak server.
|
|
||||||
|
|
||||||
Keycloak can run out of the box without SSL so long as you stick to private IP addresses like localhost, 127.0.0.1, 10.0.x.x, 192.168.x.x, and 172..16.x.x.
|
|
||||||
If you try to access Keycloak from a non-IP adress you will get an error.
|
|
||||||
|
|
||||||
Keycloak has 3 SSL/HTTPS modes which you can set up in the admin console under the Settings->Login page and the `Require SSL` select box.
|
|
||||||
Each adapter config should mirror this server-side setting.
|
|
||||||
See adapter config section for more details.
|
|
||||||
|
|
||||||
external::
|
|
||||||
Keycloak can run out of the box without SSL so long as you stick to private IP addresses like localhost, 127.0.0.1, 10.0.x.x, 192.168.x.x, and 172..16.x.x.
|
|
||||||
If you try to access Keycloak from a non-IP adress you will get an error.
|
|
||||||
|
|
||||||
none::
|
|
||||||
Keycloak does not require SSL.
|
|
||||||
|
|
||||||
all::
|
|
||||||
Keycloak requires SSL for all IP addresses.
|
|
||||||
|
|
||||||
=== SSL/HTTPS Setup
|
|
||||||
|
|
||||||
First enable SSL on Keycloak or on a reverse proxy in front of Keycloak.
|
|
||||||
Then configure the Keycloak Server to enforce HTTPS connections.
|
|
||||||
|
|
||||||
==== Enable SSL on Keycloak
|
|
||||||
|
|
||||||
The following things need to be done
|
|
||||||
|
|
||||||
* keytool
|
|
||||||
* Enable Wildfly to use this certificate and turn on SSL/HTTPS.
|
|
||||||
|
|
||||||
===== Creating the Certificate and Java Keystore
|
|
||||||
|
|
||||||
In order to allow HTTPS connections, you need to obtain a self signed or third-party signed certificate and import it into a Java keystore before you can enable HTTPS in the web container you are deploying the Keycloak Server to.
|
|
||||||
|
|
||||||
====== Self Signed Certificate
|
|
||||||
|
|
||||||
In development, you will probably not have a third party signed certificate available to test a Keycloak deployment so you'll need to generate a self-signed on.
|
|
||||||
Generate one is very easy to do with the `keytool` utility that comes with the Java jdk.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ keytool -genkey -alias localhost -keyalg RSA -keystore keycloak.jks -validity 10950
|
|
||||||
Enter keystore password: secret
|
|
||||||
Re-enter new password: secret
|
|
||||||
What is your first and last name?
|
|
||||||
[Unknown]: localhost
|
|
||||||
What is the name of your organizational unit?
|
|
||||||
[Unknown]: Keycloak
|
|
||||||
What is the name of your organization?
|
|
||||||
[Unknown]: Red Hat
|
|
||||||
What is the name of your City or Locality?
|
|
||||||
[Unknown]: Westford
|
|
||||||
What is the name of your State or Province?
|
|
||||||
[Unknown]: MA
|
|
||||||
What is the two-letter country code for this unit?
|
|
||||||
[Unknown]: US
|
|
||||||
Is CN=localhost, OU=Keycloak, O=Test, L=Westford, ST=MA, C=US correct?
|
|
||||||
[no]: yes
|
|
||||||
----
|
|
||||||
|
|
||||||
You should answer `What is your first and last name ?` question with the DNS name of the machine you're installing the server on.
|
|
||||||
For testing purposes, `localhost` should be used.
|
|
||||||
After executing this command, the `keycloak.jks` file will be generated in the same directory as you executed the `keytool` command in.
|
|
||||||
|
|
||||||
If you want a third-party signed certificate, but don't have one, you can obtain one for free at http://cacert.org[cacert.org].
|
|
||||||
You'll have to do a little set up first before doing this though.
|
|
||||||
|
|
||||||
The first thing to do is generate a Certificate Request:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ keytool -certreq -alias yourdomain -keystore keycloak.jks > keycloak.careq
|
|
||||||
----
|
|
||||||
|
|
||||||
Where `yourdomain` is a DNS name for which this certificate is generated for.
|
|
||||||
Keytool generates the request:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
-----BEGIN NEW CERTIFICATE REQUEST-----
|
|
||||||
MIIC2jCCAcICAQAwZTELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAk1BMREwDwYDVQQHEwhXZXN0Zm9y
|
|
||||||
ZDEQMA4GA1UEChMHUmVkIEhhdDEQMA4GA1UECxMHUmVkIEhhdDESMBAGA1UEAxMJbG9jYWxob3N0
|
|
||||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr7kck2TaavlEOGbcpi9c0rncY4HhdzmY
|
|
||||||
Ax2nZfq1eZEaIPqI5aTxwQZzzLDK9qbeAd8Ji79HzSqnRDxNYaZu7mAYhFKHgixsolE3o5Yfzbw1
|
|
||||||
29Rvy+eUVe+WZxv5oo9wolVVpdSINIMEL2LaFhtX/c1dqiqYVpfnvFshZQaIg2nL8juzZcBjj4as
|
|
||||||
H98gIS7khql/dkZKsw9NLvyxgJvp7PaXurX29fNf3ihG+oFrL22oFyV54BWWxXCKU/GPn61EGZGw
|
|
||||||
Ft2qSIGLdctpMD1aJR2bcnlhEjZKDksjQZoQ5YMXaAGkcYkG6QkgrocDE2YXDbi7GIdf9MegVJ35
|
|
||||||
2DQMpwIDAQABoDAwLgYJKoZIhvcNAQkOMSEwHzAdBgNVHQ4EFgQUQwlZJBA+fjiDdiVzaO9vrE/i
|
|
||||||
n2swDQYJKoZIhvcNAQELBQADggEBAC5FRvMkhal3q86tHPBYWBuTtmcSjs4qUm6V6f63frhveWHf
|
|
||||||
PzRrI1xH272XUIeBk0gtzWo0nNZnf0mMCtUBbHhhDcG82xolikfqibZijoQZCiGiedVjHJFtniDQ
|
|
||||||
9bMDUOXEMQ7gHZg5q6mJfNG9MbMpQaUVEEFvfGEQQxbiFK7hRWU8S23/d80e8nExgQxdJWJ6vd0X
|
|
||||||
MzzFK6j4Dj55bJVuM7GFmfdNC52pNOD5vYe47Aqh8oajHX9XTycVtPXl45rrWAH33ftbrS8SrZ2S
|
|
||||||
vqIFQeuLL3BaHwpl3t7j2lMWcK1p80laAxEASib/fAwrRHpLHBXRcq6uALUOZl4Alt8=
|
|
||||||
-----END NEW CERTIFICATE REQUEST-----
|
|
||||||
----
|
|
||||||
|
|
||||||
Send this ca request to your CA.
|
|
||||||
The CA will issue you a signed certificate and send it to you.
|
|
||||||
Before you import your new cert, you must obtain and import the root certificate of the CA.
|
|
||||||
You can download the cert from CA (ie.: root.crt) and import as follows:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ keytool -import -keystore keycloak.jks -file root.crt -alias root
|
|
||||||
----
|
|
||||||
|
|
||||||
Last step is import your new CA generated certificate to your keystore:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ keytool -import -alias yourdomain -keystore keycloak.jks -file your-certificate.cer
|
|
||||||
----
|
|
||||||
|
|
||||||
===== Installing the keystore to WildFly
|
|
||||||
|
|
||||||
Now that you have a Java keystore with the appropriate certificates, you need to configure your Wildfly installation to use it.
|
|
||||||
First step is to move the keystore file to a directory you can reference in configuration.
|
|
||||||
I like to put it in `standalone/configuration`.
|
|
||||||
Then you need to edit `standalone/configuration/standalone.xml` to enable SSL/HTTPS.
|
|
||||||
|
|
||||||
To the `security-realms` element add:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
<security-realm name="UndertowRealm">
|
|
||||||
<server-identities>
|
|
||||||
<ssl>
|
|
||||||
<keystore path="keycloak.jks" relative-to="jboss.server.config.dir" keystore-password="secret" />
|
|
||||||
</ssl>
|
|
||||||
</server-identities>
|
|
||||||
</security-realm>
|
|
||||||
----
|
|
||||||
|
|
||||||
Find the element `server name="default-server"` (it's a child element of `subsystem xmlns="urn:jboss:domain:undertow:1.0"`) and add:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
<https-listener name="https" socket-binding="https" security-realm="UndertowRealm"/>
|
|
||||||
----
|
|
||||||
|
|
||||||
Check the https://docs.jboss.org/author/display/WFLY8/Undertow+(web)+subsystem+configuration[Wildfly Undertow] documentation for more information on fine tuning the socket connections.
|
|
||||||
|
|
||||||
==== Enable SSL on a Reverse Proxy
|
|
||||||
|
|
||||||
Follow the documentation for your web server to enable SSL and configure reverse proxy for Keycloak.
|
|
||||||
It is important that you make sure the web server sets the `X-Forwarded-For` and `X-Forwarded-Proto` headers on the requests made to Keycloak.
|
|
||||||
Next you need to enable `proxy-address-forwarding` on the Keycloak http connector.
|
|
||||||
Assuming that your reverse proxy doesn't use port 8443 for SSL you also need to configure what port http traffic is redirected to.
|
|
||||||
|
|
||||||
===== Configure WildFly
|
|
||||||
|
|
||||||
. Open `standalone/configuration/standalone.xml` in your favorite editor.
|
|
||||||
|
|
||||||
. First add `proxy-address-forwarding` and `redirect-socket` to the `http-listener` element:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
<subsystem xmlns="urn:jboss:domain:undertow:1.1">
|
|
||||||
...
|
|
||||||
<http-listener name="default" socket-binding="http"
|
|
||||||
proxy-address-forwarding="true" redirect-socket="proxy-https"/>
|
|
||||||
...
|
|
||||||
</subsystem>
|
|
||||||
----
|
|
||||||
|
|
||||||
Then add a new `socket-binding` element to the `socket-binding-group` element:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
<socket-binding-group name="standard-sockets" default-interface="public"
|
|
||||||
port-offset="${jboss.socket.binding.port-offset:0}">
|
|
||||||
...
|
|
||||||
<socket-binding name="proxy-https" port="443"/>
|
|
||||||
...
|
|
||||||
</socket-binding-group>
|
|
||||||
----
|
|
||||||
|
|
||||||
Check the https://docs.jboss.org/author/display/WFLY8/Undertow+(web)+subsystem+configuration[WildFly] documentation for more information.
|
|
||||||
|
|
||||||
== Keycloak server in Domain Mode
|
|
||||||
|
|
||||||
In domain mode, you start the server with the "domain" command instead of the "standalone" command.
|
|
||||||
In this case, the Keycloak subsystem is defined in domain/configuration/domain.xml instead of standalone/configuration.standalone.xml.
|
|
||||||
Inside domain.xml, you will see more than one profile.
|
|
||||||
The Keycloak subsystem is defined for all initial profiles.
|
|
||||||
|
|
||||||
THe server is also added to server profiles.
|
|
||||||
By default two servers are started in the main-server-group which uses the full profile.
|
|
||||||
|
|
||||||
You need to make sure `domain/servers/SERVER NAME/configuration` is identical for all servers in a group.
|
|
||||||
|
|
||||||
To deploy custom providers and themes you should deploys these as modules and make sure the modules are available to all servers in the group.
|
|
||||||
See <<_providers,Providers>> and <<_themes,Themes>> sections for more information on how to do this.
|
|
||||||
|
|
||||||
== Installing Keycloak Server as Root Context
|
|
||||||
|
|
||||||
The Keycloak server can be installed as the default web application.
|
|
||||||
In doing so, the server can be referenced at `http://mydomain.com/` instead of `http://mydomain.com/auth`.
|
|
||||||
|
|
||||||
To do this, add the `default-web-module` attribute in the Undertow subystem in standalone.xml.
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
<subsystem xmlns="urn:jboss:domain:undertow:2.0">
|
|
||||||
<server name="default-server">
|
|
||||||
<host name="default-host" alias="localhost" default-web-module="keycloak-server.war">
|
|
||||||
<location name="/" handler="welcome-content"/>
|
|
||||||
</host>
|
|
||||||
----
|
|
||||||
|
|
||||||
`keycloak-server.war` is the runtime name of the Keycloak server application.
|
|
||||||
Note that the WAR file does not exist as a file.
|
|
||||||
If its name changes (ie. `keycloak-server.war`) in the future, find its new name from the Keycloak log entry with `runtime-name:`.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
NOTE: If you have run your server before altering the root context, your database will contain references to the old /auth context. Your clients may also have incorrect references.
|
|
||||||
To fix this on the server side, you will need to export your database to json, make corrections, and then import.
|
|
||||||
Client-side `keycloak.json` files will need to be updated manually as well.
|
|
|
@ -1,55 +0,0 @@
|
||||||
|
|
||||||
= Java Servlet Filter Adapter
|
|
||||||
|
|
||||||
If you want to use Keycloak with a Java servlet application that doesn't have an adapter for that servlet platform, you can opt to use the servlet filter adapter that Keycloak has.
|
|
||||||
This adapter works a little differently than the other adapters.
|
|
||||||
You do not define security constraints in web.xml.
|
|
||||||
Instead you define a filter mapping using the Keycloak servlet filter adapter to secure the url patterns you want to secure.
|
|
||||||
|
|
||||||
WARNING: Backchannel logout works a bit differently than the standard adapters.
|
|
||||||
Instead of invalidating the http session it instead marks the session id as logged out.
|
|
||||||
There's just no way of arbitrarily invalidating an http session based on a session id.
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
|
||||||
version="3.0">
|
|
||||||
|
|
||||||
<module-name>customer-portal</module-name>
|
|
||||||
|
|
||||||
<filter>
|
|
||||||
<filter-name>Keycloak Filter</filter-name>
|
|
||||||
<filter-class>org.keycloak.adapters.servlet.KeycloakOIDCFilter</filter-class>
|
|
||||||
</filter>
|
|
||||||
<filter-mapping>
|
|
||||||
<filter-name>Keycloak Filter</filter-name>
|
|
||||||
<url-pattern>/keycloak/*</url-pattern>
|
|
||||||
<url-pattern>/protected/*</url-pattern>
|
|
||||||
</filter-mapping>
|
|
||||||
</web-app>
|
|
||||||
----
|
|
||||||
|
|
||||||
If you notice above, there are two url-patterns.
|
|
||||||
`/protected/*` are just the files we want protected. `/keycloak/*` url-pattern will handle callback from the keycloak server.
|
|
||||||
Note that you should configure your client in the Keycloak Admin Console with an Admin URL that points to a secured section covered by the filter's url-pattern.
|
|
||||||
The Admin URL will make callbacks to the Admin URL to do things like backchannel logout.
|
|
||||||
So, the Admin URL in this example should be `http[s]://hostname/{context-root}/keycloak`.
|
|
||||||
There is an example of this in the distribution.
|
|
||||||
|
|
||||||
The Keycloak filter has the same configuration parameters available as the other adapters except you must define them as filter init params instead of context params.
|
|
||||||
|
|
||||||
To use this filter, include this maven artifact in your WAR poms
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-servlet-filter-adapter</artifactId>
|
|
||||||
<version>&project.version;</version>
|
|
||||||
</dependency>
|
|
||||||
----
|
|
|
@ -1,67 +0,0 @@
|
||||||
|
|
||||||
= Spring Boot Adapter
|
|
||||||
|
|
||||||
To be able to secure Spring Boot apps you must add the Keycloak Spring Boot adapter JAR to your app.
|
|
||||||
You then have to provide some extra configuration via normal Spring Boot configuration (`application.properties`). Let's go over these steps.
|
|
||||||
|
|
||||||
[[_spring_boot_adapter_installation]]
|
|
||||||
== Adapter Installation
|
|
||||||
|
|
||||||
The Keycloak Spring Boot adapter takes advantage of Spring Boot's autoconfiguration so all you need to do is add the Keycloak Spring Boot adapter JAR to your project.
|
|
||||||
Depending on what container you are using with Spring Boot, you also need to add the appropriate Keycloak container adapter.
|
|
||||||
If you are using Maven, add the following to your pom.xml (using Tomcat as an example):
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-spring-boot-adapter</artifactId>
|
|
||||||
<version>&project.version;</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-tomcat8-adapter</artifactId>
|
|
||||||
<version>&project.version;</version>
|
|
||||||
</dependency>
|
|
||||||
----
|
|
||||||
|
|
||||||
[[_spring_boot_adapter_configuration]]
|
|
||||||
== Required Spring Boot Adapter Configuration
|
|
||||||
|
|
||||||
This section describes how to configure your Spring Boot app to use Keycloak.
|
|
||||||
|
|
||||||
Instead of a `keycloak.json` file, you configure the realm for the Spring Boot Keycloak adapter via the normal Spring Boot configuration.
|
|
||||||
For example:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
keycloak.realm = demorealm
|
|
||||||
keycloak.realmKey = MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCLCWYuxXmsmfV+Xc9Ik8QET8lD4wuHrJAXbbutS2O/eMjQQLNK7QDX/k/XhOkhxP0YBEypqeXeGaeQJjCxDhFjJXQuewUEMlmSja3IpoJ9/hFn4Cns4m7NGO+rtvnfnwgVfsEOS5EmZhRddp+40KBPPJfTH6Vgu6KjQwuFPj6DTwIDAQAB
|
|
||||||
keycloak.auth-server-url = http://127.0.0.1:8080/auth
|
|
||||||
keycloak.ssl-required = external
|
|
||||||
keycloak.resource = demoapp
|
|
||||||
keycloak.credentials.secret = 11111111-1111-1111-1111-111111111111
|
|
||||||
keycloak.use-resource-role-mappings = true
|
|
||||||
----
|
|
||||||
|
|
||||||
You also need to specify the J2EE security config that would normally go in the `web.xml`.
|
|
||||||
Here's an example configuration:
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
keycloak.securityConstraints[0].securityCollections[0].name = insecure stuff
|
|
||||||
keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = admin
|
|
||||||
keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = user
|
|
||||||
keycloak.securityConstraints[0].securityCollections[0].patterns[0] = /insecure
|
|
||||||
|
|
||||||
keycloak.securityConstraints[0].securityCollections[1].name = admin stuff
|
|
||||||
keycloak.securityConstraints[0].securityCollections[1].authRoles[0] = admin
|
|
||||||
keycloak.securityConstraints[0].securityCollections[1].patterns[0] = /admin
|
|
||||||
----
|
|
|
@ -1,264 +0,0 @@
|
||||||
|
|
||||||
= Spring Security Adapter
|
|
||||||
|
|
||||||
To secure an application with Spring Security and Keycloak, add this adapter as a dependency to your project.
|
|
||||||
You then have to provide some extra beans in your Spring Security configuration file and add the Keycloak security filter to your pipeline.
|
|
||||||
|
|
||||||
Unlike the other Keycloak Adapters, you should not configure your security in web.xml.
|
|
||||||
However, keycloak.json is still required.
|
|
||||||
|
|
||||||
== Adapter Installation
|
|
||||||
|
|
||||||
Add Keycloak Spring Security adapter as a dependency to your Maven POM or Gradle build.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-spring-security-adapter</artifactId>
|
|
||||||
<version>&project.version;</version>
|
|
||||||
</dependency>
|
|
||||||
----
|
|
||||||
|
|
||||||
== Spring Security Configuration
|
|
||||||
|
|
||||||
The Keycloak Spring Security adapter takes advantage of Spring Security's flexible security configuration syntax.
|
|
||||||
|
|
||||||
=== Java Configuration
|
|
||||||
|
|
||||||
Keycloak provides a KeycloakWebSecurityConfigurerAdapter as a convenient base class for creating a http://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/config/annotation/web/WebSecurityConfigurer.html[WebSecurityConfigurer] instance.
|
|
||||||
The implementation allows customization by overriding methods.
|
|
||||||
While its use is not required, it greatly simplifies your security context configuration.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
|
|
||||||
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Registers the KeycloakAuthenticationProvider with the authentication manager.
|
|
||||||
*/
|
|
||||||
@Autowired
|
|
||||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
|
||||||
auth.authenticationProvider(keycloakAuthenticationProvider());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Defines the session authentication strategy.
|
|
||||||
*/
|
|
||||||
@Bean
|
|
||||||
@Override
|
|
||||||
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
|
|
||||||
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void configure(HttpSecurity http) throws Exception
|
|
||||||
{
|
|
||||||
super.configure(http);
|
|
||||||
http
|
|
||||||
.authorizeRequests()
|
|
||||||
.antMatchers("/customers*").hasRole("USER")
|
|
||||||
.antMatchers("/admin*").hasRole("ADMIN")
|
|
||||||
.anyRequest().permitAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
You must provide a session authentication strategy bean which should be of type `RegisterSessionAuthenticationStrategy` for public or confidential applications and `NullAuthenticatedSessionStrategy` for bearer-only applications.
|
|
||||||
|
|
||||||
Spring Security's `SessionFixationProtectionStrategy` is currently not supported because it changes the session identifier after login via Keycloak.
|
|
||||||
If the session identifier changes, universal log out will not work because Keycloak is unaware of the new session identifier.
|
|
||||||
|
|
||||||
=== XML Configuration
|
|
||||||
|
|
||||||
While Spring Security's XML namespace simplifies configuration, customizing the configuration can be a bit verbose.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
|
||||||
xmlns:context="http://www.springframework.org/schema/context"
|
|
||||||
xmlns:security="http://www.springframework.org/schema/security"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="
|
|
||||||
http://www.springframework.org/schema/beans
|
|
||||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
|
||||||
http://www.springframework.org/schema/context
|
|
||||||
http://www.springframework.org/schema/context/spring-context.xsd
|
|
||||||
http://www.springframework.org/schema/security
|
|
||||||
http://www.springframework.org/schema/security/spring-security.xsd">
|
|
||||||
|
|
||||||
<context:component-scan base-package="org.keycloak.adapters.springsecurity" />
|
|
||||||
|
|
||||||
<security:authentication-manager alias="authenticationManager">
|
|
||||||
<security:authentication-provider ref="keycloakAuthenticationProvider" />
|
|
||||||
</security:authentication-manager>
|
|
||||||
|
|
||||||
<bean id="adapterDeploymentContext" class="org.keycloak.adapters.springsecurity.AdapterDeploymentContextFactoryBean">
|
|
||||||
<constructor-arg value="/WEB-INF/keycloak.json" />
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<bean id="keycloakAuthenticationEntryPoint" class="org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationEntryPoint" />
|
|
||||||
<bean id="keycloakAuthenticationProvider" class="org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider" />
|
|
||||||
<bean id="keycloakPreAuthActionsFilter" class="org.keycloak.adapters.springsecurity.filter.KeycloakPreAuthActionsFilter" />
|
|
||||||
<bean id="keycloakAuthenticationProcessingFilter" class="org.keycloak.adapters.springsecurity.filter.KeycloakAuthenticationProcessingFilter">
|
|
||||||
<constructor-arg name="authenticationManager" ref="authenticationManager" />
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<bean id="keycloakLogoutHandler" class="org.keycloak.adapters.springsecurity.authentication.KeycloakLogoutHandler">
|
|
||||||
<constructor-arg ref="adapterDeploymentContext" />
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<bean id="logoutFilter" class="org.springframework.security.web.authentication.logout.LogoutFilter">
|
|
||||||
<constructor-arg name="logoutSuccessUrl" value="/" />
|
|
||||||
<constructor-arg name="handlers">
|
|
||||||
<list>
|
|
||||||
<ref bean="keycloakLogoutHandler" />
|
|
||||||
<bean class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
|
|
||||||
</list>
|
|
||||||
</constructor-arg>
|
|
||||||
<property name="logoutRequestMatcher">
|
|
||||||
<bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
|
|
||||||
<constructor-arg name="pattern" value="/sso/logout**" />
|
|
||||||
<constructor-arg name="httpMethod" value="GET" />
|
|
||||||
</bean>
|
|
||||||
</property>
|
|
||||||
</bean>
|
|
||||||
|
|
||||||
<security:http auto-config="false" entry-point-ref="keycloakAuthenticationEntryPoint">
|
|
||||||
<security:custom-filter ref="keycloakPreAuthActionsFilter" before="LOGOUT_FILTER" />
|
|
||||||
<security:custom-filter ref="keycloakAuthenticationProcessingFilter" before="FORM_LOGIN_FILTER" />
|
|
||||||
<security:intercept-url pattern="/customers**" access="ROLE_USER" />
|
|
||||||
<security:intercept-url pattern="/admin**" access="ROLE_ADMIN" />
|
|
||||||
<security:custom-filter ref="logoutFilter" position="LOGOUT_FILTER" />
|
|
||||||
</security:http>
|
|
||||||
|
|
||||||
</beans>
|
|
||||||
----
|
|
||||||
|
|
||||||
== Multi Tenancy
|
|
||||||
|
|
||||||
The Keycloak Spring Security adapter also supports multi tenancy.
|
|
||||||
Instead of injecting `AdapterDeploymentContextFactoryBean` with the path to `keycloak.json` you can inject an implementation of the `KeycloakConfigResolver` interface.
|
|
||||||
More details on how to implement the `KeycloakConfigResolver` can be found in <<_multi_tenancy>>.
|
|
||||||
|
|
||||||
== Naming Security Roles
|
|
||||||
|
|
||||||
Spring Security, when using role-based authentication, requires that role names start with `ROLE_`.
|
|
||||||
For example, an administrator role must be declared in Keycloak as `ROLE_ADMIN` or similar, not simply `ADMIN`.
|
|
||||||
|
|
||||||
The class `org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider` supports an optional `org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper` which can be used to map roles coming from Keycloak to roles recognized by Spring Security.
|
|
||||||
Use, for example, `org.springframework.security.core.authority.mapping.SimpleAuthorityMapper` to insert the `ROLE_` prefix and convert the role name to upper case.
|
|
||||||
The class is part of Spring Security Core module.
|
|
||||||
|
|
||||||
== Client to Client Support
|
|
||||||
|
|
||||||
To simplify communication between clients, Keycloak provides an extension of Spring's `RestTemplate` that handles bearer token authentication for you.
|
|
||||||
To enable this feature your security configuration must add the `KeycloakRestTemplate` bean.
|
|
||||||
Note that it must be scoped as a prototype to function correctly.
|
|
||||||
|
|
||||||
For Java configuration:
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
@ComponentScan(basePackageClasses = KeycloakSecurityComponents.class)
|
|
||||||
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public KeycloakClientRequestFactory keycloakClientRequestFactory;
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
|
||||||
public KeycloakRestTemplate keycloakRestTemplate() {
|
|
||||||
return new KeycloakRestTemplate(keycloakClientRequestFactory);
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
For XML configuration:
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
<bean id="keycloakRestTemplate" class="org.keycloak.adapters.springsecurity.client.KeycloakRestTemplate" scope="prototype">
|
|
||||||
<constructor-arg name="factory" ref="keycloakClientRequestFactory" />
|
|
||||||
</bean>
|
|
||||||
----
|
|
||||||
|
|
||||||
Your application code can then use `KeycloakRestTemplate` any time it needs to make a call to another client.
|
|
||||||
For example:
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Service
|
|
||||||
public class RemoteProductService implements ProductService {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private KeycloakRestTemplate template;
|
|
||||||
|
|
||||||
private String endpoint;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public List<String> getProducts() {
|
|
||||||
ResponseEntity<String[]> response = template.getForEntity(endpoint, String[].class);
|
|
||||||
return Arrays.asList(response.getBody());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
||||||
|
|
||||||
== Spring Boot Configuration
|
|
||||||
|
|
||||||
Spring Boot attempts to eagerly register filter beans with the web application context.
|
|
||||||
Therefore, when running the Keycloak Spring Security adapter in a Spring Boot environment, it may be necessary to add two ``FilterRegistrationBean``s to your security configuration to prevent the Keycloak filters from being registered twice.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
@Configuration
|
|
||||||
@EnableWebSecurity
|
|
||||||
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter
|
|
||||||
{
|
|
||||||
...
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public FilterRegistrationBean keycloakAuthenticationProcessingFilterRegistrationBean(
|
|
||||||
KeycloakAuthenticationProcessingFilter filter) {
|
|
||||||
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
|
|
||||||
registrationBean.setEnabled(false);
|
|
||||||
return registrationBean;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public FilterRegistrationBean keycloakPreAuthActionsFilterRegistrationBean(
|
|
||||||
KeycloakPreAuthActionsFilter filter) {
|
|
||||||
FilterRegistrationBean registrationBean = new FilterRegistrationBean(filter);
|
|
||||||
registrationBean.setEnabled(false);
|
|
||||||
return registrationBean;
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
}
|
|
||||||
----
|
|
|
@ -1,87 +0,0 @@
|
||||||
|
|
||||||
[[_tomcat_adapter]]
|
|
||||||
= Tomcat 6, 7 and 8 Adapters
|
|
||||||
|
|
||||||
To be able to secure WAR apps deployed on Tomcat 6, 7 and 8 you must install the Keycloak Tomcat 6, 7 or 8 adapter into your Tomcat installation.
|
|
||||||
You then have to provide some extra configuration in each WAR you deploy to Tomcat.
|
|
||||||
Let's go over these steps.
|
|
||||||
|
|
||||||
[[_tomcat_adapter_installation]]
|
|
||||||
== Adapter Installation
|
|
||||||
|
|
||||||
Adapters are no longer included with the appliance or war distribution.
|
|
||||||
Each adapter is a separate download on the Keycloak download site.
|
|
||||||
They are also available as a maven artifact.
|
|
||||||
|
|
||||||
You must unzip the adapter distro into Tomcat's `lib/` directory.
|
|
||||||
Including adapter's jars within your WEB-INF/lib directory will not work! The Keycloak adapter is implemented as a Valve and valve code must reside in Tomcat's main lib/ directory.
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
$ cd $TOMCAT_HOME/lib
|
|
||||||
$ unzip keycloak-tomcat6-adapter-dist.zip
|
|
||||||
or
|
|
||||||
$ unzip keycloak-tomcat7-adapter-dist.zip
|
|
||||||
or
|
|
||||||
$ unzip keycloak-tomcat8-adapter-dist.zip
|
|
||||||
----
|
|
||||||
|
|
||||||
== Required Per WAR Configuration
|
|
||||||
|
|
||||||
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
|
|
||||||
|
|
||||||
The first thing you must do is create a `META-INF/context.xml` file in your WAR package.
|
|
||||||
This is a Tomcat specific config file and you must define a Keycloak specific Valve.
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
<Context path="/your-context-path">
|
|
||||||
<Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
|
|
||||||
</Context>
|
|
||||||
----
|
|
||||||
|
|
||||||
Next you must create a `keycloak.json` adapter config file within the `WEB-INF` directory of your WAR.
|
|
||||||
The format of this config file is describe in the <<_adapter_config,general adapter configuration>> section.
|
|
||||||
|
|
||||||
Finally you must specify both a `login-config` and use standard servlet security to specify role-base constraints on your URLs.
|
|
||||||
Here's an example:
|
|
||||||
|
|
||||||
|
|
||||||
[source]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
|
||||||
version="3.0">
|
|
||||||
|
|
||||||
<module-name>customer-portal</module-name>
|
|
||||||
|
|
||||||
<security-constraint>
|
|
||||||
<web-resource-collection>
|
|
||||||
<web-resource-name>Customers</web-resource-name>
|
|
||||||
<url-pattern>/*</url-pattern>
|
|
||||||
</web-resource-collection>
|
|
||||||
<auth-constraint>
|
|
||||||
<role-name>user</role-name>
|
|
||||||
</auth-constraint>
|
|
||||||
</security-constraint>
|
|
||||||
|
|
||||||
<login-config>
|
|
||||||
<auth-method>BASIC</auth-method>
|
|
||||||
<realm-name>this is ignored currently</realm-name>
|
|
||||||
</login-config>
|
|
||||||
|
|
||||||
<security-role>
|
|
||||||
<role-name>admin</role-name>
|
|
||||||
</security-role>
|
|
||||||
<security-role>
|
|
||||||
<role-name>user</role-name>
|
|
||||||
</security-role>
|
|
||||||
</web-app>
|
|
||||||
----
|
|
Loading…
Reference in a new issue