From f823a1fc3dc26922f3205c8e5cc2030873acfcc7 Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Fri, 3 Jun 2016 09:05:27 +0200 Subject: [PATCH 1/4] Fix links --- topics/oidc/java/java-adapter-config.adoc | 6 ++-- topics/oidc/java/java-adapters.adoc | 2 +- topics/oidc/java/servlet-filter-adapter.adoc | 2 +- topics/oidc/java/spring-boot-adapter.adoc | 2 +- topics/oidc/java/spring-security-adapter.adoc | 2 +- topics/oidc/javascript-adapter.adoc | 2 +- topics/overview/supported-platforms.adoc | 28 +++++++++---------- 7 files changed, 22 insertions(+), 22 deletions(-) diff --git a/topics/oidc/java/java-adapter-config.adoc b/topics/oidc/java/java-adapter-config.adoc index 8067941f38..cce3a132a8 100644 --- a/topics/oidc/java/java-adapter-config.adoc +++ b/topics/oidc/java/java-adapter-config.adoc @@ -169,18 +169,18 @@ always-refresh-token:: register-node-at-startup:: If _true_, then adapter will send registration request to Keycloak. It's _false_ by default and useful only when application is clustered. - See link:application-clustering.html[Application Clustering] for details + See <> for details register-node-period:: Period for re-registration adapter to Keycloak. Useful when application is clustered. - See link:application-clustering.html[Application Clustering] for details + See <> 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 link:application-clustering.html[Application Clustering] for details + See <> for details principal-attribute:: OpenID Connection ID Token attribute to populate the UserPrincipal name with. diff --git a/topics/oidc/java/java-adapters.adoc b/topics/oidc/java/java-adapters.adoc index a6a5f10113..4aea42c559 100644 --- a/topics/oidc/java/java-adapters.adoc +++ b/topics/oidc/java/java-adapters.adoc @@ -2,5 +2,5 @@ {{book.project.name}} comes with a range of different adapters for Java application. Selecting the correct adapter depends on the target platform. -All Java adapters share a set of common configuration options described in the link:java-adapter-config.html[Java Adapters Config] chapter. There are also +All Java adapters share a set of common configuration options described in the <> chapter. There are also a few more chapters that are relevant to all Java adapters. \ No newline at end of file diff --git a/topics/oidc/java/servlet-filter-adapter.adoc b/topics/oidc/java/servlet-filter-adapter.adoc index 99e83244f7..035ecefd41 100755 --- a/topics/oidc/java/servlet-filter-adapter.adoc +++ b/topics/oidc/java/servlet-filter-adapter.adoc @@ -1,4 +1,4 @@ - +[[_servlet_filter_adapter]] === 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. diff --git a/topics/oidc/java/spring-boot-adapter.adoc b/topics/oidc/java/spring-boot-adapter.adoc index ef70d29bb1..87f59a036d 100755 --- a/topics/oidc/java/spring-boot-adapter.adoc +++ b/topics/oidc/java/spring-boot-adapter.adoc @@ -1,4 +1,4 @@ - +[[_spring_boot_adapter]] === Spring Boot Adapter To be able to secure Spring Boot apps you must add the Keycloak Spring Boot adapter JAR to your app. diff --git a/topics/oidc/java/spring-security-adapter.adoc b/topics/oidc/java/spring-security-adapter.adoc index 2766317e32..84e8b6c3ad 100755 --- a/topics/oidc/java/spring-security-adapter.adoc +++ b/topics/oidc/java/spring-security-adapter.adoc @@ -1,4 +1,4 @@ - +[[_spring_security_adapter]] === Spring Security Adapter To secure an application with Spring Security and Keycloak, add this adapter as a dependency to your project. diff --git a/topics/oidc/javascript-adapter.adoc b/topics/oidc/javascript-adapter.adoc index a9591730dd..3bda03a5c7 100755 --- a/topics/oidc/javascript-adapter.adoc +++ b/topics/oidc/javascript-adapter.adoc @@ -1,4 +1,4 @@ - +[[_javascript_adapter]] == Javascript Adapter The Keycloak Server comes with a Javascript library you can use to secure HTML/Javascript applications. diff --git a/topics/overview/supported-platforms.adoc b/topics/overview/supported-platforms.adoc index 3590ed4b3e..1a630d16dc 100644 --- a/topics/overview/supported-platforms.adoc +++ b/topics/overview/supported-platforms.adoc @@ -3,26 +3,26 @@ === OpenID Connect ==== Java -* link:oidc/java/jboss-adapters.html[JBoss EAP] +* <> {% if book.community %} - * link:oidc/java/jboss-adapters.html[WildFly] + * <> {% endif %} -* link:oidc/java/fuse-adapter.html[Fuse] +* <> {% if book.community %} - * link:oidc/java/tomcat-adapter.html[Tomcat] - * link:oidc/java/jetty-adapter.html[Jetty] + * <> + * <>, <> {% endif %} -* link:oidc/java/servlet-filter-adapter.html[Servlet Filter] +* <> {% if book.community %} - * link:oidc/java/spring-adapter.html[Spring Security] (community) - * link:oidc/java/spring-boot-adapter.html[Spring Boot] (community) + * <> (community) + * <> (community) {% endif %} ==== JavaScript (client-side) -* link:oidc/javascript-adapter.html[JavaScript] +* <> === Apache Cordova -* link:oidc/javascript-adapter.html[JavaScript] +* <> {% if book.community %} ==== Node.js @@ -61,11 +61,11 @@ ==== Java -* link:oidc/java/jboss-adapters.html[JBoss EAP] +* <> {% if book.community %} -* link:oidc/java/jboss-adapters.html[WildFly] -* link:oidc/java/tomcat-adapter.html[Tomcat] -* link:oidc/java/jetty-adapter.html[Jetty] +* <> +* <> +* <> {% endif %} ==== Apache HTTP Server From d53fe6a8f42f9f7f9cb772d29a257cc3bc2e4ad6 Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Fri, 3 Jun 2016 09:10:01 +0200 Subject: [PATCH 2/4] Replace Keycloak with project name --- topics/oidc/java/java-adapter-config.adoc | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/topics/oidc/java/java-adapter-config.adoc b/topics/oidc/java/java-adapter-config.adoc index cce3a132a8..03000d5a58 100644 --- a/topics/oidc/java/java-adapter-config.adoc +++ b/topics/oidc/java/java-adapter-config.adoc @@ -2,7 +2,7 @@ [[_java_adapter_config]] === Java Adapter Config -Each Java adapter supported by Keycloak can be configured by a simple JSON file. +Each Java adapter supported by {{book.project.name}} can be configured by a simple JSON file. This is what one might look like: [source,json] @@ -71,7 +71,7 @@ use-resource-role-mappings:: The default value is _false_. public-client:: - If set to true, the adapter will not send credentials for the client to Keycloak. + If set to true, the adapter will not send credentials for the client to {{book.project.name}}. This is _OPTIONAL_. The default value is _false_. @@ -118,8 +118,8 @@ credentials:: 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. + Adapters will make separate HTTP invocations to the {{book.project.name}} server to turn an access code into an access token. + This config option defines how many connections to the {{book.project.name}} server should be pooled. This is _OPTIONAL_. The default value is `20`. @@ -130,7 +130,7 @@ disable-trust-manager:: The default value is `false`. allow-any-hostname:: - If the {{book.project.name}} server requires HTTPS and this config option is set to `true` the Keycloak Server's certificate is validated via the truststore, + If the {{book.project.name}} server requires HTTPS and this config option is set to `true` the {{book.project.name}} server's certificate is validated via the truststore, but host name validation is not done. This setting should only be used during development and *never* in production as it will disable verification of SSL certificates. This seting may be useful in test environments This is _OPTIONAL_. @@ -143,7 +143,7 @@ truststore:: 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. + You can create this truststore by extracting the public certificate of the {{book.project.name}} server's SSL keystore. This is _OPTIONAL_ if `ssl-required` is `none` or `disable-trust-manager` is `true`. truststore-password:: @@ -167,12 +167,12 @@ always-refresh-token:: If _true_, the adapter will refresh token in every request. register-node-at-startup:: - If _true_, then adapter will send registration request to Keycloak. + If _true_, then adapter will send registration request to {{book.project.name}}. It's _false_ by default and useful only when application is clustered. See <> for details register-node-period:: - Period for re-registration adapter to Keycloak. + Period for re-registration adapter to {{book.project.name}}. Useful when application is clustered. See <> for details From d1f3dc049fed7274da2f032a8097d84a09becdea Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Fri, 3 Jun 2016 10:02:59 +0200 Subject: [PATCH 3/4] Updated JBoss adapter chapter --- topics/oidc/java/jboss-adapter.adoc | 204 +++++++++++++++------------- 1 file changed, 111 insertions(+), 93 deletions(-) diff --git a/topics/oidc/java/jboss-adapter.adoc b/topics/oidc/java/jboss-adapter.adoc index d65ac497be..f4d861fe13 100755 --- a/topics/oidc/java/jboss-adapter.adoc +++ b/topics/oidc/java/jboss-adapter.adoc @@ -1,110 +1,137 @@ [[_jboss_adapter]] -=== JBoss/Wildfly Adapter +{% if book.community %} +=== JBoss EAP/Wildfly Adapter +{% endif %} +{% if book.product %} +=== JBoss EAP Adapter +{% endif %} -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. +To be able to secure WAR apps deployed on JBoss EAP {% if book.community %}, WildFly or JBoss AS{% endif %}, you must install and configure the +{{book.project.name}} adapter subsystem. You then have two options to secure your WARs. + +You can provide an adapter config file in your WAR and change the auth-method to KEYCLOAK within web.xml. + +Alternatively, you don't have to modify your WAR at all and you can secure it via the {{book.project.name}} adapter 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. +Adapters are available as a separate archive and are also available as Maven artifacts. -Install on Wildfly 9 or 10: +{% if book.community %} +Install on Wildfly 9 or 10: -[source] +[source,bash] ---- - $ cd $WILDFLY_HOME -$ unzip keycloak-wildfly-adapter-dist.zip ----- -Install on Wildfly 8: - -[source] +$ unzip keycloak-wildfly-adapter-dist-{{book.project.version}}.zip ---- +Install on Wildfly 8: + +[source,bash] +---- $ cd $WILDFLY_HOME -$ unzip keycloak-wf8-adapter-dist.zip ----- -Install on JBoss EAP 6.x: +$ unzip keycloak-wf8-adapter-dist-{{book.project.version}}.zip +---- + +Install on JBoss EAP 7: [source] ---- +$ cd $EAP_HOME +$ unzip keycloak-eap7-adapter-dist-{{book.project.version}}.zip +---- +Install on JBoss EAP 6: + +[source] +---- +$ cd $EAP_HOME +$ unzip keycloak-eap6-adapter-dist-{{book.project.version}}.zip +---- + +Install on JBoss AS 7.1: + +[source] +---- $ cd $JBOSS_HOME -$ unzip keycloak-eap6-adapter-dist.zip ----- -Install on JBoss AS 7.1.1: +$ unzip keycloak-as7-adapter-dist-{{book.project.version}}.zip +---- +{% endif %} + +{% if book.product %} +Install on JBoss EAP 7: [source] ---- +$ cd $EAP_HOME +$ unzip RH-SSO-{{book.project.version}}-eap7-adapter.zip +---- -$ cd $JBOSS_HOME -$ unzip keycloak-as7-adapter-dist.zip +Install on JBoss EAP 6: + +[source] +---- +$ cd $EAP_HOME +$ unzip RH-SSO-{{book.project.version}}-eap6-adapter.zip +---- +{% endif %} + +This ZIP archive contains JBoss Modules specific to the {{book.project.name}} adapter. It also contains JBoss CLI scripts to install and configure the adapter. + +Once the ZIP archive is extracted you have to enable the {{book.project.name}} subystem in the server configuration (i.e. `standalone.xml`). The easiest way to +do this is to use the supplied JBoss CLI scripts. + +To install and configure the adapter, first start the server and then run the JBoss CLI installation script : + +[source] +---- +$ ./bin/jboss-cli.sh -c --file=adapter-install.cli +---- + +The script will add the required configuration to the server configuration file. + +For JBoss EAP 7 {% if book.community %} and WildFly 9+{% endif %} there is also an offline CLI script that can be used to install the adapter while the server +is not running: + +[source] +---- +$ ./bin/jboss-cli.sh -c --file=adapter-install-offline.cli ---- -This zip file creates new JBoss Modules specific to the Wildfly Keycloak Adapter within your Wildfly distro. +If you are planning to add it manually you need to add the extension and subsystem definition to the server configuration: -After adding the Keycloak modules, you must then enable the Keycloak Subsystem within your app server's server configuration: `domain.xml` or `standalone.xml`. +[source,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. +If you need to be able to propagate the security context from the web tier to the EJB tier you also need to add the `keycloak` security domain: -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] +[source,xml] ---- - -$ cd $JBOSS_HOME/bin -$ jboss-cli.sh -c --file=adapter-install-offline.cli ----- - -[source] ----- - - - - - - ... - - - - - ... - ----- - -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] ----- - - - + -... - - - - - + ... + + + + + + ... ---- 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: @@ -142,30 +169,27 @@ public class CustomerService { } ---- -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. +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. +Here's an example: -[source] +[source,xml] ---- - - customer-portal + application @@ -208,16 +232,13 @@ Here's an example pulled from one of the examples that comes distributed with Ke ==== 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. +You do not have to modify your WAR to secure it with {{book.project.title}}. Instead you can externally secure it via the {{book.project.title}} 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. +This metadata is instead defined within server configuration (i.e. `standalone.xml`) in the {{book.project.title}} subsystem definition. - -[source] +[source,xml] ---- - @@ -236,25 +257,22 @@ This metadata is instead defined within XML in your server's `domain.xml` or `st ---- - 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. +To make it easier for you, you can go to the {{book.project.title}} Administration 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] +[source,xml] ---- - - MIGfMA0GCSqGSIb3DQEBA + MIGfMA0GCSqGSIb3DQEBA... http://localhost:8080/auth external From 43ffe3c962a012828ff379bca14c939fc185ac09 Mon Sep 17 00:00:00 2001 From: Stian Thorgersen Date: Fri, 3 Jun 2016 12:35:36 +0200 Subject: [PATCH 4/4] Complete Java chapters --- SUMMARY.adoc | 2 +- topics/oidc/java/adapter-context.adoc | 25 ++-- topics/oidc/java/adapter_error_handling.adoc | 58 +++----- topics/oidc/java/application-clustering.adoc | 138 ++++++++----------- topics/oidc/java/jaas.adoc | 37 ++--- topics/oidc/java/logout.adoc | 5 +- topics/oidc/java/multi-tenancy.adoc | 68 ++++++--- topics/oidc/java/servlet-filter-adapter.adoc | 43 +++--- topics/oidc/oidc-generic.adoc | 1 + 9 files changed, 183 insertions(+), 194 deletions(-) diff --git a/SUMMARY.adoc b/SUMMARY.adoc index 3fd60bed92..cc60f2abca 100755 --- a/SUMMARY.adoc +++ b/SUMMARY.adoc @@ -20,7 +20,7 @@ {% endif %} ... link:topics/oidc/java/servlet-filter-adapter.adoc[Java Servlet Filter Adapter] ... link:topics/oidc/java/jaas.adoc[JAAS plugin] - ... link:topics/oidc/java/adapter-context.adoc[Keycloak Security Context] + ... link:topics/oidc/java/adapter-context.adoc[Security Context] ... link:topics/oidc/java/adapter_error_handling.adoc[Error Handling] ... link:topics/oidc/java/logout.adoc[Logout] ... link:topics/oidc/java/multi-tenancy.adoc[Multi Tenancy] diff --git a/topics/oidc/java/adapter-context.adoc b/topics/oidc/java/adapter-context.adoc index 9ac083172f..41319b0c76 100755 --- a/topics/oidc/java/adapter-context.adoc +++ b/topics/oidc/java/adapter-context.adoc @@ -1,12 +1,19 @@ -=== Keycloak Security Context +=== Security Context -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. +The `KeycloakSecurityContext` interface is available if you need to access to the tokens directly. This could be useful if you want to retrieve additional +details from the token (such as user profile information) or you want to invoke a RESTful service that is protected by {{book.project.title}}. -[source] +In servlet environments it is available in secured invocations as an attribute in HttpServletRequest: +[source,java] +---- +httpServletRequest + .getAttribute(KeycloakSecurityContext.class.getName()); +---- + +Or, it is available in secure and insecure requests in the HttpSession: + +[source,java] +---- +httpServletRequest.getSession() + .getAttribute(KeycloakSecurityContext.class.getName()); ---- -httpServletRequest.getAttribute(KeycloakSecurityContext.class.getName()); -httpServletRequest.getSession().getAttribute(KeycloakSecurityContext.class.getName()); ----- diff --git a/topics/oidc/java/adapter_error_handling.adoc b/topics/oidc/java/adapter_error_handling.adoc index bf300cd7ca..6e6beadfa9 100755 --- a/topics/oidc/java/adapter_error_handling.adoc +++ b/topics/oidc/java/adapter_error_handling.adoc @@ -2,59 +2,33 @@ [[_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()`. +{{book.project.name}} has some error handling facilities for servlet based client adapters. +When an error is encountered in authentication, {{book.project.title}} 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. +{{book.project.title}} may throw 400, 401, 403, and 500 errors. - -[source] +[source,xml] ---- - - 404 /ErrorHandler ---- -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. +{{book.project.name}} also sets a `HttpServletRequest` attribute that you can retrieve. +The attribute name is `org.keycloak.adapters.spi.AuthenticationError`, which should be casted to to `org.keycloak.adapters.OIDCAuthenticationError`. +For example: -[source] +[source,java] ---- +import org.keycloak.adapters.OIDCAuthenticationError; +import org.keycloak.adapters.OIDCAuthenticationError.Reason; +... -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 - } +OIDCAuthenticationError error = (OIDCAuthenticationError) httpServletRequest + .getAttribute('org.keycloak.adapters.spi.AuthenticationError'); - 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; - } -} ----- \ No newline at end of file +Reason reason = error.getReason(); +System.out.println(reason.name()); +---- \ No newline at end of file diff --git a/topics/oidc/java/application-clustering.adoc b/topics/oidc/java/application-clustering.adoc index b2d0b0a834..50a8d591bb 100644 --- a/topics/oidc/java/application-clustering.adoc +++ b/topics/oidc/java/application-clustering.adoc @@ -1,131 +1,113 @@ [[_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: +This chapter is related to supporting clustered applications deployed to JBoss EAP{% if book.community %}, WildFly and JBoss AS{% endif %}. -* 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 +There are several options depending on if your application is: -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. +* Stateless or stateful +* Distributable (replicated http session) or non-distributable +* Relying on sticky sessions provided by load balancer +* Hosted on same domain as {{book.project.name}} -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. +Dealing with clustering is not quite as simple as for a regular application. Mainly due to the fact that both the browser and the server-side application +sends requests to {{book.project.name}}, so it's not as simple as enabling sticky sessions on your load balancer. ==== 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. +By default, the web application secured by {{book.project.name}} uses the HTTP session to store security context. This means that you either have to +enable sticky sessions or replicate the HTTP session. -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: +As an alternative to storing the security context in the HTTP session the adapter can be configured to store this in a cookie instead. This is useful if you want +to make your application stateless or if you don't want to store the security context in the HTTP session. -* 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] +To use the cookie store for saving the security context, edit your applications `WEB-INF/keycloak.json` and add: +[source,json] ---- - - "token-store": "cookie" ---- -Default value of `token-store` is `session`, hence saving data in HTTP session. +NOTE: The default value for `token-store` is `session`, which stores the security context in the 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). +One limitation of using the cookie store is that the whole security context is passed in the cookie for every HTTP request. This may impact performance. + +Another small limitation is limited support for Single-Sign Out. It works without issues if you init servlet logout (HttpServletRequest.logout) from the +application itself as the adapter will delete the KEYCLOAK_ADAPTER_STATE cookie. However, back-channel logout initialized from a different application isn't +propagated by {{book.project.name}} to applications using cookie store. Hence it's recommended to use a short value for the access token timeout (for example 1 minute). ==== 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. +In deployment scenarios where {{book.project.name}} and the application is hosted on the same domain (through a reverse proxy or load balancer) it can be +convenient to use relative URI options in your client configuration. -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_ . +With relative URIs the URI is resolved as relative to the URL of the URL used to access {{book.project.name}}. -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. +For example if the URL to your application is `https://acme.org/myapp` and the URL to {{book.project.name}} is `https://acme.org/auth`, then you can use +the redirect-uri `/myapp` instead of `https://acme.org/myapp`. ==== 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. +Admin URL for a particular application can be configured in the {{book.project.name}} Administration Console. +It's used by the {{book.project.name}} server to send backend requests to the application for various tasks, like logout users or push revocation policies. -For example logout of user from Keycloak works like this: +For example the way backchannel logout works is: -. 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. +. User sends logout request from one application +. The application sends logout request to {{book.project.name}} +. The {{book.project.name}} server invalidates the user session +. The {{book.project.name}} server then sends a backchannel request to application with a admin url that are associated with the session +. When an application receives the logout request it invalidates the corresponding HTTP session -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. +Some examples of possible values of admin URL are: 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. + {{book.project.name}} tracks hosts associated with the HTTP Session and will send session invalidation message to the associated node. [[_registration_app_nodes]] -==== Registration of application nodes to Keycloak +==== Registration of application nodes -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. +The previous describes how {{book.project.name}} can send logout request to node associated with a specific HTTP session. +However, in some cases admin may want to propagate admin tasks to all registered cluster nodes, not just one of them. +For example to push a new not before policy to the application or to logout all users from the application. -In this case Keycloak should be aware of all application cluster nodes, so it could send event to all of them. +In this case {{book.project.name}} needs to be aware of all application cluster nodes, so it can send the 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 . +. When a new application node joins the cluster, it sends a registration request to the {{book.project.name}} server +. The request may be re-sent to {{book.project.name}} in configured periodic intervals +. If the {{book.project.name}} server doesn't receive a re-registration request within a specified timeout then it automatically unregisters the specific node +. The node is also unregistered in {{book.project.name}} when it sends an 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, which results in the need for automatic unregistration -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: +Sending startup registrations and periodic re-registration is disabled by default as it's only required for some clustered applications. + +To enable the feature edit the `WEB-INF/keycloak.json` file for your application and add: [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). +This means the adapter will send the registration request on startup and re-register every 10 minutes. + +In the {{book.project.name}} Administration Console you can specify the maximum node re-registration timeout (should be larger than _register-node-period_ from +the adapter configuration). You can also manually add and remove cluster nodes in through the Adminstration Console, which is useful if you don't want to rely +on the automatic registration feature or if you want to remove stale application nodes in the event your not using the automatic unregistration feature. [[_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. +By default the application adapter will only refresh the access token when it's expired. However, you can also configure the adapter to refresh the token on every +request. This may have a performance impact as your application will send more requests to the {{book.project.name}} server. -In `WEB-INF/keycloak.json` you can configure: +To enable the feature edit the `WEB-INF/keycloak.json` file for your application and add: [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. +NOTE: This may have a significant impact on performance. Only enable this feature if you can't rely on backchannel messages to propagate logout and not before + policies. Another thing to consider is that by default access tokens has a short expiration so even if logout is not propagated the token will expire within + minutes of the logout. \ No newline at end of file diff --git a/topics/oidc/java/jaas.adoc b/topics/oidc/java/jaas.adoc index 8145355ce3..fec56b196f 100755 --- a/topics/oidc/java/jaas.adoc +++ b/topics/oidc/java/jaas.adoc @@ -1,27 +1,30 @@ - [[_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: - +It's generally not needed to use JAAS for most of the applications, especially if they are HTTP based, and you should most likely choose one of our other adapters. +However, some applications and systems may still rely on pure legacy JAAS solution. +{{book.project.title}} provides two login modules to help in these situations. +The provided login modules 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. + This login module allows to authenticate with username/password from {{book.project.title}}. + It's using <> flow to validate if the provided + username/password is valid. It's useful for non-web based systems, which need to rely on JAAS and want to use Keycloak, but can't use the standard browser + based flows due to their non-web nature. Example of such application could be messaging or SSH. 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. + This login module allows to authenticate with {{book.project.title}} access token passed to it through CallbackHandler as password. + It may be useful for example in case, when you have {{book.project.title}} access token from standard based authentication flow and your web application then + needs to talk to external non-web based system, which rely on JAAS. For example a 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` ). +Both modules use the following configuration properties: -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. \ No newline at end of file +keycloak-config-file:: + The location of the `keycloak.json` configuration file. The configuration file can either be located on the filesystem or on the classpath. If it's located + on the classpath you need to prefix the location with `classpath:` (for example `classpath:/path/keycloak.json`). + This is _REQUIRED._ + +`role-principal-class`:: + Configure alternative class for Role principals attached to JAAS Subject. + Default value is `org.keycloak.adapters.jaas.RolePrincipal`. Note: The class is required to have a constructor with a single `String` argument. \ No newline at end of file diff --git a/topics/oidc/java/logout.adoc b/topics/oidc/java/logout.adoc index 3a9c42dac4..b56c9b4c90 100755 --- a/topics/oidc/java/logout.adoc +++ b/topics/oidc/java/logout.adoc @@ -1,6 +1,5 @@ - === 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. \ No newline at end of file +For Java EE servlet containers, you can call HttpServletRequest.logout(). For any other browser application, you can redirect the browser to +`http://auth-server/auth/realms/{realm-name}/tokens/logout?redirect_uri=encodedRedirectUri`. This will log you out if you have a SSO session with your browser. \ No newline at end of file diff --git a/topics/oidc/java/multi-tenancy.adoc b/topics/oidc/java/multi-tenancy.adoc index 5f339f16be..5992d2578f 100755 --- a/topics/oidc/java/multi-tenancy.adoc +++ b/topics/oidc/java/multi-tenancy.adoc @@ -1,28 +1,54 @@ === 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: +Multi Tenancy, in our context, means that a single target application (WAR) can be secured with multiple {{book.project.name}} realms. The realms can be located +one the same {{book.project.name}} instance or on different instances. -* 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. +In practice, this means that the application needs to have multiple `keycloak.json` adapter configuration files. -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: +You could have multiple instances of your WAR with different adapter configuration files deployed to different context-paths. However, this may be inconvenient +and you may also want to select the realm based on something else than context-path. -* web.xml -+`keycloak.config.resolver` -+`org.keycloak.adapters.KeycloakConfigResolver` -* org.keycloak.adapters.KeycloakConfigResolver -+`resolve(org.keycloak.adapters.spi.HttpFacade.Request)` -+`org.keycloak.adapters.KeycloakDeployment` +{{book.project.name}} makes it possible to have a custom config resolver so you can choose what adapter config is used for each request. -An implementation of this feature can be found in the examples. \ No newline at end of file +To achieve this first you need to create an implementation of `org.keycloak.adapters.KeycloakConfigResolver`. For example: + +[source,java] +---- +package example; + +import org.keycloak.adapters.KeycloakConfigResolver; +import org.keycloak.adapters.KeycloakDeployment; +import org.keycloak.adapters.KeycloakDeploymentBuilder; + +public class PathBasedKeycloakConfigResolver implements KeycloakConfigResolver { + + @Override + public KeycloakDeployment resolve(OIDCHttpFacade.Request request) { + if (path.startsWith("alternative")) { + KeycloakDeployment deployment = cache.get(realm); + if (null == deployment) { + InputStream is = getClass().getResourceAsStream("/tenant1-keycloak.json"); + return KeycloakDeploymentBuilder.build(is); + } + } else { + InputStream is = getClass().getResourceAsStream("/default-keycloak.json"); + return KeycloakDeploymentBuilder.build(is); + } + } + +} +---- + +You also need to configure which `KeycloakConfigResolver` implementation to use with the `keycloak.config.resolver` context-param in your `web.xml`: + +[source,xml] +---- + + ... + + keycloak.config.resolver + example.PathBasedKeycloakConfigResolver + + +---- \ No newline at end of file diff --git a/topics/oidc/java/servlet-filter-adapter.adoc b/topics/oidc/java/servlet-filter-adapter.adoc index 035ecefd41..3f8c809b68 100755 --- a/topics/oidc/java/servlet-filter-adapter.adoc +++ b/topics/oidc/java/servlet-filter-adapter.adoc @@ -1,25 +1,22 @@ [[_servlet_filter_adapter]] === 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. +If you are deploying your Java Servlet application on a platform where there is no {{book.project.title}} adapter you opt to use the the servlet filter adapter. +This adapter works a bit differently than the other adapters. You do not define security constraints in web.xml. +Instead you define a filter mapping using the {{book.project.title}} 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. +Instead of invalidating the HTTP session it marks the session id as logged out. +There's no way standard way to invalidate an HTTP session based on a session id. -[source] +[source,xml] ---- - - - customer-portal + application Keycloak Filter @@ -33,23 +30,23 @@ There's just no way of arbitrarily invalidating an http session based on a sessi ---- -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. +In the snippet above there are two url-patterns. + `/protected/*` are the files we want protected, while the `/keycloak/*` url-pattern handles callbacks from the {{book.project.title}} server. + +Note that you should configure your client in the {{book.project.title}} 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. +The {{book.project.title}} filter has the same configuration parameters 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 +To use this filter, include this maven artifact in your WAR poms: -[source] +[source,xml] ---- - - - org.keycloak - keycloak-servlet-filter-adapter - &project.version; - + + org.keycloak + keycloak-servlet-filter-adapter + &project.version; + ---- \ No newline at end of file diff --git a/topics/oidc/oidc-generic.adoc b/topics/oidc/oidc-generic.adoc index a697467c86..d625f9a539 100644 --- a/topics/oidc/oidc-generic.adoc +++ b/topics/oidc/oidc-generic.adoc @@ -14,6 +14,7 @@ TODO ==== Implicit +[[_resource_owner_password_credentials_flow]] ==== Resource Owner Password Credentials ==== Client Credentials