KEYCLOAK-3093 Remove documentation from main repository
|
@ -33,14 +33,6 @@
|
||||||
<directory>../../services/target/apidocs-rest/output</directory>
|
<directory>../../services/target/apidocs-rest/output</directory>
|
||||||
<outputDirectory>rest-api</outputDirectory>
|
<outputDirectory>rest-api</outputDirectory>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
<fileSet>
|
|
||||||
<directory>../../docbook/auth-server-docs/target/docbook/publish/en-US</directory>
|
|
||||||
<outputDirectory>userguide/keycloak-server</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
<fileSet>
|
|
||||||
<directory>../../docbook/saml-adapter-docs/target/docbook/publish/en-US</directory>
|
|
||||||
<outputDirectory>userguide/saml-client-adapter</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
</fileSets>
|
</fileSets>
|
||||||
|
|
||||||
<files>
|
<files>
|
|
@ -24,7 +24,7 @@
|
||||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
<version>2.0.0.CR1-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>keycloak-docs-dist</artifactId>
|
<artifactId>keycloak-api-docs-dist</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
<name>Keycloak Docs Distribution</name>
|
<name>Keycloak Docs Distribution</name>
|
||||||
<description/>
|
<description/>
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<finalName>keycloak-docs-${project.version}</finalName>
|
<finalName>keycloak-api-docs-${project.version}</finalName>
|
||||||
<plugins>
|
<plugins>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
|
@ -1,3 +1,4 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
<!--
|
<!--
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
~ and other contributors as indicated by the @author tags.
|
~ and other contributors as indicated by the @author tags.
|
||||||
|
@ -15,10 +16,23 @@
|
||||||
~ limitations under the License.
|
~ limitations under the License.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<chapter id="license">
|
<html>
|
||||||
<title>License</title>
|
<head>
|
||||||
<para>Keycloak codebase is distributed under the ASL 2.0 license. It does not distribute any thirdparty libraries that are
|
<style>
|
||||||
GPL. It does ship thirdparty libraries licensed under
|
td { padding: 5px; }
|
||||||
Apache ASL 2.0 and LGPL.
|
</style>
|
||||||
</para>
|
</head>
|
||||||
</chapter>
|
|
||||||
|
<body>
|
||||||
|
<h1>Keyloak API Documentation</h1>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td>Admin REST API</td>
|
||||||
|
<td colspan="3"><a href="rest-api/index.html">HTML</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>Javadocs</td>
|
||||||
|
<td colspan="3"><a href="javadocs/index.html">HTML</a></td>
|
||||||
|
</tr>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -60,10 +60,6 @@
|
||||||
<exclude>standalone/configuration/standalone-keycloak.xml</exclude>
|
<exclude>standalone/configuration/standalone-keycloak.xml</exclude>
|
||||||
</excludes>
|
</excludes>
|
||||||
</fileSet>
|
</fileSet>
|
||||||
<fileSet>
|
|
||||||
<directory>${project.build.directory}/unpacked/keycloak-docs-${project.version}</directory>
|
|
||||||
<outputDirectory>docs</outputDirectory>
|
|
||||||
</fileSet>
|
|
||||||
<fileSet>
|
<fileSet>
|
||||||
<directory>${project.build.directory}/unpacked/keycloak-examples-${project.version}</directory>
|
<directory>${project.build.directory}/unpacked/keycloak-examples-${project.version}</directory>
|
||||||
<outputDirectory>examples</outputDirectory>
|
<outputDirectory>examples</outputDirectory>
|
||||||
|
|
|
@ -50,11 +50,6 @@
|
||||||
<artifactId>keycloak-examples-dist</artifactId>
|
<artifactId>keycloak-examples-dist</artifactId>
|
||||||
<type>zip</type>
|
<type>zip</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-docs-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
@ -139,23 +134,6 @@
|
||||||
</artifactItems>
|
</artifactItems>
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
<execution>
|
|
||||||
<id>unpack-docs</id>
|
|
||||||
<phase>prepare-package</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>unpack</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<artifactItems>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-docs-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
<outputDirectory>${project.build.directory}/unpacked</outputDirectory>
|
|
||||||
</artifactItem>
|
|
||||||
</artifactItems>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
<execution>
|
||||||
<id>unpack-examples</id>
|
<id>unpack-examples</id>
|
||||||
<phase>prepare-package</phase>
|
<phase>prepare-package</phase>
|
||||||
|
|
|
@ -1,139 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<project name="example-dist" basedir="." default="all">
|
|
||||||
|
|
||||||
<target name="all">
|
|
||||||
<delete dir="target/examples"/>
|
|
||||||
<copy todir="target/examples/cors" overwrite="true">
|
|
||||||
<fileset dir="../../examples/cors">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
<exclude name="**/*.unconfigured"/>
|
|
||||||
<exclude name="**/subsystem-config.xml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/cordova" overwrite="true">
|
|
||||||
<fileset dir="../../examples/cordova">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
<exclude name="**/*.unconfigured"/>
|
|
||||||
<exclude name="**/subsystem-config.xml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/providers" overwrite="true">
|
|
||||||
<fileset dir="../../examples/providers">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
<exclude name="**/*.unconfigured"/>
|
|
||||||
<exclude name="**/subsystem-config.xml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/saml" overwrite="true">
|
|
||||||
<fileset dir="../../examples/saml">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
<exclude name="**/*.unconfigured"/>
|
|
||||||
<exclude name="**/subsystem-config.xml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/broker/saml-broker-authentication" overwrite="true">
|
|
||||||
<fileset dir="../../examples/broker/saml-broker-authentication">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
<exclude name="**/*.unconfigured"/>
|
|
||||||
<exclude name="**/subsystem-config.xml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/js-console" overwrite="true">
|
|
||||||
<fileset dir="../../examples/js-console">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
<exclude name="**/*.unconfigured"/>
|
|
||||||
<exclude name="**/subsystem-config.xml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/multi-tenant" overwrite="true">
|
|
||||||
<fileset dir="../../examples/multi-tenant">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
<exclude name="**/*.unconfigured"/>
|
|
||||||
<exclude name="**/subsystem-config.xml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/basic-auth" overwrite="true">
|
|
||||||
<fileset dir="../../examples/basic-auth">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
<exclude name="**/*.unconfigured"/>
|
|
||||||
<exclude name="**/subsystem-config.xml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/admin-client" overwrite="true">
|
|
||||||
<fileset dir="../../examples/admin-client">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
<exclude name="**/*.unconfigured"/>
|
|
||||||
<exclude name="**/subsystem-config.xml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/themes" overwrite="true">
|
|
||||||
<fileset dir="../../examples/themes">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
<exclude name="**/*.unconfigured"/>
|
|
||||||
<exclude name="**/subsystem-config.xml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/preconfigured-demo" overwrite="true">
|
|
||||||
<fileset dir="../../examples/demo-template">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
<exclude name="**/*.unconfigured"/>
|
|
||||||
<exclude name="**/subsystem-config.xml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/unconfigured-demo" overwrite="true">
|
|
||||||
<fileset dir="../../examples/demo-template">
|
|
||||||
<exclude name="**/*.wildfly"/>
|
|
||||||
<exclude name="**/*.as7"/>
|
|
||||||
<exclude name="**/WEB-INF/jboss-web.xml"/>
|
|
||||||
<exclude name="**/keycloak.json"/>
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
<exclude name="**/README.md"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/fuse" overwrite="true">
|
|
||||||
<fileset dir="../../examples/fuse">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy todir="target/examples/kerberos" overwrite="true">
|
|
||||||
<fileset dir="../../examples/kerberos">
|
|
||||||
<exclude name="**/target/**"/>
|
|
||||||
<exclude name="**/*.iml"/>
|
|
||||||
</fileset>
|
|
||||||
</copy>
|
|
||||||
<copy file="../../examples/README.md" tofile="target/examples/README.md"/>
|
|
||||||
<move file="target/examples/unconfigured-demo/README.md.unconfigured" tofile="target/examples/unconfigured-demo/README.md"/>
|
|
||||||
<move file="target/examples/unconfigured-demo/customer-app/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/customer-app/src/main/webapp/WEB-INF/web.xml"/>
|
|
||||||
<move file="target/examples/unconfigured-demo/product-app/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/product-app/src/main/webapp/WEB-INF/web.xml"/>
|
|
||||||
<move file="target/examples/unconfigured-demo/database-service/src/main/webapp/WEB-INF/web.xml.unconfigured" tofile="target/examples/unconfigured-demo/database-service/src/main/webapp/WEB-INF/web.xml"/>
|
|
||||||
</target>
|
|
||||||
</project>
|
|
|
@ -1,50 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<style>
|
|
||||||
td { padding: 5px; }
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<h1>Keyloak Documentation</h1>
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td>Server and Keycloak Adapter Userguide</td>
|
|
||||||
<td><a href="userguide/keycloak-server/html/index.html">HTML</a></td>
|
|
||||||
<td><a href="userguide/keycloak-server/html_single/index.html">HTML Single Page</a></td>
|
|
||||||
<td><a href="userguide/keycloak-server/pdf/keycloak-reference-guide-en-US.pdf">PDF</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>SAML Client Adapter Userguide</td>
|
|
||||||
<td><a href="userguide/saml-client-adapter/html/index.html">HTML</a></td>
|
|
||||||
<td><a href="userguide/saml-client-adapter/html_single/index.html">HTML Single Page</a></td>
|
|
||||||
<td><a href="userguide/saml-client-adapter/pdf/keycloak-saml-adapter-reference-guide-en-US.pdf">PDF</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Admin REST API</td>
|
|
||||||
<td colspan="3"><a href="rest-api/index.html">HTML</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Javadocs</td>
|
|
||||||
<td colspan="3"><a href="javadocs/index.html">HTML</a></td>
|
|
||||||
</tr>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -102,9 +102,9 @@
|
||||||
|
|
||||||
<artifactItem>
|
<artifactItem>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-docs-dist</artifactId>
|
<artifactId>keycloak-api-docs-dist</artifactId>
|
||||||
<type>zip</type>
|
<type>zip</type>
|
||||||
<destFileName>keycloak-docs-${project.version}.zip</destFileName>
|
<destFileName>keycloak-api-docs-${project.version}.zip</destFileName>
|
||||||
</artifactItem>
|
</artifactItem>
|
||||||
<artifactItem>
|
<artifactItem>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
<module>adapters</module>
|
<module>adapters</module>
|
||||||
<module>saml-adapters</module>
|
<module>saml-adapters</module>
|
||||||
<module>demo-dist</module>
|
<module>demo-dist</module>
|
||||||
<module>docs-dist</module>
|
<module>api-docs-dist</module>
|
||||||
<module>examples-dist</module>
|
<module>examples-dist</module>
|
||||||
<module>proxy-dist</module>
|
<module>proxy-dist</module>
|
||||||
<module>server-dist</module>
|
<module>server-dist</module>
|
||||||
|
|
|
@ -1,159 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<parent>
|
|
||||||
<artifactId>keycloak-docbook-parent</artifactId>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>keycloak-reference-guide-${translation}</artifactId>
|
|
||||||
<packaging>jdocbook</packaging>
|
|
||||||
<name>Keycloak Reference Guide (${translation})</name>
|
|
||||||
<description/>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>jboss</id>
|
|
||||||
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
|
|
||||||
</repository>
|
|
||||||
<!--
|
|
||||||
<repository>
|
|
||||||
<id>repo1.maven.org</id>
|
|
||||||
<url>http://repo1.maven.org/maven2</url>
|
|
||||||
</repository> -->
|
|
||||||
</repositories>
|
|
||||||
<pluginRepositories>
|
|
||||||
<pluginRepository>
|
|
||||||
<id>jboss</id>
|
|
||||||
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
|
|
||||||
</pluginRepository>
|
|
||||||
<!--
|
|
||||||
<pluginRepository>
|
|
||||||
<id>maven2-repository.dev.java.net</id>
|
|
||||||
<url>http://download.java.net/maven/2</url>
|
|
||||||
</pluginRepository>
|
|
||||||
<pluginRepository>
|
|
||||||
<id>plugin repo1.maven.org</id>
|
|
||||||
<url>http://repo1.maven.org/maven2</url>
|
|
||||||
</pluginRepository>
|
|
||||||
-->
|
|
||||||
</pluginRepositories>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-deploy-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<skip>true</skip>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.jboss.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jdocbook-plugin</artifactId>
|
|
||||||
<version>2.3.8</version>
|
|
||||||
<extensions>true</extensions>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.pressgang</groupId>
|
|
||||||
<artifactId>pressgang-xslt-ns</artifactId>
|
|
||||||
<version>2.0.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.pressgang</groupId>
|
|
||||||
<artifactId>pressgang-jdocbook-style</artifactId>
|
|
||||||
<type>jdocbook-style</type>
|
|
||||||
<version>2.0.2</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<configuration>
|
|
||||||
<sourceDocumentName>master.xml</sourceDocumentName>
|
|
||||||
<masterTranslation>en-US</masterTranslation>
|
|
||||||
<sourceDirectory>${project.basedir}/reference/en</sourceDirectory>
|
|
||||||
<imageResource>
|
|
||||||
<directory>${project.basedir}/reference/en</directory>
|
|
||||||
<includes>
|
|
||||||
<include>images/*</include>
|
|
||||||
</includes>
|
|
||||||
</imageResource>
|
|
||||||
<formats>
|
|
||||||
<format>
|
|
||||||
<formatName>html_single</formatName>
|
|
||||||
<stylesheetResource>classpath:/xslt/org/jboss/xhtml-single.xsl</stylesheetResource>
|
|
||||||
<finalName>index.html</finalName>
|
|
||||||
<!-- <profilingTypeName>two_pass</profilingTypeName> -->
|
|
||||||
</format>
|
|
||||||
<format>
|
|
||||||
<formatName>html</formatName>
|
|
||||||
<stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
|
|
||||||
<finalName>index.html</finalName>
|
|
||||||
<!-- <profilingTypeName>two_pass</profilingTypeName> -->
|
|
||||||
</format>
|
|
||||||
<format>
|
|
||||||
<formatName>pdf</formatName>
|
|
||||||
<stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
|
|
||||||
<finalName>${project.artifactId}.pdf</finalName>
|
|
||||||
</format>
|
|
||||||
<!--<format>-->
|
|
||||||
<!--<formatName>eclipse</formatName>-->
|
|
||||||
<!--<stylesheetResource>classpath:/xslt/org/jboss/eclipse.xsl</stylesheetResource>-->
|
|
||||||
<!--<finalName>${project.artifactId}.html</finalName>-->
|
|
||||||
<!--</format>-->
|
|
||||||
</formats>
|
|
||||||
<injections>
|
|
||||||
<injection>
|
|
||||||
<name>project.version</name>
|
|
||||||
<value>${project.version}</value>
|
|
||||||
</injection>
|
|
||||||
<injection>
|
|
||||||
<name>picketlink.version</name>
|
|
||||||
<value>${picketlink.version}</value>
|
|
||||||
</injection>
|
|
||||||
<injection>
|
|
||||||
<name>wildfly.version</name>
|
|
||||||
<value>${wildfly.version}</value>
|
|
||||||
</injection>
|
|
||||||
<injection>
|
|
||||||
<name>eap.version</name>
|
|
||||||
<value>${eap.version}</value>
|
|
||||||
</injection>
|
|
||||||
</injections>
|
|
||||||
<options>
|
|
||||||
<xmlTransformerType>saxon</xmlTransformerType>
|
|
||||||
<xincludeSupported>true</xincludeSupported>
|
|
||||||
<useRelativeImageUris>true</useRelativeImageUris>
|
|
||||||
<!-- TODO Probably obsolete after the upgrade to maven-jdocbook-plugin 2.3.0 -->
|
|
||||||
<docbookVersion>1.72.0</docbookVersion>
|
|
||||||
<!-- <localeSeparator>-</localeSeparator> -->
|
|
||||||
</options>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<translation>en-US</translation>
|
|
||||||
</properties>
|
|
||||||
</project>
|
|
|
@ -1,182 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
|
||||||
"http://www.docbook.org/xml/4.4/docbookx.dtd"
|
|
||||||
[
|
|
||||||
<!ENTITY License SYSTEM "modules/License.xml">
|
|
||||||
<!ENTITY Overview SYSTEM "modules/Overview.xml">
|
|
||||||
<!ENTITY Installation SYSTEM "modules/server-installation.xml">
|
|
||||||
<!ENTITY Providers SYSTEM "modules/providers.xml">
|
|
||||||
<!ENTITY OpenShift SYSTEM "modules/openshift.xml">
|
|
||||||
<!ENTITY AdminPermissions SYSTEM "modules/admin-permissions.xml">
|
|
||||||
<!ENTITY PerRealmAdminPermissions SYSTEM "modules/per-realm-admin-permissions.xml">
|
|
||||||
<!ENTITY AccessTypes SYSTEM "modules/access-types.xml">
|
|
||||||
<!ENTITY AdapterConfig SYSTEM "modules/adapter-config.xml">
|
|
||||||
<!ENTITY JBossAdapter SYSTEM "modules/jboss-adapter.xml">
|
|
||||||
<!ENTITY JavascriptAdapter SYSTEM "modules/javascript-adapter.xml">
|
|
||||||
<!ENTITY TomcatAdapter SYSTEM "modules/tomcat-adapter.xml">
|
|
||||||
<!ENTITY Jetty9Adapter SYSTEM "modules/jetty9-adapter.xml">
|
|
||||||
<!ENTITY Jetty8Adapter SYSTEM "modules/jetty8-adapter.xml">
|
|
||||||
<!ENTITY FuseAdapter SYSTEM "modules/fuse-adapter.xml">
|
|
||||||
<!ENTITY SpringBootAdapter SYSTEM "modules/spring-boot-adapter.xml">
|
|
||||||
<!ENTITY SpringSecurityAdapter SYSTEM "modules/spring-security-adapter.xml">
|
|
||||||
<!ENTITY InstalledApplications SYSTEM "modules/installed-applications.xml">
|
|
||||||
<!ENTITY Logout SYSTEM "modules/logout.xml">
|
|
||||||
<!ENTITY ErrorHandling SYSTEM "modules/adapter_error_handling.xml">
|
|
||||||
<!ENTITY SAML SYSTEM "modules/saml.xml">
|
|
||||||
<!ENTITY JAAS SYSTEM "modules/jaas.xml">
|
|
||||||
<!ENTITY IdentityBroker SYSTEM "modules/identity-broker.xml">
|
|
||||||
<!ENTITY Themes SYSTEM "modules/themes.xml">
|
|
||||||
<!ENTITY Clients SYSTEM "modules/clients.xml">
|
|
||||||
<!ENTITY Migration SYSTEM "modules/MigrationFromOlderVersions.xml">
|
|
||||||
<!ENTITY Email SYSTEM "modules/email.xml">
|
|
||||||
<!ENTITY Roles SYSTEM "modules/roles.xml">
|
|
||||||
<!ENTITY Groups SYSTEM "modules/groups.xml">
|
|
||||||
<!ENTITY DirectAccess SYSTEM "modules/direct-access.xml">
|
|
||||||
<!ENTITY ServiceAccounts SYSTEM "modules/service-accounts.xml">
|
|
||||||
<!ENTITY CORS SYSTEM "modules/cors.xml">
|
|
||||||
<!ENTITY Timeouts SYSTEM "modules/timeouts.xml">
|
|
||||||
<!ENTITY Events SYSTEM "modules/events.xml">
|
|
||||||
<!ENTITY AdminApi SYSTEM "modules/admin-rest-api.xml">
|
|
||||||
<!ENTITY UserFederation SYSTEM "modules/user-federation.xml">
|
|
||||||
<!ENTITY Kerberos SYSTEM "modules/kerberos.xml">
|
|
||||||
<!ENTITY ExportImport SYSTEM "modules/export-import.xml">
|
|
||||||
<!ENTITY ServerCache SYSTEM "modules/cache.xml">
|
|
||||||
<!ENTITY SecurityVulnerabilities SYSTEM "modules/security-vulnerabilities.xml">
|
|
||||||
<!ENTITY Clustering SYSTEM "modules/clustering.xml">
|
|
||||||
<!ENTITY ApplicationClustering SYSTEM "modules/application-clustering.xml">
|
|
||||||
<!ENTITY MultiTenancy SYSTEM "modules/multi-tenancy.xml">
|
|
||||||
<!ENTITY Proxy SYSTEM "modules/proxy.xml">
|
|
||||||
<!ENTITY CustomAttributes SYSTEM "modules/custom-attributes.xml">
|
|
||||||
<!ENTITY ProtocolMappers SYSTEM "modules/protocol-mappers.xml">
|
|
||||||
<!ENTITY Recaptcha SYSTEM "modules/recaptcha.xml">
|
|
||||||
<!ENTITY AuthSPI SYSTEM "modules/auth-spi.xml">
|
|
||||||
<!ENTITY FilterAdapter SYSTEM "modules/servlet-filter-adapter.xml">
|
|
||||||
<!ENTITY ClientRegistration SYSTEM "modules/client-registration.xml">
|
|
||||||
]>
|
|
||||||
|
|
||||||
<book>
|
|
||||||
|
|
||||||
<bookinfo>
|
|
||||||
<title>Keycloak Reference Guide</title>
|
|
||||||
<subtitle>SSO for Web Apps and REST Services</subtitle>
|
|
||||||
<releaseinfo>&project.version;</releaseinfo>
|
|
||||||
</bookinfo>
|
|
||||||
|
|
||||||
<toc/>
|
|
||||||
|
|
||||||
<preface id="preface" revision="1">
|
|
||||||
<title>Preface</title>
|
|
||||||
<para>
|
|
||||||
In some of the example listings, what is meant to be displayed on one line does not fit
|
|
||||||
inside the available page width. These lines have been broken up. A '\' at the end of a
|
|
||||||
line means that a break has been introduced to fit in the page, with the following lines
|
|
||||||
indented. So:
|
|
||||||
<programlisting>
|
|
||||||
Let's pretend to have an extremely \
|
|
||||||
long line that \
|
|
||||||
does not fit
|
|
||||||
This one is short
|
|
||||||
</programlisting>
|
|
||||||
Is really:
|
|
||||||
<programlisting>
|
|
||||||
Let's pretend to have an extremely long line that does not fit
|
|
||||||
This one is short
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</preface>
|
|
||||||
|
|
||||||
&License;
|
|
||||||
&Overview;
|
|
||||||
&Installation;
|
|
||||||
&Providers;
|
|
||||||
&OpenShift;
|
|
||||||
&AdminPermissions;
|
|
||||||
&PerRealmAdminPermissions;
|
|
||||||
<chapter>
|
|
||||||
<title>Adapters</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
&AdapterConfig;
|
|
||||||
&JBossAdapter;
|
|
||||||
&TomcatAdapter;
|
|
||||||
&Jetty9Adapter;
|
|
||||||
&Jetty8Adapter;
|
|
||||||
&FilterAdapter;
|
|
||||||
&FuseAdapter;
|
|
||||||
&JavascriptAdapter;
|
|
||||||
&SpringBootAdapter;
|
|
||||||
&SpringSecurityAdapter;
|
|
||||||
&InstalledApplications;
|
|
||||||
&Logout;
|
|
||||||
&ErrorHandling;
|
|
||||||
&MultiTenancy;
|
|
||||||
&JAAS;
|
|
||||||
</chapter>
|
|
||||||
&ClientRegistration;
|
|
||||||
|
|
||||||
&IdentityBroker;
|
|
||||||
&Themes;
|
|
||||||
&Clients;
|
|
||||||
&Recaptcha;
|
|
||||||
|
|
||||||
<chapter>
|
|
||||||
<title>Email</title>
|
|
||||||
<para>
|
|
||||||
Keycloak sends emails to users to verify their email address. Emails are also used to allow users to
|
|
||||||
safely restore their username and passwords.
|
|
||||||
</para>
|
|
||||||
&Email;
|
|
||||||
</chapter>
|
|
||||||
&AccessTypes;
|
|
||||||
&Roles;
|
|
||||||
&Groups;
|
|
||||||
&DirectAccess;
|
|
||||||
&ServiceAccounts;
|
|
||||||
&FineGrainedAuthorization;
|
|
||||||
&CORS;
|
|
||||||
&Timeouts;
|
|
||||||
&AdminApi;
|
|
||||||
&Events;
|
|
||||||
&UserFederation;
|
|
||||||
&Kerberos;
|
|
||||||
&ExportImport;
|
|
||||||
&AdminRecovery;
|
|
||||||
&ServerCache;
|
|
||||||
&SAML;
|
|
||||||
&SecurityVulnerabilities;
|
|
||||||
&Clustering;
|
|
||||||
&ApplicationClustering;
|
|
||||||
&Proxy;
|
|
||||||
&CustomAttributes;
|
|
||||||
&ProtocolMappers;
|
|
||||||
&AuthSPI;
|
|
||||||
&Migration;
|
|
||||||
|
|
||||||
</book>
|
|
||||||
|
|
||||||
|
|
|
@ -1,675 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="Migration_from_older_versions">
|
|
||||||
<title>Migration from older versions</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
To upgrade to a new version of Keycloak first download and install the new version of Keycloak. You then have to
|
|
||||||
migrate the database, keycloak-server.json, providers, themes and applications from the old version.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Migrate database</title>
|
|
||||||
<para>
|
|
||||||
Keycloak provides automatic migration of the database. It's highly recommended that you backup your
|
|
||||||
database prior to upgrading Keycloak.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To enable automatic upgrading of the database if you're using a relational database make sure
|
|
||||||
<literal>databaseSchema</literal> is set to <literal>update</literal> for <literal>connectionsJpa</literal>:
|
|
||||||
<programlisting>
|
|
||||||
"connectionsJpa": {
|
|
||||||
"default": {
|
|
||||||
...
|
|
||||||
"databaseSchema": "update"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For MongoDB do the same, but for <literal>connectionsMongo</literal>:
|
|
||||||
<programlisting>
|
|
||||||
"connectionsMongo": {
|
|
||||||
"default": {
|
|
||||||
...
|
|
||||||
"databaseSchema": "update"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
When you start the server with this setting your database will automatically be migrated if the database
|
|
||||||
schema has changed in the new version.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Migrate keycloak-server.json</title>
|
|
||||||
<para>
|
|
||||||
You should copy <literal>standalone/configuration/keycloak-server.json</literal> from the old version to
|
|
||||||
make sure any configuration changes you've done are added to the new installation. The version specific
|
|
||||||
section below will list any changes done to this file that you have to do when upgrading from one version
|
|
||||||
to another.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Migrate providers</title>
|
|
||||||
<para>
|
|
||||||
If you have implemented any SPI providers you need to copy them to the new server. The version
|
|
||||||
specific section below will mention if any of the SPI's have changed. If they have you may have to update
|
|
||||||
your code accordingly.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Migrate themes</title>
|
|
||||||
<para>
|
|
||||||
If you have created a custom theme you need to copy them to the new server. The version specific section below
|
|
||||||
will mention if changes have been made to themes. If there is you may have to update your themes accordingly.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Migrate application</title>
|
|
||||||
<para>
|
|
||||||
If you deploy applications directly to the Keycloak server you should copy them to the new server. For any
|
|
||||||
applications including those not deployed directly to the Keycloak server you should upgrade the adapter.
|
|
||||||
The version specific section below will mention if any changes are required to applications.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Version specific migration</title>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Migrating to 1.9.5</title>
|
|
||||||
<simplesect>
|
|
||||||
<title>Default password hashing interval increased to 20K</title>
|
|
||||||
<para>
|
|
||||||
The default password hashing interval for new realms has been increased to 20K (from 1 previously). This change will have an impact on
|
|
||||||
performance when users authenticate. For example with the old default (1) it takes less than 1 ms to hash a password, but with the new
|
|
||||||
default (20K) the same operation can take 50-100 ms.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Migrating to 1.9.3</title>
|
|
||||||
<simplesect>
|
|
||||||
<title>Add User script renamed</title>
|
|
||||||
<para>
|
|
||||||
The script to add admin users to Keycloak has been renamed to <literal>add-user-keycloak</literal>.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Migrating to 1.9.2</title>
|
|
||||||
<simplesect>
|
|
||||||
<title>Adapter option auth-server-url-for-backend-requests removed</title>
|
|
||||||
<para>
|
|
||||||
We've removed the option <literal>auth-server-url-for-backend-requests</literal> as there were issues in some scenarios when it was used.
|
|
||||||
In more details, it was possible to access the Keycloak server from 2 different contexts (internal and external), which was
|
|
||||||
causing issues in token validations etc.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If you still want to use the optimization of network, which this option provided (avoid the application to send backchannel requests
|
|
||||||
through loadbalancer but send them to local Keycloak server directly) you may need to handle it at hosts configuration (DNS) level.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Migrating to 1.9.0</title>
|
|
||||||
<simplesect>
|
|
||||||
<title>Themes and providers directory moved</title>
|
|
||||||
<para>
|
|
||||||
We've moved the themes and providers directories from <literal>standalone/configuration/themes</literal> and <literal>standalone/configuration/providers</literal>
|
|
||||||
to <literal>themes</literal> and <literal>providers</literal> respectively. If you have added custom themes and providers you need
|
|
||||||
to move them to the new location. You also need to update <literal>keycloak-server.json</literal> as it's changed due to this.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Adapter Subsystems only bring in dependencies if keycloak is on</title>
|
|
||||||
<para>
|
|
||||||
Previously, if you had installed our saml or oidc keycloak subsystem adapters into Wildfly or JBoss EAP, we would
|
|
||||||
automatically include Keycloak client jars into EVERY application irregardless if you were using Keycloak or not.
|
|
||||||
These libraries are now only added to your deployment if you have keycloak authentication turned on for that adapter
|
|
||||||
(via the subsystem, or auth-method in web.xml
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Client Registration service endpoints moved</title>
|
|
||||||
<para>
|
|
||||||
The Client Registration service endpoints have been moved from <literal>{realm}/clients</literal> to <literal>{realm}/clients-registrations</literal>.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Session state parameter in authentication response renamed</title>
|
|
||||||
<para>
|
|
||||||
In the OpenID Connect authentication response we used to return the session state as <literal>session-state</literal> this is not
|
|
||||||
correct according to the specification and has been renamed to <literal>session_state</literal>.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Deprecated OpenID Connect endpoints</title>
|
|
||||||
<para>
|
|
||||||
In 1.2 we deprecated a number of endpoints that where not consistent with the OpenID Connect
|
|
||||||
specifications, these have now been removed. This also applies to the validate token endpoints that
|
|
||||||
was replaced with the new introspect endpoint in 1.8.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Updates to theme templates</title>
|
|
||||||
<para>
|
|
||||||
Feedback in template.ftl has been moved and format has changed slightly.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Module and Source Code Re-org</title>
|
|
||||||
<para>
|
|
||||||
Most of our modules and source code have been consolidated into two maven modules: keycloak-server-spi and
|
|
||||||
keycloak-services. SPI interfaces are in server-spi, implementations are in keycloak-services.
|
|
||||||
All JPA dependent modules have been consolidated under keycloak-model-jpa. Same goes
|
|
||||||
with mongo and infinispan under modules keycloak-model-mongo and keycloak-model-infinispan.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>For adapters, session id changed after login</title>
|
|
||||||
<para>
|
|
||||||
To plug a security attack vector, for platforms that support it (Tomcat 8, Undertow/Wildfly, Jetty 9),
|
|
||||||
the keycloak oidc and saml adapters will change the session id after login. You can turn off this behavior
|
|
||||||
check adapter config switches.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>SAML SP Client Adapter Changes</title>
|
|
||||||
<para>
|
|
||||||
Keycloak SAML SP Client Adapter now requires a specific endpoint, <literal>/saml</literal> to be
|
|
||||||
registered with your IDP.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating to 1.8.0</title>
|
|
||||||
<simplesect>
|
|
||||||
<title>Admin account</title>
|
|
||||||
<para>
|
|
||||||
In previous releases we shipped with a default admin user with a default password, this has now been removed.
|
|
||||||
If you are doing a new installation of 1.8 you will have to create an admin user as a first step. This
|
|
||||||
can be done easily by following the steps in <link linkend="create-admin-user">Admin User</link>.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>OAuth2 Token Introspection</title>
|
|
||||||
<para>
|
|
||||||
In order to add more compliance with OAuth2 specification, we added a new endpoint for token introspection.
|
|
||||||
The new endpoint can reached at <literal>/realms/{realm}/protocols/openid-connect/token/introspect</literal> and it is solely
|
|
||||||
based on <literal>RFC-7662.</literal>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <literal>/realms/{realm}/protocols/openid-connect/validate</literal> endpoint is now deprecated and we strongly recommend
|
|
||||||
you to move to the new introspection endpoint as soon as possible. The reason for this change is that RFC-7662 provides a more
|
|
||||||
standard and secure introspection endpoint.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The new token introspection URL can now be obtained from OpenID Connect Provider's configuration at <literal>/realms/{realm}/.well-known/openid-configuration</literal>. There
|
|
||||||
you will find a claim with name <literal>token_introspection_endpoint</literal> within the response. Only <literal>confidential clients</literal> are allowed to
|
|
||||||
invoke the new endpoint, where these clients will be usually acting as a resource server and looking for token metadata in order to perform local authorization checks.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating to 1.7.0.CR1</title>
|
|
||||||
<simplesect>
|
|
||||||
<title>Direct access grants disabled by default for clients</title>
|
|
||||||
<para>
|
|
||||||
In order to add more compliance with OpenID Connect specification, we added flags into admin console to Client Settings page,
|
|
||||||
where you can enable/disable various kinds of OpenID Connect/OAuth2 flows (Standard flow, Implicit flow, Direct Access Grants, Service Accounts).
|
|
||||||
As part of this, we have <literal>Direct Access Grants</literal> (corresponds to OAuth2 <literal>Resource Owner Password Credentials Grant</literal>) disabled by default for new clients.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Clients migrated from previous version have <literal>Direct Access Grants</literal> enabled just if they had flag <literal>Direct Grants Only</literal> on. The
|
|
||||||
<literal>Direct Grants Only</literal> flag was removed as if you enable Direct Access Grants and disable both Standard+Implicit flow, you will achieve same effect.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
We also added builtin client <literal>admin-cli</literal> to each realm. This client has <literal>Direct Access Grants</literal> enabled.
|
|
||||||
So if you're using Admin REST API or Keycloak admin-client, you should update your configuration to use <literal>admin-cli</literal> instead
|
|
||||||
of <literal>security-admin-console</literal> as the latter one doesn't have direct access grants enabled anymore by default.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Option 'Update Profile On First Login' moved from Identity provider to Review Profile authenticator</title>
|
|
||||||
<para>
|
|
||||||
In this version, we added <literal>First Broker Login</literal>, which allows you to specify what exactly should be done
|
|
||||||
when new user is logged through Identity provider (or Social provider), but there is no existing Keycloak user
|
|
||||||
yet linked to the social account. As part of this work, we added option <literal>First Login Flow</literal> to identity providers where
|
|
||||||
you can specify the flow and then you can configure this flow under <literal>Authentication</literal> tab in admin console.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
We also removed the option <literal>Update Profile On First Login</literal> from the Identity provider settings and moved it
|
|
||||||
to the configuration of <literal>Review Profile</literal> authenticator. So once you specify which flow should be used for your
|
|
||||||
Identity provider (by default it's <literal>First Broker Login</literal> flow), you go to <literal>Authentication</literal> tab, select the flow
|
|
||||||
and then you configure the option under <literal>Review Profile</literal> authenticator.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Element 'form-error-page' in web.xml not supported anymore</title>
|
|
||||||
<para>
|
|
||||||
form-error-page in web.xml will no longer work for client adapter authentication errors. You must define an error-page for
|
|
||||||
the various HTTP error codes. See documentation for more details if you want to catch and handle adapter error conditions.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>IdentityProviderMapper changes</title>
|
|
||||||
<para>
|
|
||||||
There is no change in the interface itself or method signatures. However there is some change in behaviour. We added <literal>First Broker Login</literal> flow
|
|
||||||
in this release and the method <literal>IdentityProviderMapper.importNewUser</literal> is now called after <literal>First Broker Login</literal> flow is finished.
|
|
||||||
So if you want to have any attribute available in <literal>Review Profile</literal> page, you would need to use
|
|
||||||
the method <literal>preprocessFederatedIdentity</literal> instead of <literal>importNewUser</literal> . You can set any attribute by
|
|
||||||
invoke <literal>BrokeredIdentityContext.setUserAttribute</literal> and that will be available on <literal>Review profile</literal> page.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating to 1.6.0.Final</title>
|
|
||||||
<simplesect>
|
|
||||||
<title>Option that refresh tokens are not reusable anymore</title>
|
|
||||||
<para>
|
|
||||||
Old versions of Keycloak allowed reusing refresh tokens multiple times. Keycloak still permits this,
|
|
||||||
but also have an option <literal>Revoke refresh token</literal> to disallow it. Option is in in admin console under token settings.
|
|
||||||
When a refresh token is used to obtain a new access token a new refresh token is also
|
|
||||||
included. When option is enabled, then this new refresh token should be used next time the access token is refreshed.
|
|
||||||
It won't be possible to reuse old refresh token multiple times.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Some packages renamed</title>
|
|
||||||
<para>
|
|
||||||
We did a bit of restructure and renamed some packages. It is mainly about renaming internal packages of util classes.
|
|
||||||
The most important classes used in your application ( for example AccessToken or KeycloakSecurityContext ) as well
|
|
||||||
as the SPI are still unchanged. However there is slight chance that you will be affected and will need to update imports of your classes.
|
|
||||||
For example if you are using multitenancy and KeycloakConfigResolver, you will be affected as for example class
|
|
||||||
HttpFacade was moved to different package - it is <literal>org.keycloak.adapters.spi.HttpFacade</literal> now.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Persisting user sessions</title>
|
|
||||||
<para>
|
|
||||||
We added support for offline tokens in this release, which means that we are persisting "offline" user sessions into database now.
|
|
||||||
If you are not using offline tokens, nothing will be persisted for you, so you don't need to care about worse performance for more DB writes.
|
|
||||||
However in all cases, you will need to update <literal>standalone/configuration/keycloak-server.json</literal> and add <literal>userSessionPersister</literal>
|
|
||||||
like this:
|
|
||||||
<programlisting>
|
|
||||||
"userSessionPersister": {
|
|
||||||
"provider": "jpa"
|
|
||||||
},
|
|
||||||
</programlisting>
|
|
||||||
If you want sessions to be persisted in Mongo instead of classic RDBMS, use provider <literal>mongo</literal> instead.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating to 1.5.0.Final</title>
|
|
||||||
<simplesect>
|
|
||||||
<title>Realm and User cache providers</title>
|
|
||||||
<para>
|
|
||||||
Infinispan is now the default and only realm and user cache providers. In non-clustered mode a local Infinispan cache is used. We've also removed our
|
|
||||||
custom in-memory cache and the no cache providers. If you have realmCache or userCache set in keycloak-server.json to mem or none please
|
|
||||||
remove these. As Infinispan is the only provider there's no longer any need for the realmCache and userCache objects so these can
|
|
||||||
be removed.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Uses Session providers</title>
|
|
||||||
<para>
|
|
||||||
Infinispan is now the default and only user session provider. In non-clustered mode a local Infinispan cache is used. We've also removed the JPA
|
|
||||||
and Mongo user session providers. If you have userSession set in keycloak-server.json to mem, jpa or mongo please
|
|
||||||
remove it. As Infinispan is the only provider there's no longer any need for the userSession object so it can
|
|
||||||
be removed.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For anyone that wants to achieve increased durability of user sessions this can be achieved by configuring the user session cache with
|
|
||||||
more than one owner or use a replicated cache. It's also possible to configure Infinispan to persist caches, although that would have
|
|
||||||
impacts on performance.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Contact details removed from registration and account management</title>
|
|
||||||
<para>
|
|
||||||
In the default theme we have now removed the contact details from the registration page and account management. The admin console now lists
|
|
||||||
all the users attributes, not just contact specific attributes. The admin console also has the ability to add/remove attributes to a user.
|
|
||||||
If you want to add contact details, please refer to the address theme included in the examples.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating to 1.3.0.Final</title>
|
|
||||||
<simplesect>
|
|
||||||
<title>Direct Grant API always enabled</title>
|
|
||||||
<para>
|
|
||||||
In the past Direct Grant API (or Resource Owner Password Credentials) was disabled by default and
|
|
||||||
there was an option on a realm to enable it. The Direct Grant API is now always enabled and the
|
|
||||||
option to enable/disable for a realm is removed.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Database changed</title>
|
|
||||||
<para>
|
|
||||||
There are again few database changes. Remember to backup your database prior to upgrading.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>UserFederationProvider changed</title>
|
|
||||||
<para>
|
|
||||||
There are few minor changes in UserFederationProvider interface. You may need to sync your implementation when upgrade
|
|
||||||
to newer version and upgrade few methods, which has changed signature. Changes are really minor, but were needed to improve performance of federation.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>WildFly 9.0.0.Final</title>
|
|
||||||
<para>
|
|
||||||
Following on from the distribution changes that was done in the last release the standalone download
|
|
||||||
of Keycloak is now based on WildFly 9.0.0.Final. This als affects the overlay which can only be deployed
|
|
||||||
to WildFly 9.0.0.Final or JBoss EAP 6.4.0.GA. WildFly 8.2.0.Final is no longer supported for the server.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>WildFly, JBoss EAP and JBoss AS7 adapters</title>
|
|
||||||
<para>
|
|
||||||
There are now 3 separate adapter downloads for WildFly, JBoss EAP and JBoss AS7:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem><literal>eap6</literal> - for JBoss EAP 6.x</listitem>
|
|
||||||
<listitem><literal>wf9</literal> - for WildFly 9.x</listitem>
|
|
||||||
<listitem><literal>wf8</literal> - for WildFly 8.x</listitem>
|
|
||||||
<listitem><literal>as7</literal> - for JBoss AS 7.x</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
Make sure you grab the correct one.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You also need to update standalone.xml as the extension module and subsystem definition has changed.
|
|
||||||
See <link linkend="jboss-adapter-installation">Adapter Installation</link> for details.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating from 1.2.0.Beta1 to 1.2.0.RC1</title>
|
|
||||||
<simplesect>
|
|
||||||
<title>Distribution changes</title>
|
|
||||||
<para>
|
|
||||||
Keycloak is now available in 3 downloads: standalone, overlay and demo bundle. The standalone is intended
|
|
||||||
for production and non-JEE developers. Overlay is aimed at adding Keycloak to an existing WildFly 8.2 or EAP 6.4
|
|
||||||
installation and is mainly for development. Finally we have a demo (or dev) bundle that is aimed at
|
|
||||||
developers getting started with Keycloak. This bundle contains a WildFly server, with Keycloak server and
|
|
||||||
adapter included. It also contains all documentation and examples.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Database changed</title>
|
|
||||||
<para>
|
|
||||||
This release contains again a number of changes to the database. The biggest one is Application and OAuth client merge.
|
|
||||||
Remember to backup your database prior to upgrading.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Application and OAuth client merge</title>
|
|
||||||
<para>
|
|
||||||
Application and OAuth clients are now merged into <literal>Clients</literal>. The UI of admin console is updated and database as well.
|
|
||||||
Your data from database should be automatically updated. The previously set Applications will be converted into Clients with <literal>Consent required</literal>
|
|
||||||
switch off and OAuth Clients will be converted into Clients with this switch on.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating from 1.1.0.Final to 1.2.0.Beta1</title>
|
|
||||||
<simplesect>
|
|
||||||
<title>Database changed</title>
|
|
||||||
<para>
|
|
||||||
This release contains a number of changes to the database. Remember to backup your database prior to
|
|
||||||
upgrading.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title><literal>iss</literal> in access and id tokens</title>
|
|
||||||
<para>
|
|
||||||
The value of <literal>iss</literal> claim in access and id tokens have changed from <literal>realm name</literal>
|
|
||||||
to <literal>realm url</literal>. This is required by OpenID Connect specification. If you're using our adapters
|
|
||||||
there's no change required, other than if you've been using bearer-only without specifying <literal>auth-server-url</literal>
|
|
||||||
you have to add it now. If you're using another library (or RSATokenVerifier) you need to make the corresponding
|
|
||||||
changes when verifying <literal>iss</literal>.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>OpenID Connect endpoints</title>
|
|
||||||
<para>
|
|
||||||
To comply with OpenID Connect specification the authentication and token endpoints have been changed
|
|
||||||
to having a single authentication endpoint and a single token endpoint. As per-spec <literal>response_type</literal>
|
|
||||||
and <literal>grant_type</literal> parameters are used to select the required flow. The old endpoints (<literal>/realms/{realm}/protocols/openid-connect/login</literal>,
|
|
||||||
<literal>/realms/{realm}/protocols/openid-connect/grants/access</literal>, <literal>/realms/{realm}/protocols/openid-connect/refresh</literal>,
|
|
||||||
<literal>/realms/{realm}/protocols/openid-connect/access/codes)</literal> are now deprecated and will be removed
|
|
||||||
in a future version.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Theme changes</title>
|
|
||||||
<para>
|
|
||||||
The layout of themes have changed. The directory hierarchy used to be <literal>type/name</literal>
|
|
||||||
this is now changed to <literal>name/type</literal>. For example a login theme named <literal>sunrise</literal>
|
|
||||||
used to be deployed to <literal>standalone/configuration/themes/login/sunrise</literal>, which is now
|
|
||||||
moved to <literal>standalone/configuration/themes/sunrise/login</literal>. This change was done to
|
|
||||||
make it easier to have group the different types for the same theme into one folder.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If you deployed themes as a JAR in the past you had to create a custom theme loader which required
|
|
||||||
Java code. This has been simplified to only requiring a plain text file (<literal>META-INF/keycloak-themes.json</literal>)
|
|
||||||
to describe the themes included in a JAR. See the <link linkend='themes'>themes</link> section in the docs for more information.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Claims changes</title>
|
|
||||||
<para>
|
|
||||||
Previously there was <literal>Claims</literal> tab in admin console for application and OAuth clients. This
|
|
||||||
was used to configure which attributes should go into access token for particular application/client. This was removed
|
|
||||||
and replaced with <link linkend='mappers'>Protocol mappers</link>, which are more flexible.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You don't need to care about migration of database from previous version.
|
|
||||||
We did migration scripts for both RDBMS and Mongo, which should ensure that claims configured for particular application/client
|
|
||||||
will be converted into corresponding protocol mappers (Still it's safer to backup DB before migrating to newer version though).
|
|
||||||
Same applies for exported JSON representation from previous version.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>Social migration to identity brokering</title>
|
|
||||||
<para>
|
|
||||||
We refactored social providers SPI and replaced it with <link linkend="identity-broker">identity brokering SPI</link>,
|
|
||||||
which is more flexible. The <literal>Social</literal> tab in admin console is renamed to <literal>Identity Provider</literal> tab.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Again you don't need to care about migration of database from previous version similarly like for Claims/protocol mappers.
|
|
||||||
Both configuration of social providers and "social links" to your users will be converted to corresponding Identity providers.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Only required action from you would be to change allowed <literal>Redirect URI</literal> in the admin console of
|
|
||||||
particular 3rd party social providers. You can first go to the Keycloak admin console and copy Redirect URI from the page where
|
|
||||||
you configure the identity provider. Then you can simply paste this as allowed Redirect URI to the admin console
|
|
||||||
of 3rd party provider (IE. Facebook admin console).
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating from 1.1.0.Beta2 to 1.1.0.Final</title>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
Providers are no longer loaded from <literal>WEB-INF/lib</literal>, they are now loaded
|
|
||||||
from <literal>standalone/configuration/providers</literal>. See the
|
|
||||||
<link linkend='providers'>providers</link> section for more details.
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating from 1.1.0.Beta1 to 1.1.0.Beta2</title>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>Adapters are now a separate download. They are not included in appliance and war distribution. We have too many now and the distro
|
|
||||||
is getting bloated.</listitem>
|
|
||||||
<listitem>The tomcat adapter valve has moved to a different package. From <literal>org.keycloak.adapters.tomcat7.KeycloakAuthenticatorValve</literal> to <literal>org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve</literal>
|
|
||||||
From the 'tomcat7' package to just 'tomcat'.
|
|
||||||
</listitem>
|
|
||||||
<listitem>JavaScript adapter now has idToken and idTokenParsed properties. If you use idToken to retrieve first name, email, etc. you need to change this to idTokenParsed.</listitem>
|
|
||||||
<listitem>The as7-eap-subsystem and keycloak-wildfly-subsystem have been merged into one keycloak-subsystem. If you have an existing standalone.xml
|
|
||||||
or domain.xml, you will need edit near the top of the file and change the extension module name to org.keycloak.keycloak-subsystem.
|
|
||||||
For AS7 only, the extension module name is org.keycloak.keycloak-as7-subsystem.</listitem>
|
|
||||||
<listitem>Server installation is no longer supported on AS7. You can still use AS7 as an application client.</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating from 1.0.x.Final to 1.1.0.Beta1</title>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>RealmModel JPA and Mongo storage schema has changed</listitem>
|
|
||||||
<listitem>UserSessionModel JPA and Mongo storage schema has changed as these interfaces have been refactored</listitem>
|
|
||||||
<listitem>
|
|
||||||
Upgrade your adapters, old adapters are not compatible with Keycloak 1.1. We interpreted JSON Web Token and OIDC ID Token specification incorrectly. 'aud'
|
|
||||||
claim must be the client id, we were storing the realm name in there and validating it.
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating from 1.0 RC-1 to RC-2</title>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>A lot of info level logging has been changed to debug. Also, a realm no longer has the jboss-logging audit listener by default.
|
|
||||||
If you want log output when users login, logout, change passwords, etc. enable the jboss-logging audit listener through the admin console.</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating from 1.0 Beta 4 to RC-1</title>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
logout REST API has been refactored. The GET request on the logout URI does not take a session_state
|
|
||||||
parameter anymore. You must be logged in in order to log out the session.
|
|
||||||
You can also POST to the logout REST URI. This action requires a valid refresh token to perform the logout.
|
|
||||||
The signature is the same as refresh token minus the grant type form parameter. See documentation for details.
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating from 1.0 Beta 1 to Beta 4</title>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
LDAP/AD configuration is changed. It is no longer under the "Settings" page. It is now under
|
|
||||||
Users->Federation. Add Provider will show you an "ldap" option.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Authentication SPI has been removed and rewritten. The new SPI is UserFederationProvider and is
|
|
||||||
more flexible.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>ssl-not-required</literal> property in adapter config has been removed. Replaced with
|
|
||||||
<literal>ssl-required</literal>, valid values are <literal>all</literal> (require SSL for all requests), <literal>external</literal>
|
|
||||||
(require SSL only for external request) and <literal>none</literal> (SSL not required).
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
DB Schema has changed again.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Created applications now have a full scope by default. This means that you don't have to configure
|
|
||||||
the scope of an application if you don't want to.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Format of JSON file for importing realm data was changed. Now role mappings is available under the JSON record of particular
|
|
||||||
user.
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating from 1.0 Alpha 4 to Beta 1</title>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
DB Schema has changed. We have added export of the database to Beta 1, but not the ability to import
|
|
||||||
the database from older versions. This will be supported in future releases.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
For all clients except bearer-only applications, you must specify at least one redirect uri. Keycloak
|
|
||||||
will not allow you to log in unless you have specified a valid redirect uri for that application.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Resource Owner Password Credentials flow is now disabled by default. It can be enabled by setting the toggle
|
|
||||||
for <literal>Direct Grant API</literal> <literal>ON</literal> under realm config in the admin console.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Configuration is now done through <literal>standalone/configuration/keycloak-server.json</literal>. This
|
|
||||||
should mainly affect those that use MongoDB.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
JavaScript adapter has been refactored. See the <link linkend='javascript-adapter'>JavaScript adapter</link> section for more details.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
The "Central Login Lifespan" setting no longer exists. Please see the <link linkend='session-timeouts'>Session Timeout</link> section
|
|
||||||
for me details.
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating from 1.0 Alpha 2 to Alpha 3</title>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
SkeletonKeyToken, SkeletonKeyScope, SkeletonKeyPrincipal, and SkeletonKeySession have been renamed to:
|
|
||||||
AccessToken, AccessScope, KeycloakPrincipal, and KeycloakAuthenticatedSession respectively.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
ServleOAuthClient.getBearerToken() method signature has changed. It now returns an AccessTokenResponse
|
|
||||||
so that you can obtain a refresh token too.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Adapters now check the access token expiration with every request. If the token is expired, they will
|
|
||||||
attempt to invoke a refresh on the auth server using a saved refresh token.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Subject in AccessToken has been changed to the User ID.
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Migrating from 1.0 Alpha 1 to Alpha 2</title>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
DB Schema has changed. We don't have any data migration utilities yet as of Alpha 2.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
JBoss and Wildfly adapters are now installed via a JBoss/Wildfly subsystem. Please review the adapter
|
|
||||||
installation documentation. Edits to standalone.xml are now required.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
There is a new credential type "secret". Unlike other credential types, it is stored in plain text in
|
|
||||||
the database and can be viewed in the admin console.
|
|
||||||
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
There is no longer required Application or OAuth Client credentials. These client types are now
|
|
||||||
hard coded to use the "secret" credential type.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Because of the "secret" credential change to Application and OAuth Client, you'll have to update
|
|
||||||
your keycloak.json configuration files and regenarate a secret within the Application or OAuth Client
|
|
||||||
credentials tab in the administration console.
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,188 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="Overview">
|
|
||||||
<title>Overview</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Keycloak is an SSO solution for web apps, mobile and RESTful web services. It is an authentication server where users
|
|
||||||
can centrally login, logout, register, and manage their user accounts. The Keycloak admin UI can manage roles
|
|
||||||
and role mappings for any application secured by Keycloak. The Keycloak Server can also be used to perform
|
|
||||||
social logins via the user's favorite social media site i.e. Google, Facebook, Twitter etc.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
|
|
||||||
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Features:
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
SSO and Single Log Out for browser applications
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
Social Login. Enable Google, GitHub, Facebook, Twitter social login with no code required.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
LDAP and Active Directory support.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
Optional User Registration
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
Password and TOTP support (via Google Authenticator). Client cert auth coming soon.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
Forgot password support. User can have an email sent to them
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
Reset password/totp. Admin can force a password reset, or set up a temporary password.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
Not-before revocation policies per realm, application, or user.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
User session management. Admin can view user sessions and what applications/clients have an access token. Sessions can be invalidated
|
|
||||||
per realm or per user.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
Pluggable theme and style support for user facing screens. Login, grant pages, account mgmt, and admin console all
|
|
||||||
can be styled, branded, and tailored to your application and organizational needs.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
Integrated Browser App to REST Service token propagation
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
OAuth Bearer token auth for REST Services
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
OAuth 2.0 Grant requests
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
OpenID Connect Support.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
SAML Support.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
CORS Support
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
CORS Web Origin management and validation
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Completely centrally managed user and role mapping metadata. Minimal configuration at the application side
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Admin Console for managing users, roles, role mappings, clients, user sessions and allowed CORS web origins.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Account Management console that allows users to manage their own account, view their open sessions, reset passwords, etc.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Deployable as a WAR, appliance, or on Openshift. Completely clusterable.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Multitenancy support. You can host and manage multiple realms for multiple organizations. In the same auth server
|
|
||||||
and even within the same deployed application.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Identity brokering/chaining. You can make the Keycloak server a child IDP to another SAML 2.0 or OpenID Connect IDP.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Token claim, assertion, and attribute mappings. You can map user attributes, roles, and role names however you want
|
|
||||||
into a OIDC ID Token, Access Token, SAML attribute statements, etc. This feature allows you to basically
|
|
||||||
tailor however you want auth responses to look.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Supports JBoss AS7, EAP 6.x, Wildfly, Tomcat 7, Tomcat 8, Jetty 9.1.x, Jetty 9.2.x, Jetty 8.1.x, and Pure JavaScript applications. Plans to support Node.js, RAILS, GRAILS, and other non-Java deployments
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Key Concepts in Keycloak</title>
|
|
||||||
<para>
|
|
||||||
The core concept in Keycloak is a <emphasis>Realm</emphasis>. A realm secures and manages security metadata
|
|
||||||
for a set of users and registered clients. Users can be created within a specific realm
|
|
||||||
within the Administration console. Roles (permission types) can be defined at the realm level and you can also
|
|
||||||
set up user role mappings to assign these permissions to specific users.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
A <emphasis>client</emphasis> is a service that is secured by a realm. You will often use Client for every Application secured by Keycloak. When a user browses an
|
|
||||||
application's web site, the application can redirect the user agent to the Keycloak Server and request a login.
|
|
||||||
Once a user is logged in, they can visit any other client (application) managed by the realm and not have to re-enter
|
|
||||||
credentials. This also hold true for logging out. Roles can also be defined at the client level and
|
|
||||||
assigned to specific users. Depending on the client type, you may also be able to view and manage
|
|
||||||
user sessions from the administration console.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In admin console there is switch <emphasis>Consent required</emphasis> specified when creating/editing client. When on, the client is not immediately granted
|
|
||||||
all permissions of the user. In addition to requesting the login credentials of the user, the Keycloak Server
|
|
||||||
will also display a grant page asking the user if it is ok to grant allowed permissions to the client. The granted consents are saved
|
|
||||||
and every user can see his granted consents in Account Management UI and he can also revoke them for particular client. Also admin can see and revoke the grants
|
|
||||||
of particular user in Keycloak Admin Console UI.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>How Does Security Work in Keycloak?</title>
|
|
||||||
<para>
|
|
||||||
Keycloak uses <emphasis>access tokens</emphasis> to secure web invocations. Access tokens contains security metadata specifying the
|
|
||||||
identity of the user as well as the role mappings for that user. The format of these tokens is a Keycloak
|
|
||||||
extension to the <ulink url="http://tools.ietf.org/html/draft-ietf-oauth-json-web-token-14">JSON Web Token</ulink> specification. Each realm has a private and public key pair
|
|
||||||
which it uses to digitally sign the access token using the <ulink url="http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-19">JSON Web Signature</ulink> specification.
|
|
||||||
Applications can verify the integrity of the digitally signed
|
|
||||||
access token using the public key of the realm. The protocols used to obtain this token is defined by the
|
|
||||||
<ulink url="http://tools.ietf.org/html/rfc6749">OAuth 2.0</ulink> specification.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The interesting thing about using these <emphasis>smart</emphasis> access tokens is that applications themselves are completely stateless
|
|
||||||
as far as security metadata goes. All the information they need about the user is contained in the token and there's
|
|
||||||
no need for them to store any security metadata locally other than the public key of the realm.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Signed access tokens can also be propagated by REST client requests within an <literal>Authorization</literal>
|
|
||||||
header. This is great for distributed integration as applications can request a login from a client to obtain
|
|
||||||
an access token, then invoke any aggregated REST invocations to other services using that access token. So,
|
|
||||||
you have a distributed security model that is centrally managed, yet does not require a Keycloak Server hit
|
|
||||||
per request, only for the initial login.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Permission Scopes</title>
|
|
||||||
<para>
|
|
||||||
Each client is configured with a set of permission scopes. These are a set
|
|
||||||
of roles that a client is allowed to ask permission for. Access tokens are always
|
|
||||||
granted at the request of a specific client. This also holds true for SSO. As you visit
|
|
||||||
different sites, the application will redirect back to the Keycloak Server via the OAuth 2.0 protocol to obtain an access
|
|
||||||
token specific to that application (client). The role mappings contained within the token are the intersection
|
|
||||||
between the set of user role mappings and the permission scope of the client. So,
|
|
||||||
access tokens are tailor made for each client and contain only the information required
|
|
||||||
for by them.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,71 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="access-types">
|
|
||||||
<title>Client Access Types</title>
|
|
||||||
<para>
|
|
||||||
When you create a Client in admin console you may be wondering what the "Access Types" are.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>confidential</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Confidential access type is for clients that need to perform a browser login and that you want
|
|
||||||
to require a client secret when they turn an access code into an access token, (see
|
|
||||||
<ulink url="http://tools.ietf.org/html/rfc6749#section-4.1.3">Access Token Request</ulink> in
|
|
||||||
the OAuth 2.0 spec for more details). The advantages of this is that it is a little extra security.
|
|
||||||
Since Keycloak requires you to register valid redirect-uris, I'm not exactly sure what this little
|
|
||||||
extra security is though. :)
|
|
||||||
The disadvantages of this access type is that confidential access type is pointless for pure
|
|
||||||
Javascript clients as anybody could easily figure out your client's secret!
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>public</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Public access type is for clients that need to perform a browser login and that you feel
|
|
||||||
that the added extra security of confidential access type is not needed. FYI, Pure javascript
|
|
||||||
clients are by nature public.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>bearer-only</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Bearer-only access type means that the application only allows bearer token requests. If this
|
|
||||||
is turned on, this application cannot participate in browser logins.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>direct access only</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
You would also see a "Direct Access Only" switch when creating the Client.
|
|
||||||
This switch is for clients that only use the <link linkend='direct-access-grants'>Direct Access Grant</link>
|
|
||||||
protocol to obtain access tokens.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,421 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="adapter-config">
|
|
||||||
<title>General Adapter Config</title>
|
|
||||||
<para>
|
|
||||||
Each adapter supported by Keycloak can be configured by a simple JSON text file. This is what one might
|
|
||||||
look like:
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting><![CDATA[{
|
|
||||||
"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"
|
|
||||||
}]]>
|
|
||||||
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Some of these configuration switches may be adapter specific and some are common across all adapters.
|
|
||||||
For Java adapters you can use <literal>${...}</literal> enclosure as System property replacement.
|
|
||||||
For example <literal>${jboss.server.config.dir}</literal>. 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 <literal>Installation</literal> tab and this will provide you with a template that includes
|
|
||||||
the public key of the realm.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Here is a description of each item:
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>realm</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Name of the realm representing the users of your distributed applications and services.
|
|
||||||
This is
|
|
||||||
<emphasis>REQUIRED.</emphasis>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>resource</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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
|
|
||||||
<emphasis>REQUIRED.</emphasis>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>realm-public-key</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
PEM format of public key. You can obtain this from the administration console.
|
|
||||||
This is
|
|
||||||
<emphasis>REQUIRED.</emphasis>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>auth-server-url</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The base URL of the Keycloak Server. All other Keycloak pages and REST services are derived
|
|
||||||
from this. It is usually of the form <literal>https://host:port/auth</literal>
|
|
||||||
This is
|
|
||||||
<emphasis>REQUIRED.</emphasis>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>ssl-required</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Ensures that all communication to and from the Keycloak server from the adapter is over HTTPS.
|
|
||||||
This is <emphasis>OPTIONAL</emphasis>. The default value is
|
|
||||||
<emphasis>external</emphasis>
|
|
||||||
meaning that HTTPS is required by default for external requests. Valid values are 'all', 'external'
|
|
||||||
and 'none'.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>use-resource-role-mappings</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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 <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>public-client</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If set to true, the adapter will not send credentials for the client to Keycloak.
|
|
||||||
The default value is <emphasis>false</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>enable-cors</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This enables CORS support. It will handle CORS preflight requests. It will also look into
|
|
||||||
the access token to determine valid origins.
|
|
||||||
This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>cors-max-age</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If CORS is enabled, this sets the value of the
|
|
||||||
<literal>Access-Control-Max-Age</literal>
|
|
||||||
header.
|
|
||||||
This is <emphasis>OPTIONAL</emphasis>. If not set, this header is not returned in CORS
|
|
||||||
responses.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>cors-allowed-methods</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If CORS is enabled, this sets the value of the
|
|
||||||
<literal>Access-Control-Allow-Methods</literal>
|
|
||||||
header. This should be a comma-separated string.
|
|
||||||
This is <emphasis>OPTIONAL</emphasis>. If not set, this header is not returned in CORS
|
|
||||||
responses.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>cors-allowed-headers</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If CORS is enabled, this sets the value of the
|
|
||||||
<literal>Access-Control-Allow-Headers</literal>
|
|
||||||
header. This should be a comma-separated string.
|
|
||||||
This is <emphasis>OPTIONAL</emphasis>. If not set, this header is not returned in CORS
|
|
||||||
responses.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>bearer-only</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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
|
|
||||||
<literal>Authorization</literal>
|
|
||||||
header.
|
|
||||||
This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>enable-basic-auth</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This tells the adapter to also support basic authentication. If this option is enabled,
|
|
||||||
then <emphasis>secret</emphasis> must also be provided.
|
|
||||||
This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>expose-token</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If <literal>true</literal>, an authenticated browser client (via a Javascript HTTP invocation)
|
|
||||||
can obtain the signed access token via the URL <literal>root/k_query_bearer_token</literal>.
|
|
||||||
This is <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>credentials</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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
|
|
||||||
<literal>password</literal>
|
|
||||||
is supported.
|
|
||||||
This is <emphasis>REQUIRED</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>connection-pool-size</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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 <emphasis>OPTIONAL</emphasis>. The default value is <literal>20</literal>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>disable-trust-manager</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If the Keycloak Server requires HTTPS and this config option is set to <literal>true</literal>
|
|
||||||
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 <emphasis>OPTIONAL</emphasis>. The default value is <literal>false</literal>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>allow-any-hostname</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If the Keycloak Server requires HTTPS and this config option is set to <literal>true</literal>
|
|
||||||
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 <emphasis>OPTIONAL</emphasis>. The default value is <literal>false</literal>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
|
|
||||||
<varlistentry>
|
|
||||||
<term>truststore</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This setting is for Java adapters. The value is the file path to a Java keystore file. If
|
|
||||||
you prefix the path with <literal>classpath:</literal>, 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
|
|
||||||
<emphasis>OPTIONAL</emphasis>
|
|
||||||
if
|
|
||||||
<literal>ssl-required</literal>
|
|
||||||
is
|
|
||||||
<literal>none</literal>
|
|
||||||
or
|
|
||||||
<literal>disable-trust-manager</literal>
|
|
||||||
is <literal>true</literal>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>truststore-password</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Password for the truststore keystore.
|
|
||||||
This is
|
|
||||||
<emphasis>REQUIRED</emphasis>
|
|
||||||
if
|
|
||||||
<literal>truststore</literal>
|
|
||||||
is set.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>client-keystore</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<emphasis>Not supported yet, but we will support in future versions.</emphasis>
|
|
||||||
|
|
||||||
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 <emphasis>OPTIONAL</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>client-keystore-password</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<emphasis>Not supported yet, but we will support in future versions.</emphasis>
|
|
||||||
Password for the client keystore.
|
|
||||||
This is
|
|
||||||
<emphasis>REQUIRED</emphasis>
|
|
||||||
if
|
|
||||||
<literal>client-keystore</literal>
|
|
||||||
is set.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>client-key-password</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<emphasis>Not supported yet, but we will support in future versions.</emphasis>
|
|
||||||
Password for the client's key.
|
|
||||||
This is
|
|
||||||
<emphasis>REQUIRED</emphasis>
|
|
||||||
if
|
|
||||||
<literal>client-keystore</literal>
|
|
||||||
is set.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>auth-server-url-for-backend-requests</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Alternative location of auth-server-url used just for backend requests. It must be absolute URI. Useful
|
|
||||||
especially in cluster (see <link linkend="relative-uri-optimization">Relative URI Optimization</link>) or if you would like to use <emphasis>https</emphasis> for browser requests
|
|
||||||
but stick with <emphasis>http</emphasis> for backend requests etc.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>always-refresh-token</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If <emphasis>true</emphasis>, Keycloak will refresh token in every request. More info in <link linkend="refresh-token-each-req">Refresh token in each request</link> .
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>register-node-at-startup</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If <emphasis>true</emphasis>, then adapter will send registration request to Keycloak. It's <emphasis>false</emphasis>
|
|
||||||
by default and useful just in cluster (See <link linkend="registration-app-nodes">Registration of application nodes to Keycloak</link>)
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>register-node-period</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Period for re-registration adapter to Keycloak. Useful in cluster. See <link linkend="registration-app-nodes">Registration of application nodes to Keycloak</link> for details.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>token-store</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Possible values are <emphasis>session</emphasis> and <emphasis>cookie</emphasis>. Default is <emphasis>session</emphasis>,
|
|
||||||
which means that adapter stores account info in HTTP Session. Alternative <emphasis>cookie</emphasis> means storage of info in cookie.
|
|
||||||
See <link linkend="stateless-token-store">Stateless token store</link> for details.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>principal-attribute</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
OpenID Connection ID Token attribute to populate the UserPrincipal name with. If token attribute is null, defaults to <literal>sub</literal>.
|
|
||||||
Possible values are <literal>sub</literal>, <literal>preferred_username</literal>, <literal>email</literal>, <literal>name</literal>, <literal>nickname</literal>, <literal>given_name</literal>, <literal>family_name</literal>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>turn-off-change-session-id-on-login</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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 <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>proxy-url</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Defines the proxy to use for requests sent to the auth-server-url.
|
|
||||||
This is <emphasis>OPTIONAL</emphasis>. Note that only the <emphasis>scheme</emphasis>,
|
|
||||||
<emphasis>host</emphasis> and <emphasis>port</emphasis> of the proxy URL are used.
|
|
||||||
Proxies that require authentication are currently not supported.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
|
@ -1,12 +0,0 @@
|
||||||
<chapter>
|
|
||||||
<title>KeycloakSecurityContext</title>
|
|
||||||
<para>
|
|
||||||
The <literal>KeycloakSecurityContext</literal> 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.
|
|
||||||
<programlisting>
|
|
||||||
httpServletRequest.getAttribute(KeycloakSecurityContext.class.getName());
|
|
||||||
httpServletRequest.getSession().getAttribute(KeycloakSecurityContext.class.getName());
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,75 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="adapter_error_handling">
|
|
||||||
<title>Error Handling</title>
|
|
||||||
<para>
|
|
||||||
Keycloak has some error handling facilities for servlet based client adapters. When an error is encountered in
|
|
||||||
authentication, keycloak will call <literal>HttpServletResponse.sendError()</literal>. You can set up an error-page
|
|
||||||
within your <literal>web.xml</literal> file to handle the error however you want. Keycloak may throw
|
|
||||||
400, 401, 403, and 500 errors.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<error-page>
|
|
||||||
<error-code>404</error-code>
|
|
||||||
<location>/ErrorHandler</location>
|
|
||||||
</error-page>]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Keycloak also sets an <literal>HttpServletRequest</literal> attribute that you can retrieve. The attribute name
|
|
||||||
is <literal>org.keycloak.adapters.spi.AuthenticationError</literal>. Typecast this object to:
|
|
||||||
<literal>org.keycloak.adapters.OIDCAuthenticationError</literal>. This class can tell you exactly what happened.
|
|
||||||
If this attribute is not set, then the adapter was not responsible for the error code.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
|
@ -1,102 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="admin-permissions">
|
|
||||||
<title>Master Admin Access Control</title>
|
|
||||||
<para>
|
|
||||||
You can create and manage multiple realms by logging into the <literal>master</literal> Keycloak admin console
|
|
||||||
at <literal>/{keycloak-root}/admin/index.html</literal>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Users in the Keycloak <literal>master</literal> realm can be granted permission to manage zero or more realms that are
|
|
||||||
deployed on the Keycloak server. When a realm is created, Keycloak automatically creates various roles that grant fine-grain
|
|
||||||
permissions to access that new realm.
|
|
||||||
Access to The Admin Console and REST endpoints can be controlled by mapping these roles to users in the <literal>master</literal> realm.
|
|
||||||
It's possible to create multiple super users as well as users that have only access to certain operations in specific realms.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Global Roles</title>
|
|
||||||
<para>
|
|
||||||
There are two realm roles in the <literal>master</literal> realm. These are:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<literal>admin</literal> - This is the super-user role and grants permissions to all operations on all realms
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>create-realm</literal> - This grants the user permission to create new realms. A user that creates a realm is granted all permissions to the newly created realm.
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To add these roles to a user select the <literal>master</literal> realm, then click on <literal>Users</literal>.
|
|
||||||
Find the user you want to grant permissions to, open the user and click on <literal>Role Mappings</literal>. Under
|
|
||||||
<literal>Realm Roles</literal> assign any of the above roles to the user by selecting it and clicking on the right-arrow.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Realm Specific Roles</title>
|
|
||||||
<para>
|
|
||||||
Each realm in Keycloak is represented by an application in the <literal>master</literal> realm. The name of the application
|
|
||||||
is <literal><realm name>-realm</literal>. This allows assigning access to users for individual realms. The
|
|
||||||
roles available are:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<literal>view-realm</literal> - View the realm configuration
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>view-users</literal> - View users (including details for specific user) in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>view-applications</literal> - View applications in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>view-clients</literal> - View clients in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>view-events</literal> - View events in the realm
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<literal>manage-realm</literal> - Modify the realm configuration (and delete the realm)
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>manage-users</literal> - Create, modify and delete users in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>manage-applications</literal> - Create, modify and delete applications in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>create-clients</literal> - Create clients in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>manage-clients</literal> - Create, modify and delete clients in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>manage-events</literal> - Enable/disable events, clear logged events and manage event listeners
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
Manage roles includes permissions to view (for example a user with manage-realm role can also view the realm configuration).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To add these roles to a user select the <literal>master</literal> realm, then click on <literal>Users</literal>.
|
|
||||||
Find the user you want to grant permissions to, open the user and click on <literal>Role Mappings</literal>. Under
|
|
||||||
<literal>Application Roles</literal> select the application that represents the realm you're adding permissions to
|
|
||||||
(<literal><realm name>-realm</literal>), then assign any of the above roles to the user by selecting it and clicking on the right-arrow.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,35 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="admin-rest-api">
|
|
||||||
<title>Admin REST API</title>
|
|
||||||
<para>
|
|
||||||
The Keycloak Admin Console is implemented entirely with a fully functional REST admin API. You can invoke this
|
|
||||||
REST API from your Java applications by obtaining an access token. You must have the appropriate
|
|
||||||
permissions set up as described in <xref linkend="admin-permissions" /> and <xref linkend="per-realm-admin-permissions" />
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The documentation for this REST API is auto-generated and is contained in the distribution of keycloak under
|
|
||||||
the docs/rest-api/overview-index.html directory, or directly from the docs page at the keycloak website.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
There are a number of examples that come with the keycloak distribution that show you how to invoke on this REST API.
|
|
||||||
<literal>examples/preconfigured-demo/admin-access-app</literal> shows you how to access this api from java.
|
|
||||||
<literal>examples/cors/angular-product-app</literal> shows you how to invoke on it from Javascript. Finally there is example in
|
|
||||||
<literal>example/admin-client</literal>, which contains example for Admin client, that can be used to invoke REST endpoints easily as Java methods.
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,253 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="applicationClustering">
|
|
||||||
<title>Application Clustering</title>
|
|
||||||
|
|
||||||
<para>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:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
stateless or stateful
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
distributable (replicated http session) or non-distributable and just relying on sticky sessions provided by loadbalancer
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
deployed on same or different cluster hosts where keycloak servers are deployed
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<note>
|
|
||||||
<para>
|
|
||||||
To enable distributable (replicated) HTTP Sessions in your application, you may need to do some additional steps. Usually you need to put <![CDATA[<distributable />]]>
|
|
||||||
tag into <literal>WEB-INF/web.xml</literal> 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.
|
|
||||||
</para>
|
|
||||||
</note>
|
|
||||||
|
|
||||||
<section id="stateless-token-store">
|
|
||||||
<title>Stateless token store</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
stateless application without need of HTTP Session, but with requirement to be safe to failover of some cluster node
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
stateful application, but you don't want sensitive token data to be saved in HTTP session
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
stateless application relying on loadbalancer, which is not aware of sticky sessions (in this case cookie is your only way)
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To configure this, you can add this line to configuration of your adapter in <literal>WEB-INF/keycloak.json</literal> of your application:
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
"token-store": "cookie"
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Default value of <literal>token-store</literal> is <literal>session</literal>, hence saving data in HTTP session.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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).
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="admin-url-configuration">
|
|
||||||
<title>Admin URL configuration</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For example logout of user from Keycloak works like this:
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
User sends logout request from one of applications where he is logged.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Then application will send logout request to Keycloak
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You may again use relative values for admin URL, but in cluster it may not be the best similarly like in <link linkend='relative-uri-optimization'>previous section</link> .
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Some examples of possible values of admin URL are:
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>http://${jboss.host.name}:8080/myapp</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Note that since the application is distributable,
|
|
||||||
the backend request sent by Keycloak could be served on any application cluster node as invalidation
|
|
||||||
of HTTP Session on <emphasis>node1</emphasis> will propagate the invalidation to other cluster nodes due to replicated HTTP sessions.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>http://${application.session.host}:8080/myapp</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Keycloak will track hosts where is particular HTTP Session served and it will send session
|
|
||||||
invalidation message to proper cluster node.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For example application is deployed on <emphasis>http://node1:8080/myapp</emphasis> and <emphasis>http://node2:8080/myapp</emphasis> .
|
|
||||||
Now HTTP Session <emphasis>session1</emphasis> is sticky-session served on cluster node <emphasis>node2</emphasis> .
|
|
||||||
When keycloak invalidates this session, it will send request directly to <emphasis>http://node2:8080/myapp</emphasis> .
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This is ideal configuration for distributable applications deployed on different host than keycloak
|
|
||||||
or for non-distributable applications deployed either on same or different nodes than keycloak.
|
|
||||||
Good thing is that it doesn't send requests through load-balancer and hence helps to reduce network traffic.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="registration-app-nodes">
|
|
||||||
<title>Registration of application nodes to Keycloak</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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:
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Once new application node joins cluster, it sends registration request to Keycloak server
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The request may be re-sent to Keycloak in configured periodic intervals
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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 .
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Sending startup registrations and periodic re-registration is disabled by default, as it's main usecase is just
|
|
||||||
cluster deployment. In <literal>WEB-INF/keycloak.json</literal> of your application, you can specify:
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
"register-node-at-startup": true,
|
|
||||||
"register-node-period": 600,
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In Keycloak admin console you can specify the maximum node re-registration timeout (makes sense to have it
|
|
||||||
bigger than <emphasis>register-node-period</emphasis> 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).
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="refresh-token-each-req">
|
|
||||||
<title>Refresh token in each request</title>
|
|
||||||
<para>
|
|
||||||
By default, application adapter tries to refresh access token when it's expired (period can be specified as <link linkend='token-timeouts'>Access Token Lifespan</link>) .
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In <literal>WEB-INF/keycloak.json</literal> you can configure:
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
"always-refresh-token": true
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,81 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="server_cache">
|
|
||||||
<title>Server Cache</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Eviction and Expiration</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
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 <literal>standalone.xml</literal> or <literal>standalone-ha.xml</literal>.
|
|
||||||
Locate the element <literal>cache-container name="keycloak"</literal> and change the eviction policy for the <literal>users</literal> cache. For
|
|
||||||
more information see <ulink url="https://docs.jboss.org/author/display/WFLY10/Infinispan+Subsystem">Infinispan Subsystem documentation</ulink>.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Disabling Caches</title>
|
|
||||||
<para>
|
|
||||||
To disable the realm or user cache, you must edit the <literal>keycloak-server.json</literal> file
|
|
||||||
in your distribution. Here's what the config looks like initially.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
"userCache": {
|
|
||||||
"infinispan" : {
|
|
||||||
"enabled": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"realmCache": {
|
|
||||||
"infinispan" : {
|
|
||||||
"enabled": true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
<para>To disable the cache set the enabled field to false for the cache you want to disable:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
"userCache": {
|
|
||||||
"infinispan" : {
|
|
||||||
"enabled": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
"realmCache": {
|
|
||||||
"infinispan" : {
|
|
||||||
"enabled": false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Clear Caches</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,232 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="client-registration">
|
|
||||||
<title>Client Registration</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
In order for an application or service to utilize Keycloak it has to register a client in Keycloak. An
|
|
||||||
admin can do this through the admin console (or admin REST endpoints), but clients can also register themselves
|
|
||||||
through Keycloak's client registration service.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The Client Registration Service provides built-in support for Keycloak Client Representations, OpenID Connect
|
|
||||||
Client Meta Data and SAML Entity Descriptors. It's also possible to plugin custom client registration providers
|
|
||||||
if required. The Client Registration Service endpoint is <literal><KEYCLOAK URL>/realms/<realm>/clients-registrations/<provider></literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The built-in supported <literal>providers</literal> are:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem><literal>default</literal> Keycloak Representations</listitem>
|
|
||||||
<listitem><literal>install</literal> Keycloak Adapter Configuration</listitem>
|
|
||||||
<listitem><literal>openid-connect</literal> OpenID Connect Dynamic Client Registration</listitem>
|
|
||||||
<listitem><literal>saml2-entity-descriptor</literal> SAML Entity Descriptors</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
The following sections will describe how to use the different providers.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Authentication</title>
|
|
||||||
<para>
|
|
||||||
To invoke the Client Registration Services you need a token. The token can be a standard bearer token, a
|
|
||||||
initial access token or a registration access token.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Bearer Token</title>
|
|
||||||
<para>
|
|
||||||
The bearertoken can be issued on behalf of a user or a Service Account. The following permissions are required
|
|
||||||
to invoke the endpoints (see <link linkend='admin-permissions'>Admin Permissions</link> for more details):
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<literal>create-client</literal> or <literal>manage-client</literal> - To create clients
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>view-client</literal> or <literal>manage-client</literal> - To view clients
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>manage-client</literal> - To update or delete clients
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
If you are using a regular bearer token to create clients we recommend using a token from on behalf of a
|
|
||||||
Service Account with only the <literal>create-client</literal> role. See the
|
|
||||||
<link linkend="service-accounts">Service Account</link> section for more details.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Initial Access Token</title>
|
|
||||||
<para>
|
|
||||||
The best approach to create new clients is by using initial access tokens. An initial access token can
|
|
||||||
only be used to create clients and has a configurable expiration as well as a configurable limit on
|
|
||||||
how many clients can be created.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
An initial access token can be created through the admin console. To create a new initial access token
|
|
||||||
first select the realm in the admin console, then click on <literal>Realm Settings</literal> in the menu
|
|
||||||
on the left, followed by <literal>Initial Access Tokens</literal> in the tabs displayed in the page.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You will now be able to see any existing initial access tokens. If you have access you can delete tokens
|
|
||||||
that are no longer required. You can only retrieve the value of the token when you are creating it. To
|
|
||||||
create a new token click on <literal>Create</literal>. You can now optionally add how long the token
|
|
||||||
should be valid, also how many clients can be created using the token. After you click on <literal>Save</literal>
|
|
||||||
the token value is displayed. It is important that you copy/paste this token now as you won't be able
|
|
||||||
to retrieve it later. If you forget to copy/paste it, then delete the token and create another one.
|
|
||||||
The token value is used as a standard bearer token when invoking the Client Registration Services, by
|
|
||||||
adding it to the Authorization header in the request. For example:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
Authorization: bearer eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiJmMjJmNzQyYy04ZjNlLTQ2M....
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Registration Access Token</title>
|
|
||||||
<para>
|
|
||||||
When you create a client through the Client Registration Service the response will include a registration
|
|
||||||
access token. The registration access token provides access to retrieve the client configuration later, but
|
|
||||||
also to update or delete the client. The registration access token is included with the request in the
|
|
||||||
same way as a bearer token or initial access token. Registration access tokens are only valid once
|
|
||||||
when it's used the response will include a new token.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If a client was created outside of the Client Registration Service it won't have a registration access
|
|
||||||
token associated with it. You can create one through the admin console. This can also be useful if
|
|
||||||
you loose the token for a particular client. To create a new token find the client in the admin console
|
|
||||||
and click on <literal>Credentials</literal>. Then click on <literal>Generate registration access token</literal>.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Keycloak Representations</title>
|
|
||||||
<para>
|
|
||||||
The <literal>default</literal> client registration provider can be used to create, retrieve, update and delete a client. It uses
|
|
||||||
Keycloaks Client Representation format which provides support for configuring clients exactly as they can
|
|
||||||
be configured through the admin console, including for example configuring protocol mappers.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To create a client create a Client Representation (JSON) then do a HTTP POST to:
|
|
||||||
<literal><KEYCLOAK URL>/realms/<realm>/clients-registrations/default</literal>. It will return a Client Representation
|
|
||||||
that also includes the registration access token. You should save the registration access token somewhere
|
|
||||||
if you want to retrieve the config, update or delete the client later.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To retrieve the Client Representation then do a HTTP GET to:
|
|
||||||
<literal><KEYCLOAK URL>/realms/<realm>/clients-registrations/default/<client id></literal>. It will also
|
|
||||||
return a new registration access token.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To update the Client Representation then do a HTTP PUT to with the updated Client Representation to:
|
|
||||||
<literal><KEYCLOAK URL>/realms/<realm>/clients-registrations/default/<client id></literal>. It will also
|
|
||||||
return a new registration access token.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To delete the Client Representation then do a HTTP DELETE to:
|
|
||||||
<literal><KEYCLOAK URL>/realms/<realm>/clients-registrations/default/<client id></literal>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Keycloak Adapter Configuration</title>
|
|
||||||
<para>
|
|
||||||
The <literal>installation</literal> client registration provider can be used to retrieve the adapter configuration
|
|
||||||
for a client. In addition to token authentication you can also authenticate with client credentials using
|
|
||||||
HTTP basic authentication. To do this include the following header in the request:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
Authorization: basic BASE64(client-id + ':' + client-secret)
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To retrieve the Adapter Configuration then do a HTTP GET to:
|
|
||||||
<literal><KEYCLOAK URL>//realms/<realm>/clients-registrations/install/<client id></literal>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
No authentication is required for public clients. This means that for the JavaScript adapter you can
|
|
||||||
load the client configuration directly from Keycloak using the above URL.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>OpenID Connect Dynamic Client Registration</title>
|
|
||||||
<para>
|
|
||||||
Keycloak implements <ulink url="https://openid.net/specs/openid-connect-registration-1_0.html">OpenID Connect Dynamic Client Registration</ulink>,
|
|
||||||
which extends <ulink url="https://tools.ietf.org/html/rfc7591">OAuth 2.0 Dynamic Client Registration Protocol</ulink> and
|
|
||||||
<ulink url="https://tools.ietf.org/html/rfc7592">OAuth 2.0 Dynamic Client Registration Management Protocol</ulink>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The endpoint to use these specifications to register clients in Keycloak is:
|
|
||||||
<literal><KEYCLOAK URL>/realms/<realm>/clients-registrations/oidc[/<client id>]</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This endpoints can also be found in the OpenID Connect Discovery endpoint for the realm:
|
|
||||||
<literal><KEYCLOAK URL>/realms/<realm>/.well-known/openid-configuration</literal>.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>SAML Entity Descriptors</title>
|
|
||||||
<para>
|
|
||||||
The SAML Entity Descriptor endpoint only supports using SAML v2 Entity Descriptors to create clients. It
|
|
||||||
doesn't support retrieving, updating or deleting clients. For those operations the Keycloak representation
|
|
||||||
endpoints should be used. When creating a client a Keycloak Client Representation is returned with details
|
|
||||||
about the created client, including a registration access token.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To create a client do a HTTP POST with the SAML Entity Descriptor to:
|
|
||||||
<literal><KEYCLOAK URL>/realms/<realm>/clients-registrations/saml2-entity-descriptor</literal>.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Client Registration Java API</title>
|
|
||||||
<para>
|
|
||||||
The Client Registration Java API makes it easy to use the Client Registration Service using Java. To use
|
|
||||||
include the dependency <literal>org.keycloak:keycloak-client-registration-api:>VERSION<</literal> from
|
|
||||||
Maven.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For full instructions on using the Client Registration refer to the JavaDocs. Below is an example of creating
|
|
||||||
a client:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
String initialAccessToken = "eyJhbGciOiJSUzI1NiJ9.eyJqdGkiOiJmMjJmNzQyYy04ZjNlLTQ2M....";
|
|
||||||
|
|
||||||
ClientRepresentation client = new ClientRepresentation();
|
|
||||||
client.setClientId(CLIENT_ID);
|
|
||||||
|
|
||||||
ClientRegistration reg = ClientRegistration.create().url("http://keycloak/auth/realms/myrealm/clients").build();
|
|
||||||
reg.auth(Auth.token(initialAccessToken));
|
|
||||||
|
|
||||||
client = reg.create(client);
|
|
||||||
|
|
||||||
String registrationAccessToken = client.getRegistrationAccessToken();
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
<section>
|
|
||||||
<title>Client Registration CLI</title>
|
|
||||||
<para>
|
|
||||||
TODO
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
-->
|
|
||||||
|
|
||||||
</chapter>
|
|
|
@ -1,57 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="clients">
|
|
||||||
<title>Clients</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Keycloak provides support for managing Clients.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section id="client-config">
|
|
||||||
<title>Client Config</title>
|
|
||||||
<para>
|
|
||||||
Keycloak supports flexible configuration of Clients.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Redirect Endpoint</title>
|
|
||||||
<para>
|
|
||||||
For scenarios where one wants to link from one client to another, Keycloak provides a special redirect endpoint:
|
|
||||||
<literal>/realms/realm_name/clients/client_id/redirect</literal>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
If a client accesses this endpoint via an <literal>HTTP GET</literal> request, Keycloak returns the configured base URL
|
|
||||||
for the provided Client and Realm in the form of an <literal>HTTP 307</literal> (Temporary Redirect) via the response's <literal>Location</literal> header.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Thus, a client only needs to know the Realm name and the Client ID in order to link to them.
|
|
||||||
This indirection helps avoid hard-coding client base URLs.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
As an example, given the realm <literal>master</literal> and the client-id <literal>account</literal>:
|
|
||||||
<programlisting>http://keycloak-host:keycloak-port/auth/realms/master/clients/account/redirect</programlisting>
|
|
||||||
|
|
||||||
Would temporarily redirect to:
|
|
||||||
<programlisting>http://keycloak-host:keycloak-port/auth/realms/master/account</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,235 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="clustering">
|
|
||||||
<title>Clustering</title>
|
|
||||||
|
|
||||||
<para>To improve availability and scalability Keycloak can be deployed in a cluster.</para>
|
|
||||||
|
|
||||||
<para>It's fairly straightforward to configure a Keycloak cluster, the steps required are:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Configure a shared database
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Configure Infinispan
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Enable realm and user cache invalidation
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Enable distributed user sessions
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Start in HA mode
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Loadbalancer (optional step)
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Configure a shared database</title>
|
|
||||||
<para>
|
|
||||||
Keycloak doesn't replicate realms and users, but instead relies on all nodes using the same
|
|
||||||
database. This can be a relational database or Mongo. To make sure your database doesn't become a single
|
|
||||||
point of failure you may also want to deploy your database to a cluster.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Migration lock</title>
|
|
||||||
<para>
|
|
||||||
Keycloak locks the database during startup. This guarantees that only startup actions like migration and importing realms are not executed
|
|
||||||
concurrently by multiple nodes.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
By default, the maximum timeout for lock is 900 seconds. If a node is unable to acquire the lock within 900 seconds, it fails to start.
|
|
||||||
The lock checking is done every 2 seconds by default. Typically you won't need to increase/decrease the default value, but just in case
|
|
||||||
it's possible to configure it in <literal>standalone/configuration/keycloak-server.json</literal>:
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
"dblock": {
|
|
||||||
"jpa": {
|
|
||||||
"lockWaitTimeout": 900,
|
|
||||||
"lockRecheckTime": 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
or similarly if you're using Mongo (just by replace <literal>jpa</literal> with <literal>mongo</literal>)
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title id="cluster-configure-infinispan">Configure Infinispan</title>
|
|
||||||
<para>
|
|
||||||
Keycloak uses <ulink url="http://www.infinispan.org/">Infinispan</ulink> caches to share information between nodes.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For realm and users Keycloak uses a invalidation cache. An invalidation cache doesn't share any data, but simply
|
|
||||||
removes stale data from remote caches and makes sure all nodes re-load data from the database when it is changed. This reduces network traffic,
|
|
||||||
as well as preventing sensitive data (such as realm keys and password hashes) from being transmitted.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
User sessions and login failures supports either distributed caches or fully replicated caches. The default is a distributed
|
|
||||||
cache. A distributed cache splits user sessions into segments where each node holds one or more segment. It is possible
|
|
||||||
to replicate each segment to multiple nodes, but this is not strictly necessary since the failure of a node
|
|
||||||
will only result in users having to re-authenticate. If you need to prevent node failures from requiring users to
|
|
||||||
re-authenticate, set the <literal>owners</literal> attribute to 2 or more for the <literal>sessions</literal> cache
|
|
||||||
of <literal>infinispan/Keycloak</literal> container as described below.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For cluster configuration edit the configuration of <literal>infinispan/Keycloak</literal> container in <literal>standalone/configuration/standalone-ha.xml</literal>.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Secure Private Network</title>
|
|
||||||
<para>
|
|
||||||
Best practice is to put intra-cluster traffic on a separate network from the network handling user request. This is both for performance reasons as
|
|
||||||
well as reducing the risk of exposing clustering to unwanted, possibly malevolent, traffic. As this is the best practice there's a separate
|
|
||||||
network interface to configure the address for clustering. This means that changing the bind address by adding <literal>-b <address></literal>
|
|
||||||
to the startup command will only affect user request.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To configure bind address for clustering add <literal>-bprivate=<private address></literal> to the startup command. As mentioned in the previous
|
|
||||||
paragraph you should only expose this on a secure private network.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Start in HA mode</title>
|
|
||||||
<para>
|
|
||||||
To start the server in HA mode, start it with:
|
|
||||||
<programlisting># bin/standalone --server-config=standalone-ha.xml -bpublic=<public address> -bprivate=<private address></programlisting>
|
|
||||||
Replace <literal>public address</literal> with the address used for user request and <literal>private address</literal> with the address used for
|
|
||||||
cluster communication.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Enabling cluster authentication and encryption</title>
|
|
||||||
<para>
|
|
||||||
By default anyone that has access to the secure private network is able to join the cluster and could potentially send malicious messages to the
|
|
||||||
cluster. As mentioned earlier the realm and user caches are invalidation caches so no sensitive information is transmitted. There is also limited
|
|
||||||
risk with regards to user sessions as even though a malicious node could potentially create a new user session they would need to be able to sign
|
|
||||||
associated tokens which is not possible without the realm private key. It would be possible to prevent user sessions from expiring and reset
|
|
||||||
failed login attempts if brute force protection is enabled.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If you are not able to fully isolate the network used for clustering communication from potential attackers you may want to enable authentication
|
|
||||||
and encryption of the cluster. This will have an impact on performance.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To enable encryption of cluster messages you first have to create a shared keystore (change the key and store passwords!):
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
# keytool -genseckey -alias keycloak -keypass <PASSWORD> -storepass <PASSWORD> \
|
|
||||||
-keyalg Blowfish -keysize 56 -keystore defaultStore.keystore -storetype JCEKS
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Copy this keystore to all nodes (for example to standalone/configuration). Then configure JGroups to encrypt all
|
|
||||||
messages by adding the <literal>ENCRYPT</literal> protocol to the JGroups sub-system (this should be added after
|
|
||||||
the <literal>pbcast.GMS</literal> protocol):
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<subsystem xmlns="urn:jboss:domain:jgroups:2.0" default-stack="udp">
|
|
||||||
<stack name="udp">
|
|
||||||
...
|
|
||||||
<protocol type="pbcast.GMS"/>
|
|
||||||
<protocol type="ENCRYPT">
|
|
||||||
<property name="key_store_name">
|
|
||||||
${jboss.server.config.dir}/defaultStore.keystore
|
|
||||||
</property>
|
|
||||||
<property name="key_password">PASSWORD</property>
|
|
||||||
<property name="store_password">PASSWORD</property>
|
|
||||||
<property name="alias">keycloak</property>
|
|
||||||
</protocol>
|
|
||||||
...
|
|
||||||
</stack>
|
|
||||||
<stack name="tcp">
|
|
||||||
...
|
|
||||||
<protocol type="pbcast.GMS"/>
|
|
||||||
<protocol type="ENCRYPT">
|
|
||||||
<property name="key_store_name">
|
|
||||||
${jboss.server.config.dir}/defaultStore.keystore
|
|
||||||
</property>
|
|
||||||
<property name="key_password">PASSWORD</property>
|
|
||||||
<property name="store_password">PASSWORD</property>
|
|
||||||
<property name="alias">keycloak</property>
|
|
||||||
</protocol>
|
|
||||||
...
|
|
||||||
</stack>
|
|
||||||
...
|
|
||||||
</subsystem>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
See the <ulink url="http://www.jgroups.org/manual/index.html#ENCRYPT">JGroups manual</ulink> for more details.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Loadbalancer setup</title>
|
|
||||||
<para>
|
|
||||||
This is optional step, however in production, when you have more Keycloak nodes in cluster, you usually want to "hide" them behind frontent loadbalancer server, which will forward the
|
|
||||||
requests to the "backend" keycloak nodes. Consult the documentation of your loadbalancer (For example <ulink url="http://mod-cluster.jboss.org/">Mod cluster</ulink> )
|
|
||||||
for how to configure this.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
But regardless of loadbalancer implementation used, it is important that you make sure the web server sets the <literal>X-Forwarded-For</literal> and
|
|
||||||
<literal>X-Forwarded-Proto</literal> headers on the requests made to Keycloak properly. This is described in details in <link linkend="proxy-address-forwarding">Reverse proxy</link>
|
|
||||||
section.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Troubleshooting</title>
|
|
||||||
<para>
|
|
||||||
Note that when you run cluster, you should see message similar to this in the log of both cluster nodes:
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
INFO [org.infinispan.remoting.transport.jgroups.JGroupsTransport] (Incoming-10,shared=udp)
|
|
||||||
ISPN000094: Received new cluster view: [node1/keycloak|1] (2) [node1/keycloak, node2/keycloak]
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
If you see just one node mentioned, it's possible that your cluster hosts are not joined together.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Usually it's best practice to have your cluster nodes on private network without firewall for communication among them.
|
|
||||||
Firewall could be enabled just on public access point to your network instead. If for some reason you still need to have firewall
|
|
||||||
enabled on cluster nodes, you will need to open some ports. Default values are UDP port 55200 and multicast port 45688
|
|
||||||
with multicast address 230.0.0.4. Note that you may need more ports opened if you want to enable additional features like diagnostics for your
|
|
||||||
JGroups stack. Keycloak delegates most of the clustering work to Infinispan/JGroups, so consult EAP or JGroups documentation for more info.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</chapter>
|
|
|
@ -1,72 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="cors">
|
|
||||||
<title>CORS</title>
|
|
||||||
<para>
|
|
||||||
CORS stands for Cross-Origin Resource Sharing. If executing browser Javascript tries to make an AJAX HTTP request
|
|
||||||
to a server's whose domain is different than the one the Javascript code came from, then the request uses the
|
|
||||||
<ulink url="http://www.w3.org/TR/cors/">CORS protocol</ulink>. The server must handle CORS requests in a special
|
|
||||||
way, otherwise the browser will not display or allow the request to be processed. This protocol exists to protect
|
|
||||||
against XSS and other Javascript-based attacks. Keycloak has support for validated CORS requests.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Keycloak's CORS support is configured per client. You specify the allowed origins
|
|
||||||
in the client's configuration page in the admin console. You can add as many you want. The value
|
|
||||||
must be what the browser would send as a value in the <literal>Origin</literal> header. For example <literal>http://example.com</literal>
|
|
||||||
is what you must specify to allow CORS requests from <literal>example.com</literal>. When an access token is
|
|
||||||
created for the client, these allowed origins are embedded within the token. On authenticated
|
|
||||||
CORS requests, your application's Keycloak adapter will handle the CORS protocol and validate the <literal>Origin</literal>
|
|
||||||
header against the allowed origins embedded in the token. If there is no match, then the request is denied.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To enable CORS processing in your application's server, you must set the <literal>enable-cors</literal> setting
|
|
||||||
to <literal>true</literal> in your <link linkend='adapter-config'>adapter's configuration file</link>. When this
|
|
||||||
setting is enabled, the Keycloak adapter will handle all CORS preflight requests. It will validate authenticated
|
|
||||||
requests (protected resource requests), but will let unauthenticated requests (unprotected resource requests) pass through.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Handling CORS Yourself</title>
|
|
||||||
<para>
|
|
||||||
This section is for Java developers securing servlet-based applications using our servlet adapter.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If you don't like our CORS support you can handle it yourself in a filter or something. One problem you will encounter is that our adapter will
|
|
||||||
may trigger for any CORS preflight OPTIONS requests to blindly secured URLs. This will result in 302 redirection or 401 responses
|
|
||||||
for the preflight OPTIONS request. To workaround this problem, you must modify your web.xml security constraints to let OPTIONS requests
|
|
||||||
through
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<security-constraint>
|
|
||||||
<web-resource-collection>
|
|
||||||
<web-resource-name>wholesale</web-resource-name>
|
|
||||||
<url-pattern>/*</url-pattern>
|
|
||||||
<http-method>GET</http-method>
|
|
||||||
<http-method>POST</http-method>
|
|
||||||
<http-method>PUT</http-method>
|
|
||||||
<http-method>DELETE</http-method>
|
|
||||||
</web-resource-collection>
|
|
||||||
...
|
|
||||||
</security-constraint>]]>
|
|
||||||
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The above security constraint will secure all URLs, but only on GET, POST, PUT, and DELETE calls. OPTIONS requests
|
|
||||||
will be let through.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,167 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="custom-user-attributes">
|
|
||||||
<title>Custom User Attributes</title>
|
|
||||||
<para>If you have custom user data you want to store and manage in the admin console, registration page, and user account service, you can easily add
|
|
||||||
support for it by extending and modifying various Keycloak <link linkend="themes">themes</link>.</para>
|
|
||||||
<section>
|
|
||||||
<title>In admin console</title>
|
|
||||||
<para>To be able to enter custom attributes in the admin console, take the following steps</para>
|
|
||||||
<para>
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
|
||||||
Create a new theme within the <literal>themes/mytheme/admin</literal> directory in your distribution.
|
|
||||||
Where <literal>mytheme</literal> is whatever you want to name your theme.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Create a <literal>theme.properties</literal> file in this directory that extends the main admin console
|
|
||||||
theme.
|
|
||||||
<programlisting><![CDATA[parent=keycloak
|
|
||||||
import=common/keycloak
|
|
||||||
]]></programlisting>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Copy the file <literal>themes/base/admin/resources/partials/user-attributes.html</literal> into the
|
|
||||||
a mirror directory in your theme: <literal>themes/mytheme/admin/resources/partials/user-attributes.html</literal>.
|
|
||||||
What you are doing here is overriding the user attribute entry page in the admin console and putting in
|
|
||||||
what attributes you want. This file already contains an example of entering address data. You can remove
|
|
||||||
this if you want and replace it with something else. Also, if you want to edit this file directly instead
|
|
||||||
of creating a new theme, you can.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
In the <literal>user-attributes.html</literal> file add your custom user attribute entry form item. For example
|
|
||||||
<programlisting><![CDATA[ <div class="form-group clearfix block">
|
|
||||||
<label class="col-sm-2 control-label" for="mobile">Mobile</label>
|
|
||||||
<div class="col-sm-6">
|
|
||||||
<input ng-model="user.attributes.mobile" class="form-control" type="text" name="mobile" id="mobile" />
|
|
||||||
</div>
|
|
||||||
<span tooltip-placement="right" tooltip="Mobile number." class="fa fa-info-circle"></span>
|
|
||||||
</div>
|
|
||||||
]]></programlisting>
|
|
||||||
The <literal>ng-model</literal> names the user attribute you will store in the database and must have the
|
|
||||||
form of <literal>user.attributes.ATTR_NAME</literal>.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Change the theme for the admin console. Save it, then refresh your browser, and you should
|
|
||||||
now see these fields in the User detail page for any user.
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>In registration page</title>
|
|
||||||
<para>To be able to enter custom attributes in the registration page, take the following steps</para>
|
|
||||||
<para>
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
|
||||||
Create a new theme within the <literal>themes/mytheme/login</literal> directory in your distribution.
|
|
||||||
Where <literal>mytheme</literal> is whatever you want to name your theme.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Create a <literal>theme.properties</literal> file in this directory that extends the main admin console
|
|
||||||
theme.
|
|
||||||
<programlisting><![CDATA[parent=keycloak
|
|
||||||
import=common/keycloak
|
|
||||||
styles= ../patternfly/lib/patternfly/css/patternfly.css ../patternfly/css/login.css ../patternfly/lib/zocial/zocial.css css/login.css]]></programlisting>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Copy the file <literal>themes/base/login/register.ftl</literal> into the
|
|
||||||
a mirror directory in your theme: <literal>themes/mytheme/login/register.ftl</literal>.
|
|
||||||
What you are doing here is overriding the registration page and adding
|
|
||||||
what attributes you want. This file already contains an example of entering address data. You can remove
|
|
||||||
this if you want and replace it with something else. Also, if you want to edit this file directly instead
|
|
||||||
of creating a new theme, you can.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
In the <literal>register.ftl</literal> file add your custom user attribute entry form item. For example
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="${properties.kcLabelWrapperClass!}">
|
|
||||||
<label for="user.attributes.mobile" class="${properties.kcLabelClass!}">Mobile number</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-sm-10 col-md-10">
|
|
||||||
<input type="text" class="${properties.kcInputClass!}" id="user.attributes.mobile" name="user.attributes.mobile"/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
]]></programlisting>
|
|
||||||
Make sure the input field id ane name match the user attribute you want to store in the database.
|
|
||||||
This must have the
|
|
||||||
form of <literal>user.attributes.ATTR_NAME</literal>. You might also want to replace the label text
|
|
||||||
with a message property. This will help later if you want to internationalize your pages.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Change the theme for the login to your new theme. Save it, then refresh your browser, and you should
|
|
||||||
now see these fields in the registration.
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>In user account profile page</title>
|
|
||||||
<para>To be able to manage custom attributes in the user account profile page, take the following steps</para>
|
|
||||||
<para>
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
|
||||||
Create a new theme within the <literal>themes/mytheme/account</literal> directory in your distribution.
|
|
||||||
Where <literal>mytheme</literal> is whatever you want to name your theme.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Create a <literal>theme.properties</literal> file in this directory that extends the main admin console
|
|
||||||
theme.
|
|
||||||
<programlisting><![CDATA[parent=patternfly
|
|
||||||
import=common/keycloak
|
|
||||||
|
|
||||||
styles= ../patternfly/lib/patternfly/css/patternfly.css ../patternfly/css/account.css css/account.css]]></programlisting>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Copy the file <literal>themes/base/account/account.ftl</literal> into the
|
|
||||||
a mirror directory in your theme: <literal>themes/mytheme/account/account.ftl</literal>.
|
|
||||||
What you are doing here is overriding the profile page and adding
|
|
||||||
what attributes you want to manage. This file already contains an example of entering address data. You can remove
|
|
||||||
this if you want and replace it with something else. Also, if you want to edit this file directly instead
|
|
||||||
of creating a new theme, you can.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
In the <literal>account.ftl</literal> file add your custom user attribute entry form item. For example
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<div class="form-group">
|
|
||||||
<div class="col-sm-2 col-md-2">
|
|
||||||
<label for="user.attributes.mobile" class="control-label">Mobile number</label>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-sm-10 col-md-10">
|
|
||||||
<input type="text" class="form-control" id="user.attributes.mobile" name="user.attributes.mobile" value="${(account.attributes.mobile!'')?html}"/>
|
|
||||||
</div>
|
|
||||||
</div>]]></programlisting>
|
|
||||||
Make sure the input field id ane name match the user attribute you want to store in the database.
|
|
||||||
This must have the
|
|
||||||
form of <literal>user.attributes.ATTR_NAME</literal>. You might also want to replace the label text
|
|
||||||
with a message property. This will help later if you want to internationalize your pages.
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
Change the theme for the account to your new theme. Save it, then refresh your browser, and you should
|
|
||||||
now see these fields in the account profile page.
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</chapter>
|
|
|
@ -1,185 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="direct-access-grants">
|
|
||||||
<title>Direct Access Grants</title>
|
|
||||||
<para>
|
|
||||||
Keycloak allows you to make direct REST invocations to obtain an access token.
|
|
||||||
(See <ulink url="http://tools.ietf.org/html/rfc6749#section-4.3">Resource Owner Password Credentials Grant</ulink>
|
|
||||||
from OAuth 2.0 spec). To use it you must also have
|
|
||||||
registered a valid Client to use as the "client_id" for this grant request.
|
|
||||||
</para>
|
|
||||||
<warning>
|
|
||||||
<para>
|
|
||||||
It is highly recommended that you do not use Direct Access Grants to write your own login pages for your application.
|
|
||||||
You will lose a lot of features that Keycloak has if you do this. Specifically all the account management, remember me,
|
|
||||||
lost password, account reset features of Keycloak. Instead, if you want to tailor the look and feel of Keycloak login
|
|
||||||
pages, you should create your own <link linkend="themes">theme</link>. There are also security implications
|
|
||||||
to using Direct Access Grants compared to the redirect based flows as you are exposing plain text passwords
|
|
||||||
to applications directly.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
It is even highly recommended that you use the browser to log in for native mobile applications! Android
|
|
||||||
and iPhone applications allow you to redirect to and from the browser. You can use this to redirect the user
|
|
||||||
from your native mobile app to the web browser to perform login, then the browser will redirect back to your
|
|
||||||
native application.
|
|
||||||
</para>
|
|
||||||
</warning>
|
|
||||||
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The REST URL to invoke on is <literal>/{keycloak-root}/realms/{realm-name}/protocol/openid-connect/token</literal>.
|
|
||||||
Invoking on this URL is a POST request and requires you to post the username and credentials of the user you want
|
|
||||||
an access token for. You must also pass along the "client_id" of the client you are creating
|
|
||||||
an access token for. This "client_id" is the Client Id specified in admin console (not it's id from DB!). Depending on
|
|
||||||
whether your client is <link linkend='access-types'>"public" or "confidential"</link>, you may also have to pass along
|
|
||||||
it's client secret as well. We support pluggable client authentication, so alternatively you can use other form of client credentials like signed JWT assertion.
|
|
||||||
See <link linkend="client_authentication">Client Authentication</link> section for more details. Finally you need to pass "grant_type"
|
|
||||||
parameter with value "password" .
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For public client's, the POST invocation requires form parameters that contain the username,
|
|
||||||
credentials, and client_id of your application. For example:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
POST /auth/realms/demo/protocol/openid-connect/token
|
|
||||||
Content-Type: application/x-www-form-urlencoded
|
|
||||||
|
|
||||||
username=bburke&password=geheim&client_id=customer-portal&grant_type=password]]>
|
|
||||||
</programlisting>
|
|
||||||
The response would be this <ulink url="http://tools.ietf.org/html/rfc6749#section-4.3.3">standard JSON document</ulink> from the OAuth 2.0 specification.
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
HTTP/1.1 200 OK
|
|
||||||
Content-Type: application/json;charset=UTF-8
|
|
||||||
Cache-Control: no-store
|
|
||||||
Pragma: no-cache
|
|
||||||
|
|
||||||
{
|
|
||||||
"access_token":"2YotnFZFEjr1zCsicMWpAA",
|
|
||||||
"token_type":"bearer",
|
|
||||||
"expires_in":3600,
|
|
||||||
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
|
|
||||||
"id_token":"tGzv3JOkF0XG5Qx2TlKWIA",
|
|
||||||
"session_state":"234234-234234-234234"
|
|
||||||
}]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For confidential client's, you must create a Basic Auth <literal>Authorization</literal>
|
|
||||||
header that contains the client_id and client secret. And pass in the form parameters for username and for
|
|
||||||
each user credential. For example:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
POST /auth/realms/demo/protocol/openid-connect/token
|
|
||||||
Authorization: Basic atasdf023l2312023
|
|
||||||
Content-Type: application/x-www-form-urlencoded
|
|
||||||
|
|
||||||
username=bburke&password=geheim&grant_type=password]]>
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
<para>As mentioned above, we support also other means of authenticating clients. In adition to default client_id and client secret,
|
|
||||||
we also have signed JWT assertion by default. There is possibility to use any other form of client authentication implemented by you. See <link linkend="client_authentication">Client Authentication</link>
|
|
||||||
section for more details.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Here's a Java example using Apache HTTP Client and some Keycloak utility classes.:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
HttpClient client = new HttpClientBuilder()
|
|
||||||
.disableTrustManager().build();
|
|
||||||
|
|
||||||
|
|
||||||
try {
|
|
||||||
HttpPost post = new HttpPost(
|
|
||||||
KeycloakUriBuilder.fromUri("http://localhost:8080/auth")
|
|
||||||
.path(ServiceUrlConstants.TOKEN_PATH).build("demo"));
|
|
||||||
List <NameValuePair> formparams = new ArrayList <NameValuePair>();
|
|
||||||
formparams.add(new BasicNameValuePair(OAuth2Constants.GRANT_TYPE, "password"));
|
|
||||||
formparams.add(new BasicNameValuePair("username", "bburke"));
|
|
||||||
formparams.add(new BasicNameValuePair("password", "password"));
|
|
||||||
|
|
||||||
if (isPublic()) { // if client is public access type
|
|
||||||
formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, "customer-portal"));
|
|
||||||
} else {
|
|
||||||
String authorization = BasicAuthHelper.createHeader("customer-portal", "secret-secret-secret");
|
|
||||||
post.setHeader("Authorization", authorization);
|
|
||||||
}
|
|
||||||
UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
|
|
||||||
post.setEntity(form);
|
|
||||||
|
|
||||||
HttpResponse response = client.execute(post);
|
|
||||||
int status = response.getStatusLine().getStatusCode();
|
|
||||||
HttpEntity entity = response.getEntity();
|
|
||||||
if (status != 200) {
|
|
||||||
throw new IOException("Bad status: " + status);
|
|
||||||
}
|
|
||||||
if (entity == null) {
|
|
||||||
throw new IOException("No Entity");
|
|
||||||
}
|
|
||||||
InputStream is = entity.getContent();
|
|
||||||
try {
|
|
||||||
AccessTokenResponse tokenResponse = JsonSerialization.readValue(is, AccessTokenResponse.class);
|
|
||||||
} finally {
|
|
||||||
try {
|
|
||||||
is.close();
|
|
||||||
} catch (IOException ignored) { }
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
client.getConnectionManager().shutdown();
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Once you have the access token string, you can use it in REST HTTP bearer token authorized requests, i.e
|
|
||||||
<programlisting>
|
|
||||||
GET /my/rest/api
|
|
||||||
Authorization: Bearer 2YotnFZFEjr1zCsicMWpAA
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To logout you must use the refresh token contained in the AccessTokenResponse object.
|
|
||||||
</para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
List<NameValuePair> formparams = new ArrayList<NameValuePair>();
|
|
||||||
if (isPublic()) { // if client is public access type
|
|
||||||
formparams.add(new BasicNameValuePair(OAuth2Constants.CLIENT_ID, "customer-portal"));
|
|
||||||
} else {
|
|
||||||
String authorization = BasicAuthHelper.createHeader("customer-portal", "secret-secret-secret");
|
|
||||||
post.setHeader("Authorization", authorization);
|
|
||||||
}
|
|
||||||
formparams.add(new BasicNameValuePair(OAuth2Constants.REFRESH_TOKEN, tokenResponse.getRefreshToken()));
|
|
||||||
HttpResponse response = null;
|
|
||||||
URI logoutUri = KeycloakUriBuilder.fromUri(getBaseUrl(request) + "/auth")
|
|
||||||
.path(ServiceUrlConstants.TOKEN_SERVICE_LOGOUT_PATH)
|
|
||||||
.build("demo");
|
|
||||||
HttpPost post = new HttpPost(logoutUri);
|
|
||||||
UrlEncodedFormEntity form = new UrlEncodedFormEntity(formparams, "UTF-8");
|
|
||||||
post.setEntity(form);
|
|
||||||
response = client.execute(post);
|
|
||||||
int status = response.getStatusLine().getStatusCode();
|
|
||||||
HttpEntity entity = response.getEntity();
|
|
||||||
if (status != 204) {
|
|
||||||
error(status, entity);
|
|
||||||
}
|
|
||||||
if (entity == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
InputStream is = entity.getContent();
|
|
||||||
if (is != null) is.close();
|
|
||||||
]]></programlisting>
|
|
||||||
</chapter>
|
|
|
@ -1,57 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="email-config">
|
|
||||||
<title>Email Server Config</title>
|
|
||||||
<para>
|
|
||||||
To enable Keycloak to send emails you need to provide Keycloak with your SMTP server settings. If you don't have
|
|
||||||
a SMTP server you can use one of many hosted solutions (such as Sendgrid or smtp2go).
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
To configure your SMTP server, open the <literal>Keycloak Admin Console</literal>, select your realm from the drop-down box in the top left corner.
|
|
||||||
Then click on <literal>Email</literal> in the menu at the top.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
You are required to fill in the <literal>Host</literal> and <literal>Port</literal> for your SMTP server (the default port for SMTP is 25). You also have
|
|
||||||
to specify the sender email address (<literal>From</literal>). The other options are optional.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The screenshot below shows a simple example where the SMTP server doesn't use SSL or TLS and doesn't require authentication.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<imagedata fileref="images/email-simple-example.png"/>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Enable SSL or TLS</title>
|
|
||||||
<para>
|
|
||||||
As emails are used for recovering usernames and passwords it's recommended to use SSL or TLS, especially if the SMTP server
|
|
||||||
is on an external network. To enable SSL click on <literal>Enable SSL</literal> or to enable TLS click on <literal>Enable TLS</literal>.
|
|
||||||
You will most likely also need to change the <literal>Port</literal> (the default port for SSL/TLS is 465).
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Authentication</title>
|
|
||||||
<para>
|
|
||||||
If your SMTP server requires authentication click on <literal>Enable Authentication</literal> and insert
|
|
||||||
the <literal>Username</literal> and <literal>Password</literal>.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
|
@ -1,120 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="events">
|
|
||||||
<title>Events</title>
|
|
||||||
<para>
|
|
||||||
Keycloak provides an Events SPI that makes it possible to register listeners for user related events, for example
|
|
||||||
user logins. There are two interfaces that can be implemented, the first is a pure listener, the second is a events
|
|
||||||
store which listens for events, but is also required to store events. An events store provides a way for the admin
|
|
||||||
and account management consoles to view events.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Event types</title>
|
|
||||||
<para>
|
|
||||||
Login events:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>Login - A user has logged in</listitem>
|
|
||||||
<listitem>Register - A user has registered</listitem>
|
|
||||||
<listitem>Logout - A user has logged out</listitem>
|
|
||||||
<listitem>Code to Token - An application/client has exchanged a code for a token</listitem>
|
|
||||||
<listitem>Refresh Token - An application/client has refreshed a token</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Account events:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>Social Link - An account has been linked to a social provider</listitem>
|
|
||||||
<listitem>Remove Social Link - A social provider has been removed from an account</listitem>
|
|
||||||
<listitem>Update Email - The email address for an account has changed</listitem>
|
|
||||||
<listitem>Update Profile - The profile for an account has changed</listitem>
|
|
||||||
<listitem>Send Password Reset - A password reset email has been sent</listitem>
|
|
||||||
<listitem>Update Password - The password for an account has changed</listitem>
|
|
||||||
<listitem>Update TOTP - The TOTP settings for an account has changed</listitem>
|
|
||||||
<listitem>Remove TOTP - TOTP has been removed from an account</listitem>
|
|
||||||
<listitem>Send Verify Email - A email verification email has been sent</listitem>
|
|
||||||
<listitem>Verify Email - The email address for an account has been verified</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For all events there is a corresponding error event.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Event Listener</title>
|
|
||||||
<para>
|
|
||||||
Keycloak comes with an Email Event Listener and a JBoss Logging Event Listener. The Email Event Listener
|
|
||||||
sends an email to the users account when an event occurs. The JBoss Logging Event Listener writes to a log
|
|
||||||
file when an events occurs.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The Email Event Listener only supports the following events at the moment:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>Login Error</listitem>
|
|
||||||
<listitem>Update Password</listitem>
|
|
||||||
<listitem>Update TOTP</listitem>
|
|
||||||
<listitem>Remove TOTP</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
You can exclude one or more events by editing <literal>standalone/configuration/keycloak-server.json</literal>
|
|
||||||
and adding for example:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
"eventsListener": {
|
|
||||||
"email": {
|
|
||||||
"exclude-events": [ "UPDATE_TOTP", "REMOVE_TOTP" ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Event Store</title>
|
|
||||||
<para>
|
|
||||||
Event Store listen for events and is expected to persist the events to make it possible to query for them
|
|
||||||
later. This is used by the admin console and account management to view events. Keycloak includes providers
|
|
||||||
to persist events to JPA and Mongo.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You can specify events to include or exclude by editing <literal>standalone/configuration/keycloak-server.json</literal>,
|
|
||||||
and adding for example:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
"eventsStore": {
|
|
||||||
"jpa": {
|
|
||||||
"exclude-events": [ "LOGIN", "REFRESH_TOKEN", "CODE_TO_TOKEN" ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Configure Events Settings for Realm</title>
|
|
||||||
<para>
|
|
||||||
To enable persisting of events for a realm you first need to make sure you have a event store provider registered for Keycloak.
|
|
||||||
By default the JPA event store provider is registered. Once you've done that open the admin console, select the
|
|
||||||
realm you're configuring, select <literal>Events</literal>. Then click on <literal>Config</literal>.
|
|
||||||
You can enable storing events for your realm by toggling <literal>Save Events</literal> to ON. You can also set
|
|
||||||
an expiration on events. This will periodically delete events from the database that are older than the specified
|
|
||||||
time.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To configure listeners for a realm on the same page as above add one or more event listeners to the
|
|
||||||
<literal>Listeners</literal> select box. This will allow you to enable any registered event listeners with the
|
|
||||||
realm.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,160 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="export-import">
|
|
||||||
<title>Export and Import</title>
|
|
||||||
<section>
|
|
||||||
<title>Startup export/import</title>
|
|
||||||
<para>
|
|
||||||
Export/import is useful especially if you want to migrate your whole Keycloak database from one environment to another or migrate to different database (For example from MySQL to Oracle).
|
|
||||||
You can trigger export/import at startup of Keycloak server and it's configurable with System properties right now. The fact it's done at server startup means that no-one can access Keycloak UI or REST endpoints
|
|
||||||
and edit Keycloak database on the fly when export or import is in progress. Otherwise it could lead to inconsistent results.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You can export/import your database either to:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>Directory on local filesystem</listitem>
|
|
||||||
<listitem>Single JSON file on your filesystem</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
When importing using the "dir" strategy, note that the files need to follow the naming convention specified below.
|
|
||||||
If you are importing files which were previously exported, the files already follow this convention.
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>{REALM_NAME}-realm.json, such as "acme-roadrunner-affairs-realm.json" for the realm named "acme-roadrunner-affairs"</listitem>
|
|
||||||
<listitem>{REALM_NAME}-users-{INDEX}.json, such as "acme-roadrunner-affairs-users-0.json" for the first users file of the realm named "acme-roadrunner-affairs"</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If you import to Directory, you can specify also the number of users to be stored in each JSON file.
|
|
||||||
</para>
|
|
||||||
<warning>
|
|
||||||
<para>
|
|
||||||
If you have bigger amount of users in your database (500 or more), it's higly recommended to export into directory rather than to single file.
|
|
||||||
Exporting into single file may lead to the very big file. Also the directory provider is using separate transaction for each "page" (file with users),
|
|
||||||
which leads to much better performance. Default count of users per file (and transaction) is 50, which showed us best performance, but you have possibility to override (See below).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Exporting to single file is using one transaction per whole export and one per whole import, which leads to
|
|
||||||
bad performance with large amount of users - time increases exponentially with number of users.
|
|
||||||
</para>
|
|
||||||
</warning>
|
|
||||||
<para>
|
|
||||||
To export into the directory you can use:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
bin/standalone.sh -Dkeycloak.migration.action=export
|
|
||||||
-Dkeycloak.migration.provider=dir -Dkeycloak.migration.dir=<DIR TO EXPORT TO>
|
|
||||||
]]></programlisting>
|
|
||||||
And similarly for import just use <literal>-Dkeycloak.migration.action=import</literal> instead of <literal>export</literal> .
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To export into single JSON file you can use:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
bin/standalone.sh -Dkeycloak.migration.action=export
|
|
||||||
-Dkeycloak.migration.provider=singleFile -Dkeycloak.migration.file=<FILE TO EXPORT TO>
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Here's an example of importing:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
bin/standalone.sh -Dkeycloak.migration.action=import
|
|
||||||
-Dkeycloak.migration.provider=singleFile -Dkeycloak.migration.file=<FILE TO IMPORT>
|
|
||||||
-Dkeycloak.migration.strategy=OVERWRITE_EXISTING
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Other available options are:
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>-Dkeycloak.migration.realmName</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
can be used if you want to export just one specified realm instead of all.
|
|
||||||
If not specified, then all realms will be exported.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>-Dkeycloak.migration.usersExportStrategy</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
can be used to specify for Directory providers to specify where to import users.
|
|
||||||
Possible values are:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>DIFFERENT_FILES - Users will be exported into more different files according to maximum number of users per file. This is default value</listitem>
|
|
||||||
<listitem>SKIP - exporting of users will be skipped completely</listitem>
|
|
||||||
<listitem>REALM_FILE - All users will be exported to same file with realm (So file like "foo-realm.json" with both realm data and users)</listitem>
|
|
||||||
<listitem>SAME_FILE - All users will be exported to same file but different than realm (So file like "foo-realm.json" with realm data and "foo-users.json" with users)</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>-Dkeycloak.migration.usersPerFile</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
can be used to specify number of users per file (and also per DB transaction).
|
|
||||||
It's 50 by default. It's used only if usersExportStrategy is DIFFERENT_FILES
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>-Dkeycloak.migration.strategy</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
is used during import. It can be used to specify how to proceed if realm with same name
|
|
||||||
already exists in the database where you are going to import data. Possible values are:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>IGNORE_EXISTING - Ignore importing if realm of this name already exists</listitem>
|
|
||||||
<listitem>OVERWRITE_EXISTING - Remove existing realm and import it again with new data from JSON file.
|
|
||||||
If you want to fully migrate one environment to another and ensure that the new environment will contain same data
|
|
||||||
like the old one, you can specify this.
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
When importing realm files that weren't exported before, the option <literal>keycloak.import</literal> can be used. If more than one realm
|
|
||||||
file needs to be imported, a comma separated list of file names can be specified. This is more appropriate than the cases before, as this
|
|
||||||
will happen only after the master realm has been initialized. Examples:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>-Dkeycloak.import=/tmp/realm1.json</listitem>
|
|
||||||
<listitem>-Dkeycloak.import=/tmp/realm1.json,/tmp/realm2.json</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Admin console export/import</title>
|
|
||||||
<para>
|
|
||||||
Import of most resources can be performed from the admin console.
|
|
||||||
Exporting resources will be supported in future versions.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The files created during a "startup" export can be used to import from
|
|
||||||
the admin UI. This way, you can export from one realm and import to
|
|
||||||
another realm. Or, you can export from one server and import to another.
|
|
||||||
</para>
|
|
||||||
<warning>
|
|
||||||
<para>
|
|
||||||
The admin console import allows you to "overwrite" resources if you choose.
|
|
||||||
Use this feature with caution, especially on a production system.
|
|
||||||
</para>
|
|
||||||
</warning>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,69 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="fuse-adapter">
|
|
||||||
<title>JBoss Fuse and Apache Karaf Adapter</title>
|
|
||||||
<para>
|
|
||||||
Currently Keycloak supports securing your web applications running inside <ulink url="http://www.jboss.org/products/fuse/overview/">JBoss Fuse</ulink>
|
|
||||||
or <ulink url="http://karaf.apache.org/">Apache Karaf</ulink> . It leverages <link linkend="jetty8-adapter">Jetty 8 adapter</link> as all of JBoss Fuse 6.2.1, JBoss Fuse 6.2.0
|
|
||||||
and Apache Karaf 3 are bundled with <ulink url="http://eclipse.org/jetty/">Jetty 8.1 server</ulink> under the covers and Jetty is used for running various kinds of web applications.
|
|
||||||
For JBoss Fuse 6.3 and Karaf 4, bundled with Jetty 9 server, it leverages <link linkend="jetty9-adapter">Jetty 9 adapter</link>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
What is supported for Fuse/Karaf is:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Security for classic WAR applications deployed on Fuse/Karaf with <ulink url="https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+War">Pax Web War Extender</ulink>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Security for servlets deployed on Fuse/Karaf as OSGI services with <ulink url="https://ops4j1.jira.com/wiki/display/ops4j/Pax+Web+Extender+-+Whiteboard">Pax Web Whiteboard Extender</ulink>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Security for <ulink url="http://camel.apache.org/">Apache Camel</ulink> Jetty endpoints running with
|
|
||||||
<ulink url="http://camel.apache.org/jetty.html">Camel Jetty</ulink> component.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Security for <ulink url="http://cxf.apache.org/">Apache CXF</ulink> endpoints running on their own separate
|
|
||||||
<ulink url="http://cxf.apache.org/docs/jetty-configuration.html">Jetty engine</ulink>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Security for <ulink url="http://cxf.apache.org/">Apache CXF</ulink> endpoints running on default engine provided by CXF servlet.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Security for SSH and JMX admin access.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Security for <ulink url="http://hawt.io/">Hawt.io admin console</ulink> .
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>The best place to start is look at Fuse demo bundled as part of Keycloak examples in directory <literal>examples/fuse</literal> .</para>
|
|
||||||
</section>
|
|
|
@ -1,48 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="groups">
|
|
||||||
<title>Groups</title>
|
|
||||||
<para>
|
|
||||||
Groups in Keycloak allow you to manage a common set of attributes and role mappings for a large set of users.
|
|
||||||
Users can be members of zero or more groups. Users inherit the attributes and role mappings assign to each group.
|
|
||||||
As an admin this makes it easy for you to manage permissions for a user in one place.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Groups are hierarchical. A group can have many subgroups, but a group can only have one parent. Subgroups inherit
|
|
||||||
the attributes and role mappings from the parent. This applies to user as well. So, if you have a parent group and a child group
|
|
||||||
and a user that only belongs to the child group, the user inherits the attributes and role mappings of both the
|
|
||||||
parent and child.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Groups vs. Roles</title>
|
|
||||||
<para>
|
|
||||||
In the IT world the concepts of Group and Role are often blurred and interchangeable. In Keycloak, Groups are just
|
|
||||||
a collection of users that you can apply roles and attributes to in one place. Roles are used to assign permissions
|
|
||||||
and access control.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Keycloak Roles have the concept of a Composite Role. A role can be associated with one or more additional roles.
|
|
||||||
This is called a Composite Role. If a user has a role mapping to the Composite Role, they inherit all the roles associated
|
|
||||||
with the composite. So what's the difference from a Keycloak Group and a Composite Role? Logically they could be
|
|
||||||
used for the same exact thing. The difference is conceptual. Composite roles should be used to compose the
|
|
||||||
permission model of your set of services and applications. So, roles become a set of permissions. Groups on the
|
|
||||||
other hand, would be a set of users that have a set of permissions. Use Groups to manage users, composite roles to
|
|
||||||
manage applications and services.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,42 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="installed-applications">
|
|
||||||
<title>Installed Applications</title>
|
|
||||||
<para>
|
|
||||||
Keycloak provides two special redirect uris for installed applications.
|
|
||||||
</para>
|
|
||||||
<section id="installed-applications-url">
|
|
||||||
<title>http://localhost</title>
|
|
||||||
<para>
|
|
||||||
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 <literal>Admin Console</literal>.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="installed-applications-urn">
|
|
||||||
<title>urn:ietf:wg:oauth:2.0:oob</title>
|
|
||||||
<para>
|
|
||||||
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 <literal>urn:ietf:wg:oauth:2.0:oob</literal> 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.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
|
@ -1,59 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="jaas-adapter">
|
|
||||||
<title>JAAS plugin</title>
|
|
||||||
<para>
|
|
||||||
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:
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>org.keycloak.adapters.jaas.DirectAccessGrantsLoginModule</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This login module allows to authenticate with username/password from Keycloak database. It's using
|
|
||||||
<link linkend="direct-access-grants">Direct Access Grants</link> 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.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>org.keycloak.adapters.jaas.BearerTokenLoginModule</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Both login modules have configuration property <literal>keycloak-config-file</literal> 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 <literal>classpath:/folder-on-classpath/keycloak.json</literal> ).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Second property <literal>role-principal-class</literal> allows to specify alternative class for Role principals attached to JAAS Subject. Default
|
|
||||||
value for Role principal is <literal>org.keycloak.adapters.jaas.RolePrincipal</literal> . Note that class should have constructor
|
|
||||||
with single String argument.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
|
@ -1,429 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="javascript-adapter">
|
|
||||||
<title>Javascript Adapter</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To use this adapter, you must first configure an application (or client) through the <literal>Keycloak Admin Console</literal>.
|
|
||||||
You should select <literal>public</literal> for the <literal>Access Type</literal> 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 <literal>Installation</literal> tab and download the <literal>keycloak.json</literal>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Next, you have to initialize the adapter in your application. An example is shown below.
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<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>
|
|
||||||
]]></programlisting>
|
|
||||||
To specify the location of the keycloak.json file:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
var keycloak = Keycloak('http://localhost:8080/myapp/keycloak.json'));
|
|
||||||
]]></programlisting>
|
|
||||||
Or finally to manually configure the adapter:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
var keycloak = Keycloak({
|
|
||||||
url: 'http://keycloak-server/auth',
|
|
||||||
realm: 'myrealm',
|
|
||||||
clientId: 'myapp'
|
|
||||||
});
|
|
||||||
]]></programlisting>
|
|
||||||
You can also pass <literal>login-required</literal> or <literal>check-sso</literal> 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:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
keycloak.init({ onLoad: 'login-required' })
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
After you login, your application will be able to make REST calls using bearer token authentication. Here's
|
|
||||||
an example pulled from the <literal>customer-portal-js</literal> example that comes with the distribution.
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<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>
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <literal>loadData()</literal> method builds an HTTP request setting the <literal>Authorization</literal>
|
|
||||||
header to a bearer token. The <literal>keycloak.token</literal> points to the access token the browser obtained
|
|
||||||
when it logged you in. The <literal>loadFailure()</literal> method is invoked on a failure. The <literal>reloadData()</literal>
|
|
||||||
function calls <literal>keycloak.updateToken()</literal> passing in the <literal>loadData()</literal> and
|
|
||||||
<literal>loadFailure()</literal> callbacks. The <literal>keycloak.updateToken()</literal> 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 <literal>loadData()</literal> method.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
To refresh the token when it is expired, call the <literal>updateToken</literal> 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.
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
keycloak.updateToken(30).success(function() {
|
|
||||||
// send request with valid token
|
|
||||||
}).error(function() {
|
|
||||||
alert('failed to refresh token');
|
|
||||||
);
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Session status iframe</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
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 <literal>checkLoginIframe: false</literal> in the options passed to the <literal>init</literal>
|
|
||||||
method.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="javascript-implicit-flow">
|
|
||||||
<title>Implicit and Hybrid Flow</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
By default, the JavaScript adapter uses <ulink url="http://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth">OpenID Connect standard (Authorization code) flow</ulink>, which
|
|
||||||
means that after authentication, the Keycloak server redirects the user back to your application, where the JavaScript adapter will exchange the <literal>code</literal> for an access token and a refresh token.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
However, Keycloak also supports <ulink url="http://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth">OpenID Connect Implicit flow</ulink>
|
|
||||||
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).
|
|
||||||
</para>
|
|
||||||
<para>To enable implicit flow, you need to enable the <literal>Implicit Flow Enabled</literal> flag for the client in the Keycloak admin console. You also need to pass
|
|
||||||
the parameter <literal>flow</literal> with value <literal>implicit</literal> to <literal>init</literal> method.
|
|
||||||
An example is below:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
keycloak.init({ flow: 'implicit' })
|
|
||||||
]]></programlisting>
|
|
||||||
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 <literal>onTokenExpired</literal> 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.)
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Keycloak also has support for <ulink url="http://openid.net/specs/openid-connect-core-1_0.html#HybridFlowAuth">OpenID Connect Hybrid flow</ulink>. This requires
|
|
||||||
the client to have both the <literal>Standard Flow Enabled</literal> and <literal>Implicit Flow Enabled</literal> 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).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For hybrid flow, you need to pass the parameter <literal>flow</literal> with value <literal>hybrid</literal> to <literal>init</literal> method.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Older browsers</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
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:
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>Base64 - <ulink url="https://github.com/davidchambers/Base64.js">https://github.com/davidchambers/Base64.js</ulink></listitem>
|
|
||||||
<listitem>HTML5 History - <ulink url="https://github.com/devote/HTML5-History-API">https://github.com/devote/HTML5-History-API</ulink></listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>JavaScript Adapter reference</title>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Constructor</title>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
new Keycloak();
|
|
||||||
new Keycloak('http://localhost/keycloak.json');
|
|
||||||
new Keycloak({ url: 'http://localhost/auth', realm: 'myrealm', clientId: 'myApp' });
|
|
||||||
]]></programlisting>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Properties</title>
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>authenticated - true if the user is authenticated</listitem>
|
|
||||||
<listitem>token - the base64 encoded token that can be sent in the <literal>Authorization</literal> header in requests to services</listitem>
|
|
||||||
<listitem>tokenParsed - the parsed token</listitem>
|
|
||||||
<listitem>subject - the user id</listitem>
|
|
||||||
<listitem>idToken - the id token if claims is enabled for the application, null otherwise</listitem>
|
|
||||||
<listitem>idTokenParsed - the parsed id token</listitem>
|
|
||||||
<listitem>realmAccess - the realm roles associated with the token</listitem>
|
|
||||||
<listitem>resourceAccess - the resource roles assocaited with the token</listitem>
|
|
||||||
<listitem>refreshToken - the base64 encoded token that can be used to retrieve a new token</listitem>
|
|
||||||
<listitem>refreshTokenParsed - the parsed refresh token</listitem>
|
|
||||||
<listitem>timeSkew - estimated skew between local time and Keycloak server in seconds</listitem>
|
|
||||||
<listitem>responseMode - responseMode passed during initialization. See below for details. Default value is <literal>fragment</literal></listitem>
|
|
||||||
<listitem>flow - OpenID Connect flow passed during initialization. See <link linkend="javascript-implicit-flow">Implicit flow</link> for details.</listitem>
|
|
||||||
<listitem>responseType - responseType used for send to Keycloak server at login request. This is determined based on the <literal>flow</literal> value used during initialization,
|
|
||||||
but you have possibility to override it by directly set this value</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Methods</title>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>init(options)</title>
|
|
||||||
|
|
||||||
<para>Called to initialize the adapter.</para>
|
|
||||||
<para>Options is an Object, where:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>onLoad - specifies an action to do on load, can be either 'login-required' or 'check-sso'</listitem>
|
|
||||||
<listitem>token - set an initial value for the token</listitem>
|
|
||||||
<listitem>refreshToken - set an initial value for the refresh token</listitem>
|
|
||||||
<listitem>idToken - set an initial value for the id token (only together with token or refreshToken)</listitem>
|
|
||||||
<listitem>timeSkew - set an initial value for skew between local time and Keycloak server in seconds (only together with token or refreshToken)</listitem>
|
|
||||||
<listitem>checkLoginIframe - set to enable/disable monitoring login state (default is true)</listitem>
|
|
||||||
<listitem>checkLoginIframeInterval - set the interval to check login state (default is 5 seconds)</listitem>
|
|
||||||
<listitem>responseMode - set the OpenID Connect response mode send to Keycloak server at login request. Valid values are <literal>query</literal> or <literal>fragment</literal> .
|
|
||||||
Default value is <literal>fragment</literal>, which means that after successful authentication will Keycloak redirect to javascript application
|
|
||||||
with OpenID Connect parameters added in URL fragment. This is generally safer and recommended over <literal>query</literal>.
|
|
||||||
</listitem>
|
|
||||||
<listitem>flow - set the OpenID Connect flow. Valid values are <literal>standard</literal>, <literal>implicit</literal> or <literal>hybrid</literal>.
|
|
||||||
See <link linkend="javascript-implicit-flow">Implicit flow</link> for details.</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>Returns promise to set functions to be invoked on success or error.</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>login(options)</title>
|
|
||||||
|
|
||||||
<para>Redirects to login form on (options is an optional object with redirectUri and/or prompt fields)</para>
|
|
||||||
<para>Options is an Object, where:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>redirectUri - specifies the uri to redirect to after login</listitem>
|
|
||||||
<listitem>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)</listitem>
|
|
||||||
<listitem>loginHint - used to pre-fill the username/email field on the login form</listitem>
|
|
||||||
<listitem>action - if value is 'register' then user is redirected to registration page, otherwise to login page</listitem>
|
|
||||||
<listitem>locale - specifies the desired locale for the UI</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
<simplesect>
|
|
||||||
<title>createLoginUrl(options)</title>
|
|
||||||
|
|
||||||
<para>Returns the url to login form on (options is an optional object with redirectUri and/or prompt fields)</para>
|
|
||||||
<para>Options is an Object, where:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>redirectUri - specifies the uri to redirect to after login</listitem>
|
|
||||||
<listitem>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)</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>logout(options)</title>
|
|
||||||
|
|
||||||
<para>Redirects to logout</para>
|
|
||||||
<para>Options is an Object, where:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>redirectUri - specifies the uri to redirect to after logout</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>createLogoutUrl(options)</title>
|
|
||||||
|
|
||||||
<para>Returns logout out</para>
|
|
||||||
<para>Options is an Object, where:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>redirectUri - specifies the uri to redirect to after logout</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>register(options)</title>
|
|
||||||
|
|
||||||
<para>Redirects to registration form. It's a shortcut for doing login with option action = 'register'</para>
|
|
||||||
<para>Options are same as login method but 'action' is overwritten to 'register'</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>createRegisterUrl(options)</title>
|
|
||||||
|
|
||||||
<para>Returns the url to registration page. It's a shortcut for doing createRegisterUrl with option action = 'register'</para>
|
|
||||||
<para>Options are same as createLoginUrl method but 'action' is overwritten to 'register'</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>accountManagement()</title>
|
|
||||||
|
|
||||||
<para>Redirects to account management</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>createAccountUrl()</title>
|
|
||||||
|
|
||||||
<para>Returns the url to account management</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>hasRealmRole(role)</title>
|
|
||||||
|
|
||||||
<para>Returns true if the token has the given realm role</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>hasResourceRole(role, resource)</title>
|
|
||||||
|
|
||||||
<para>Returns true if the token has the given role for the resource (resource is optional, if not specified clientId is used)</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>loadUserProfile()</title>
|
|
||||||
|
|
||||||
<para>Loads the users profile</para>
|
|
||||||
|
|
||||||
<para>Returns promise to set functions to be invoked on success or error.</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>isTokenExpired(minValidity)</title>
|
|
||||||
|
|
||||||
<para>Returns true if the token has less than minValidity seconds left before it expires (minValidity is optional, if not specified 0 is used)</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>updateToken(minValidity)</title>
|
|
||||||
|
|
||||||
<para>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.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>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:</para>
|
|
||||||
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
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');
|
|
||||||
});
|
|
||||||
]]></programlisting>
|
|
||||||
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
<simplesect>
|
|
||||||
<title>clearToken()</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
keycloak.updateToken(5).error(function() {
|
|
||||||
keycloak.clearToken();
|
|
||||||
});
|
|
||||||
]]></programlisting>
|
|
||||||
|
|
||||||
</simplesect>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Callback Events</title>
|
|
||||||
|
|
||||||
<para>The adapter supports setting callback listeners for certain events. For example:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
keycloak.onAuthSuccess = function() { alert('authenticated'); }
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>onReady(authenticated) - called when the adapter is initialized</listitem>
|
|
||||||
<listitem>onAuthSuccess - called when a user is successfully authenticated</listitem>
|
|
||||||
<listitem>onAuthError - called if there was an error during authentication</listitem>
|
|
||||||
<listitem>onAuthRefreshSuccess - called when the token is refreshed</listitem>
|
|
||||||
<listitem>onAuthRefreshError - called if there was an error while trying to refresh the token</listitem>
|
|
||||||
<listitem>onAuthLogout - called if the user is logged out (will only be called if the session status iframe is enabled, or in Cordova mode)</listitem>
|
|
||||||
<listitem>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</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
|
@ -1,303 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="jboss-adapter">
|
|
||||||
<title>JBoss/Wildfly Adapter</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<section id="jboss-adapter-installation">
|
|
||||||
<title>Adapter Installation</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Install on Wildfly 9 or 10:
|
|
||||||
<programlisting>
|
|
||||||
$ cd $WILDFLY_HOME
|
|
||||||
$ unzip keycloak-wildfly-adapter-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Install on Wildfly 8:
|
|
||||||
<programlisting>
|
|
||||||
$ cd $WILDFLY_HOME
|
|
||||||
$ unzip keycloak-wf8-adapter-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Install on JBoss EAP 6.x:
|
|
||||||
<programlisting>
|
|
||||||
$ cd $JBOSS_HOME
|
|
||||||
$ unzip keycloak-eap6-adapter-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Install on JBoss AS 7.1.1:
|
|
||||||
<programlisting>
|
|
||||||
$ cd $JBOSS_HOME
|
|
||||||
$ unzip keycloak-as7-adapter-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This zip file creates new JBoss Modules specific to the Wildfly Keycloak Adapter within your Wildfly distro.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
After adding the Keycloak modules, you must then enable the Keycloak Subsystem within your app server's server configuration:
|
|
||||||
<literal>domain.xml</literal> or <literal>standalone.xml</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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:
|
|
||||||
<programlisting>
|
|
||||||
$ cd $JBOSS_HOME/bin
|
|
||||||
$ jboss-cli.sh -c --file=adapter-install.cli
|
|
||||||
</programlisting>
|
|
||||||
The script will add the extension, subsystem, and optional security-domain as described below.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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:
|
|
||||||
<programlisting>
|
|
||||||
$ cd $JBOSS_HOME/bin
|
|
||||||
$ jboss-cli.sh -c --file=adapter-install-offline.cli
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
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:
|
|
||||||
</para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Required Per WAR Configuration</title>
|
|
||||||
<para>
|
|
||||||
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The first thing you must do is create
|
|
||||||
a <literal>keycloak.json</literal> adapter config file within the <literal>WEB-INF</literal> directory
|
|
||||||
of your WAR. The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
|
|
||||||
section.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Next you must set the <literal>auth-method</literal> to <literal>KEYCLOAK</literal> in <literal>web.xml</literal>. 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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Securing WARs via Keycloak Subsystem</title>
|
|
||||||
<para>
|
|
||||||
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 <literal>auth-method</literal>,
|
|
||||||
you still have to define the <literal>security-constraints</literal> in <literal>web.xml</literal>. You do
|
|
||||||
not, however, have to create a <literal>WEB-INF/keycloak.json</literal> file. This metadata is instead defined
|
|
||||||
within XML in your server's <literal>domain.xml</literal> or <literal>standalone.xml</literal> subsystem
|
|
||||||
configuration section.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <literal>secure-deployment</literal> <literal>name</literal> attribute identifies the WAR you want
|
|
||||||
to secure. Its value is the <literal>module-name</literal> defined in <literal>web.xml</literal> with
|
|
||||||
<literal>.war</literal> appended. The rest of the configuration corresponds pretty much one to one
|
|
||||||
with the <literal>keycloak.json</literal> configuration options defined in <link linkend='adapter-config'>general adapter configuration</link>.
|
|
||||||
The exception is the <literal>credential</literal> element.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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 <literal>realm</literal> element.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</section>
|
|
|
@ -1,67 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="jetty8-adapter">
|
|
||||||
<title>Jetty 8.1.x Adapter</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<section id="jetty8-adapter-installation">
|
|
||||||
<title>Adapter Installation</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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!
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
$ cd $JETTY_HOME
|
|
||||||
$ unzip keycloak-jetty81-adapter-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Next, you will have to enable the keycloak option. Edit start.ini and add keycloak to the options
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
#===========================================================
|
|
||||||
# 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
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Required Per WAR Configuration</title>
|
|
||||||
<para>
|
|
||||||
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 <link linkend="jetty9_per_war">Required Per WAR Configuration</link>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
|
@ -1,173 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="jetty9-adapter">
|
|
||||||
<title>Jetty 9.x Adapters</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<section id="jetty9-adapter-installation">
|
|
||||||
<title>Adapter Installation</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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!
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
$ cd $JETTY_HOME
|
|
||||||
$ unzip keycloak-jetty92-adapter-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Next, you will have to enable the keycloak module for your jetty.base.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
$ cd your-base
|
|
||||||
$ java -jar $JETTY_HOME/start.jar --add-to-startd=keycloak
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="jetty9_per_war">
|
|
||||||
<title>Required Per WAR Configuration</title>
|
|
||||||
<para>
|
|
||||||
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The first thing you must do is create a <literal>WEB-INF/jetty-web.xml</literal> file in your WAR package. This is
|
|
||||||
a Jetty specific config file and you must define a Keycloak specific authenticator within it.
|
|
||||||
</para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<?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>]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
Next you must create
|
|
||||||
a <literal>keycloak.json</literal> adapter config file within the <literal>WEB-INF</literal> directory
|
|
||||||
of your WAR. The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
|
|
||||||
section.
|
|
||||||
</para>
|
|
||||||
<warning>
|
|
||||||
<para>
|
|
||||||
The Jetty 9.1.x adapter will not be able to find the <literal>keycloak.json</literal> file. You will have to define
|
|
||||||
all adapter settings within the <literal>jetty-web.xml</literal> file as described below.
|
|
||||||
</para>
|
|
||||||
</warning>
|
|
||||||
<para>
|
|
||||||
Instead of using keycloak.json, you can define everything within the <literal>jetty-web.xml</literal>. You'll
|
|
||||||
just have to figure out how the json settings match to the <literal>org.keycloak.representations.adapters.config.AdapterConfig</literal>
|
|
||||||
class.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<?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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Finally you must specify both a <literal>login-config</literal> and use standard servlet security to specify
|
|
||||||
role-base constraints on your URLs. Here's an example:
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
|
@ -1,297 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="kerberos">
|
|
||||||
<title>Kerberos brokering</title>
|
|
||||||
<para>
|
|
||||||
Keycloak supports login with Kerberos ticket through SPNEGO. SPNEGO (Simple and Protected GSSAPI Negotiation Mechanism) is used
|
|
||||||
to authenticate transparently through the web browser after the user has been authenticated when logging-in his session.
|
|
||||||
For non-web cases or when ticket is not available during login, Keycloak also supports login with Kerberos username/password.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
A typical use case for web authentication is the following:
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
User logs into his desktop (Such as a Windows machine in Active Directory domain or Linux machine with Kerberos integration enabled).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
User then uses his browser (IE/Firefox/Chrome) to access a web application secured by Keycloak.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Application redirects to Keycloak login.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Keycloak sends HTML login screen together with status 401 and HTTP header <literal>WWW-Authenticate: Negotiate</literal>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
In case that browser has Kerberos ticket from desktop login, it transfers the desktop sign on information to the
|
|
||||||
Keycloak in header <literal>Authorization: Negotiate 'spnego-token'</literal> . Otherwise it just displays login screen.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Keycloak validates token from browser and authenticate user. It provisions user data from LDAP (in case of
|
|
||||||
LDAPFederationProvider with Kerberos authentication support) or let user to update his profile and prefill data
|
|
||||||
(in case of KerberosFederationProvider).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Keycloak returns back to the application. Communication between Keycloak and application happens through OpenID
|
|
||||||
Connect or SAML messages. The fact that Keycloak was authenticated through Kerberos is hidden from the application.
|
|
||||||
So Keycloak acts as broker to Kerberos/SPNEGO login.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For setup there are 3 main parts:
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Setup and configuration of Kerberos server (KDC)
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Setup and configuration of Keycloak server
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Setup and configuration of client machines
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Setup of Kerberos server</title>
|
|
||||||
<para>
|
|
||||||
This is platform dependent. Exact steps depend on your OS and the Kerberos vendor you're going to use.
|
|
||||||
Consult Windows Active Directory, MIT Kerberos and your OS documentation for how exactly to setup and configure Kerberos server.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
At least you will need to:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Add some user principals to your Kerberos database. You can also integrate your Kerberos with LDAP,
|
|
||||||
which means that user accounts will be provisioned from LDAP server.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Add service principal for "HTTP" service. For example if your Keycloak server will be running on
|
|
||||||
<literal>www.mydomain.org</literal> you may need to add principal <literal>HTTP/www.mydomain.org@MYDOMAIN.ORG</literal>
|
|
||||||
assuming that MYDOMAIN.ORG will be your Kerberos realm.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For example on MIT Kerberos you can run "kadmin" session. If you are on same machine where is MIT Kerberos, you can simply use command:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
sudo kadmin.local
|
|
||||||
]]></programlisting>
|
|
||||||
Then add HTTP principal and export his key to keytab file with the commands like:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
addprinc -randkey HTTP/www.mydomain.org@MYDOMAIN.ORG
|
|
||||||
ktadd -k /tmp/http.keytab HTTP/www.mydomain.org@MYDOMAIN.ORG
|
|
||||||
]]></programlisting>
|
|
||||||
Keytab file <literal>/tmp/http.keytab</literal> will need to be accessible on the host where keycloak server will be running.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Setup and configuration of Keycloak server</title>
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Install kerberos client. This is again platform dependent. If you are on Fedora, Ubuntu or RHEL, you can install package <literal>freeipa-client</literal>,
|
|
||||||
which contains Kerberos client and bunch of other stuff.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Configure kerberos client (on linux it's in file <literal>/etc/krb5.conf</literal> ). You need to put your Kerberos realm and at least
|
|
||||||
configure the Http domains your server will be running on. For the example realm MYDOMAIN.ORG you may configure <literal>domain_realm</literal> section like this:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
[domain_realm]
|
|
||||||
.mydomain.org = MYDOMAIN.ORG
|
|
||||||
mydomain.org = MYDOMAIN.ORG
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Export keytab file with HTTP principal and make sure the file is accessible to the process under which Keycloak
|
|
||||||
server is running. For production, it's ideal if it's readable just by this process and not by someone else.
|
|
||||||
For MIT Kerberos example above, we already exported keytab to <literal>/tmp/http.keytab</literal> . If your KDC and Keycloak
|
|
||||||
are running on same host, you have file already available.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Run Keycloak server and configure SPNEGO/Kerberos authentication in Keycloak admin console. Keycloak supports Kerberos authentication
|
|
||||||
through <link linkend='user_federation'>Federation provider SPI</link> . We have 2 federation providers with Kerberos authentication support:
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Kerberos</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This provider is useful if you want to authenticate with Kerberos <literal>NOT</literal> backed by LDAP server.
|
|
||||||
In this case, users are usually created to Keycloak database after first successful SPNEGO/Kerberos login
|
|
||||||
and they may need to update profile after first login, as Kerberos protocol itself doesn't provision
|
|
||||||
any data like first name, last name or email.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You can also choose if users can authenticate with classic username/password. In this case, if user doesn't have SPNEGO ticket available,
|
|
||||||
Keycloak will display login screen and user can fill his Kerberos username and password on login screen. Username/password works also for non-web flows like
|
|
||||||
<link linkend='direct-access-grants'>Direct Access grants</link>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>LDAP</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This provider is useful if you want to authenticate with Kerberos backed by LDAP server.
|
|
||||||
In this case, data about users are provisioned from LDAP server after successful Kerberos authentication.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Finally you may need to check the Kerberos authenticator correctly configured. You can go to <literal>Authentication</literal> tab in
|
|
||||||
admin console and select <literal>Browser</literal> flow. Here you will see <literal>Kerberos</literal> authenticator, which is used by Keycloak for SPNEGO
|
|
||||||
handshake with client (exchange <literal>Negotiate</literal> header etc.). By default it's disabled, so Keycloak doesn't ask for Negotiate header, however once you
|
|
||||||
configured federation provider in previous step, it's automatically switched to <literal>ALTERNATIVE</literal>. So defacto you don't need to do anything, just
|
|
||||||
check that it's really switched to Alternative.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Alternative means that Keycloak tries to ask browser for Negotiate header, but if it's not available, it will continue on next authenticator (which usually means
|
|
||||||
displaying username/password form to user). You can switch to <literal>REQUIRED</literal> if you want to enforce login with
|
|
||||||
kerberos ticket and not allow fallback to username/password form.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Setup and configuration of client machines</title>
|
|
||||||
<para>
|
|
||||||
Clients need to install kerberos client and setup krb5.conf as described above. Additionally they need to enable SPNEGO login support in their browser.
|
|
||||||
See for example <ulink url="http://www.microhowto.info/howto/configure_firefox_to_authenticate_using_spnego_and_kerberos.html">this</ulink>
|
|
||||||
for more info about Firefox. URI <literal>.mydomain.org</literal> must be allowed in <literal>network.negotiate-auth.trusted-uris</literal> config option.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In windows domain, clients usually don't need to configure anything special as IE is already able to participate in SPNEGO authentication for the windows domain.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Example setups</title>
|
|
||||||
<para>
|
|
||||||
For easier testing with Kerberos, we provided some example setups to test.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Keycloak and FreeIPA docker image</title>
|
|
||||||
<para>
|
|
||||||
Once you install <ulink url="https://www.docker.com/">docker</ulink>, you can run docker image with <ulink url="http://www.freeipa.org/">FreeIPA</ulink>
|
|
||||||
server installed. FreeIPA provides integrated security solution with MIT Kerberos and 389 LDAP server among other things . The image provides
|
|
||||||
also Keycloak server configured with LDAP Federation provider and enabled SPNEGO/Kerberos authentication against the FreeIPA server.
|
|
||||||
See details <ulink url="https://github.com/mposolda/keycloak-freeipa-docker/blob/master/README.md">here</ulink> .
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>ApacheDS testing Kerberos server</title>
|
|
||||||
<para>
|
|
||||||
For quick testing and unit tests, we use very simple <ulink url="http://directory.apache.org/apacheds/">ApacheDS</ulink> Kerberos server.
|
|
||||||
You need to build Keycloak from sources and then run Kerberos server with maven-exec-plugin from our testsuite. See details
|
|
||||||
<ulink url="https://github.com/keycloak/keycloak/blob/master/misc/Testsuite.md#kerberos-server">here</ulink> .
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Credential delegation</title>
|
|
||||||
<para>
|
|
||||||
One scenario supported by Kerberos 5 is credential delegation. In this case when user receives forwardable TGT and authenticates to the web server,
|
|
||||||
then web server might be able to reuse the ticket and forward it to another service secured by Kerberos (for example LDAP server or IMAP server).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The scenario is supported by Keycloak, but there is tricky thing that SPNEGO authentication is done by Keycloak server but
|
|
||||||
GSS credential will need to be used by your application. So you need to enable built-in <literal>gss delegation credential</literal> protocol mapper
|
|
||||||
in admin console for your application. This will cause that Keycloak will deserialize GSS credential and transmit it to the application
|
|
||||||
in access token. Application will need to deserialize it and use it for further GSS calls against other services. We have an example, which is showing it in details. It's in <literal>examples/kerberos</literal>
|
|
||||||
in the Keycloak example distribution or demo distribution download. You can also check the example sources directly <ulink url="https://github.com/keycloak/keycloak/blob/master/examples/kerberos">here</ulink> .
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Once you deserialize the credential from the access token to the GSSCredential object, then GSSContext will need to
|
|
||||||
be created with this credential passed to the method <literal>GSSManager.createContext</literal> for example like this:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
GSSContext context = gssManager.createContext(serviceName, krb5Oid,
|
|
||||||
deserializedGssCredFromKeycloakAccessToken, GSSContext.DEFAULT_LIFETIME);
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Note that you also need to configure <literal>forwardable</literal> kerberos tickets in <literal>krb5.conf</literal> file
|
|
||||||
and add support for delegated credentials to your browser. For details, see the kerberos example from Keycloak examples set as mentioned above.
|
|
||||||
</para>
|
|
||||||
<warning>
|
|
||||||
<para>
|
|
||||||
Credential delegation has some security implications. So enable the protocol claim and support in browser just if you really need it.
|
|
||||||
It's highly recommended to use it together with HTTPS. See for example
|
|
||||||
<ulink url="http://www.microhowto.info/howto/configure_firefox_to_authenticate_using_spnego_and_kerberos.html#idp27072">this article</ulink>
|
|
||||||
for details.
|
|
||||||
</para>
|
|
||||||
</warning>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Troubleshooting</title>
|
|
||||||
<para>
|
|
||||||
If you have issues, we recommend to enable more logging by:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Enable <literal>Debug</literal> flag in admin console for Kerberos or LDAP federation providers
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Enable TRACE logging for category <literal>org.keycloak</literal> in logging section of <literal>$WILDFLY_HOME/standalone/configuration/standalone.xml</literal>
|
|
||||||
to receive more info <literal>$WILDFLY_HOME/standalone/log/server.log</literal>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Add system properties <literal>-Dsun.security.krb5.debug=true</literal> and <literal>-Dsun.security.spnego.debug=true</literal>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,26 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Logout</title>
|
|
||||||
<para>
|
|
||||||
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 <literal>http://auth-server/auth/realms/{realm-name}/protocol/openid-connect/logout?redirect_uri=encodedRedirectUri</literal>.
|
|
||||||
This will log you out if you have an SSO session with your browser.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
|
@ -1,73 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="multi_tenancy">
|
|
||||||
<title>Multi Tenancy</title>
|
|
||||||
<para>
|
|
||||||
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 <literal>keycloak.json</literal> files.
|
|
||||||
For this case, there are two possible solutions:
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
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.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
A WAR file deployed once (possibly in a cluster), that decides which realm to authenticate against based on the request parameters.
|
|
||||||
This scenario is suitable when there are an undefined number of realms. One example would be a SaaS provider that have only one deployment
|
|
||||||
(perhaps in a cluster) serving several companies, differentiating between clients based on the hostname
|
|
||||||
(<literal>client1.acme.com</literal>, <literal>client2.acme.com</literal>) or path (<literal>/app/client1/</literal>,
|
|
||||||
<literal>/app/client2/</literal>) or even via a special HTTP Header.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
This chapter of the reference guide focus on this second scenario.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
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:
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
Add a context parameter to the <literal>web.xml</literal>, named <literal>keycloak.config.resolver</literal>.
|
|
||||||
The value of this property should be the fully qualified name of the class extending
|
|
||||||
<literal>org.keycloak.adapters.KeycloakConfigResolver</literal>.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
A concrete implementation of <literal>org.keycloak.adapters.KeycloakConfigResolver</literal>. Keycloak will call the
|
|
||||||
<literal>resolve(org.keycloak.adapters.spi.HttpFacade.Request)</literal> method and expects a complete
|
|
||||||
<literal>org.keycloak.adapters.KeycloakDeployment</literal> in response. Note that Keycloak will call this for every request,
|
|
||||||
so, take the usual performance precautions.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
An implementation of this feature can be found in the examples.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
|
@ -1,87 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="openshift">
|
|
||||||
<title>Running Keycloak Server on OpenShift</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
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
|
|
||||||
<ulink url="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.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<warning>
|
|
||||||
<para>
|
|
||||||
It's important that immediately after creating a Keycloak instance you open the <literal>Administration Console</literal>
|
|
||||||
and login to reset the password. If this is not done anyone can easily gain admin rights to your Keycloak instance.
|
|
||||||
</para>
|
|
||||||
</warning>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Create Keycloak instance with the web tool</title>
|
|
||||||
<para>
|
|
||||||
Open
|
|
||||||
<ulink url="https://openshift.redhat.com/app/console/applications"/>
|
|
||||||
and click on <literal>Add Application</literal>.
|
|
||||||
Scroll down to the bottom of the page to find the
|
|
||||||
<literal>Code Anything</literal>
|
|
||||||
section. Insert
|
|
||||||
<literal>http://cartreflect-claytondev.rhcloud.com/github/keycloak/openshift-keycloak-cartridge</literal>
|
|
||||||
into the
|
|
||||||
<literal>URL to a cartridge definition</literal>
|
|
||||||
field and click on <literal>Next</literal>. Fill in the
|
|
||||||
following form and click on <literal>Create Application</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Click on <literal>Continue to the application overview page</literal>. Under the list of applications you should
|
|
||||||
find your Keycloak instance and the status should be <literal>Started</literal>. Click on it to open the Keycloak
|
|
||||||
servers homepage.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Create Keycloak instance with the command-line tool</title>
|
|
||||||
<para>
|
|
||||||
Run the following command from a terminal:
|
|
||||||
<programlisting>rhc app create <APPLICATION NAME> http://cartreflect-claytondev.rhcloud.com/github/keycloak/openshift-keycloak-cartridge</programlisting>
|
|
||||||
Replace <literal><APPLICATION NAME></literal> with the name you want (for example keycloak).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Once the instance is created the rhc tool outputs details about it. Open the returned <literal>URL</literal> in a
|
|
||||||
browser to open the Keycloak servers homepage.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Next steps</title>
|
|
||||||
<para>
|
|
||||||
The Keycloak servers homepage shows the Keycloak logo and <literal>Welcome to Keycloak</literal>.
|
|
||||||
There is also a link to the <literal>Administration Console</literal>. Open that and log in using username
|
|
||||||
<literal>admin</literal> and password <literal>admin</literal>. On the first login you are required to change the password.
|
|
||||||
</para>
|
|
||||||
<tip>
|
|
||||||
<para>
|
|
||||||
On OpenShift Keycloak has been configured to only accept requests over https. If you try to use http
|
|
||||||
you will be redirected to https.
|
|
||||||
</para>
|
|
||||||
</tip>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,82 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="per-realm-admin-permissions">
|
|
||||||
<title>Per Realm Admin Access Control</title>
|
|
||||||
<para>
|
|
||||||
Administering your realm through the <literal>master</literal> realm as discussed in <xref linkend="admin-permissions" /> may not always be
|
|
||||||
ideal or feasible. For example, maybe you have more than one admin application that manages various admin aspects of your organization
|
|
||||||
and you want to unify all these different "admin consoles" under one realm so you can do SSO between them. Keycloak allows you to
|
|
||||||
grant realm admin privileges to users within that realm. These realm admins can participate in SSO for that realm and
|
|
||||||
visit a keycloak admin console instance that is dedicated solely for that realm by going to the url:
|
|
||||||
<literal>/{keycloak-root}/admin/{realm}/console</literal>
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Realm Roles</title>
|
|
||||||
<para>
|
|
||||||
Each realm has a built-in application called <literal>realm-management</literal>. This application defines
|
|
||||||
roles that define permissions that can be granted to manage the realm.
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<literal>realm-admin</literal> - This is a composite role that grants all admin privileges for managing
|
|
||||||
security for that realm.
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
These are more fine-grain roles you can assign to the user.
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<literal>view-realm</literal> - View the realm configuration
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>view-users</literal> - View users (including details for specific user) in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>view-applications</literal> - View applications in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>view-clients</literal> - View clients in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>view-events</literal> - View events in the realm
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<literal>manage-realm</literal> - Modify the realm configuration (and delete the realm)
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>manage-users</literal> - Create, modify and delete users in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>manage-applications</literal> - Create, modify and delete applications in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>manage-clients</literal> - Create, modify and delete clients in the realm
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<literal>manage-events</literal> - Enable/disable events, clear logged events and manage event listeners
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
Manage roles includes permissions to view (for example a user with manage-realm role can also view the realm configuration).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To add these roles to a user select the realm you want. Then click on <literal>Users</literal>.
|
|
||||||
Find the user you want to grant permissions to, open the user and click on <literal>Role Mappings</literal>. Under
|
|
||||||
<literal>Application Roles</literal> select <literal>realm-management</literal>, then assign any of the above roles to the user by selecting it and clicking on the right-arrow.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,34 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="mappers">
|
|
||||||
<title>OIDC Token and SAML Assertion Mappings</title>
|
|
||||||
<para>
|
|
||||||
Applications that receive ID Tokens, Access Tokens, or SAML assertions may need or want different user metadata
|
|
||||||
and roles. Keycloak allows you to define what exactly is transferred. You can hardcode roles, claims and custom
|
|
||||||
attributes. You can pull user metadata into a token or assertion. You can rename roles. Basicall you have
|
|
||||||
a lot of control of what exactly goes back to the client.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Within the admin console, if you go to an application you've registered, you'll see a "Mappers" sub-menu item.
|
|
||||||
This is the place where you can control how a OIDC ID Token, Access Token, and SAML login response assertions look
|
|
||||||
like. When you click on this you'll see some default mappers that have been set up for you. Clicking the
|
|
||||||
"Add Builtin" button gives you the option to add other preconfigured mappers. Clicking on "Create" allows
|
|
||||||
you to define your own protocol mappers. The tooltips are very helpful to learn exactly what you can do
|
|
||||||
to tailor your tokens and assertions. They should be enough to guide you through the process.
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,410 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="providers">
|
|
||||||
<title>Providers and SPIs</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Keycloak is designed to cover most use-cases without requiring custom code, but we also want it to be
|
|
||||||
customizable. To achive this Keycloak has a number of SPIs which you can implement your own providers for.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Implementing a SPI</title>
|
|
||||||
<para>
|
|
||||||
To implement an SPI you need to implement it's ProviderFactory and Provider interfaces. You also need to
|
|
||||||
create a provider-configuration file. For example to implement the Event Listener SPI you need to implement
|
|
||||||
EventListenerProviderFactory and EventListenerProvider and also provide the file
|
|
||||||
<literal>META-INF/services/org.keycloak.events.EventListenerProviderFactory</literal>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For example to implement the Event Listener SPI you start by implementing EventListenerProviderFactory:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
package org.acme.provider;
|
|
||||||
|
|
||||||
import ...
|
|
||||||
|
|
||||||
public class MyEventListenerProviderFactory implements EventListenerProviderFactory {
|
|
||||||
|
|
||||||
private List<Event> events;
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return "my-event-listener";
|
|
||||||
}
|
|
||||||
|
|
||||||
public void init(Config.Scope config) {
|
|
||||||
int max = config.getInt("max");
|
|
||||||
events = new MaxList(max);
|
|
||||||
}
|
|
||||||
|
|
||||||
public EventListenerProvider create(KeycloakSession session) {
|
|
||||||
return new MyEventListenerProvider(events);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void close() {
|
|
||||||
events = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
]]></programlisting>
|
|
||||||
The example uses an imagined MaxList which has a maximum size and is concurrency safe. When the maximum size is reached
|
|
||||||
and new entries are added the oldest entry is removed. Keycloak creates a single instance of
|
|
||||||
EventListenerProviderFactory which makes it possible to store state for multiple requests. EventListenerProvider
|
|
||||||
instances are created by calling create on the factory for each requests so these should be light-weight.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Next you would implement EventListenerProvider:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
package org.acme.provider;
|
|
||||||
|
|
||||||
import ...
|
|
||||||
|
|
||||||
public class MyEventListenerProvider implements EventListenerProvider {
|
|
||||||
|
|
||||||
private List<Event> events;
|
|
||||||
|
|
||||||
public MyEventListenerProvider(List<Event> events) {
|
|
||||||
this.events = events;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onEvent(Event event) {
|
|
||||||
events.add(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The file <literal>META-INF/services/org.keycloak.events.EventListenerProviderFactory</literal> should
|
|
||||||
contain the full name of your ProviderFactory implementation:
|
|
||||||
<programlisting><![CDATA[org.acme.provider.MyEventListenerProviderFactory]]></programlisting>
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Show info from you SPI implementation in Keycloak admin console</title>
|
|
||||||
<para>
|
|
||||||
Sometimes it is useful to show additional info about your Provider to a Keycloak administrator.
|
|
||||||
You can show provider build time informations (eg. version of custom provider currently installed),
|
|
||||||
current configuration of the provider (eg. url of remote system your provider talks to) or some operational
|
|
||||||
info (average time of response from remote system your provider talks to).
|
|
||||||
Keycloak admin console provides Server Info page to show this kind of information.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To show info from your provider it is enough to implement
|
|
||||||
<literal>org.keycloak.provider.ServerInfoAwareProviderFactory</literal> interface in your ProviderFactory.
|
|
||||||
Example implementation for MyEventListenerProviderFactory from previous example:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
package org.acme.provider;
|
|
||||||
|
|
||||||
import ...
|
|
||||||
|
|
||||||
public class MyEventListenerProviderFactory implements EventListenerProviderFactory, ServerInfoAwareProviderFactory {
|
|
||||||
|
|
||||||
private List<Event> events;
|
|
||||||
private int max;
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void init(Config.Scope config) {
|
|
||||||
max = config.getInt("max");
|
|
||||||
events = new MaxList(max);
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Map<String, String> getOperationalInfo() {
|
|
||||||
Map<String, String> ret = new LinkedHashMap<>();
|
|
||||||
ret.put("version", "1.0");
|
|
||||||
ret.put("listSizeMax", max + "");
|
|
||||||
ret.put("listSizeCurrent", events.size() + "");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
]]></programlisting>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Registering provider implementations</title>
|
|
||||||
<para>
|
|
||||||
Keycloak can load provider implementations from JBoss Modules or directly from the file-system. Using Modules
|
|
||||||
is recommended as you can control exactly what classes are available to your provider. Any providers loaded
|
|
||||||
from the file-system uses a classloader with the Keycloak classloader as its parent.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Register a provider using Modules</title>
|
|
||||||
<para>
|
|
||||||
To register a provider using Modules first create a module. To do this you can either use the jboss-cli
|
|
||||||
script or manually create a folder inside KEYCLOAK_HOME/modules and add your jar and a <literal>module.xml</literal>.
|
|
||||||
For example to add the event listener sysout example provider using the jboss-cli script execute:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.keycloak.examples.event-sysout --resources=target/event-listener-sysout-example.jar --dependencies=org.keycloak.keycloak-core,org.keycloak.keycloak-server-spi,org.keycloak.keycloak-events-api"
|
|
||||||
]]></programlisting>
|
|
||||||
Or to manually create it start by creating the folder <literal>KEYCLOAK_HOME/modules/org/keycloak/examples/event-sysout/main</literal>.
|
|
||||||
Then copy <literal>event-listener-sysout-example.jar</literal> to this folder and create <literal>module.xml</literal>
|
|
||||||
with the following content:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<module xmlns="urn:jboss:module:1.1" name="org.keycloak.examples.event-sysout">
|
|
||||||
<resources>
|
|
||||||
<resource-root path="event-listener-sysout-example.jar"/>
|
|
||||||
</resources>
|
|
||||||
<dependencies>
|
|
||||||
<module name="org.keycloak.keycloak-core"/>
|
|
||||||
<module name="org.keycloak.keycloak-server-spi"/>
|
|
||||||
</dependencies>
|
|
||||||
</module>
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Once you've created the module you need to register this module with Keycloak. This is done by editing
|
|
||||||
keycloak-server.json and adding it to the providers:
|
|
||||||
<programlisting><![CDATA[{
|
|
||||||
"providers": [
|
|
||||||
...
|
|
||||||
"module:org.keycloak.examples.event-sysout"
|
|
||||||
]
|
|
||||||
}]]></programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Register a provider using file-system</title>
|
|
||||||
<para>
|
|
||||||
To register your provider simply copy the JAR including the ProviderFactory and Provider classes and the
|
|
||||||
provider configuration file to server's root <literal>providers</literal> directory.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You can also define multiple provider class-path if you want to create isolated class-loaders. To do this
|
|
||||||
edit keycloak-server.json and add more classpath entries to the providers array. For example:
|
|
||||||
<programlisting><![CDATA[{
|
|
||||||
"providers": [
|
|
||||||
"classpath:provider1.jar;lib-v1.jar",
|
|
||||||
"classpath:provider2.jar;lib-v2.jar"
|
|
||||||
]
|
|
||||||
}]]></programlisting>
|
|
||||||
The above example will create two separate class-loaders for providers. The classpath entries follow the
|
|
||||||
same syntax as Java classpath, with ';' separating multiple-entries. Wildcard is also supported allowing
|
|
||||||
loading all jars (files with .jar or .JAR extension) in a folder, for example:
|
|
||||||
<programlisting><![CDATA[{
|
|
||||||
"providers": [
|
|
||||||
"classpath:/home/user/providers/*"
|
|
||||||
]
|
|
||||||
}]]></programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Configuring a provider</title>
|
|
||||||
<para>
|
|
||||||
You can pass configuration options to your provider by setting them in <literal>keycloak-server.json</literal>.
|
|
||||||
For example to set the max value for <literal>my-event-listener</literal> add:
|
|
||||||
<programlisting><![CDATA[{
|
|
||||||
"eventsListener": {
|
|
||||||
"my-event-listener": {
|
|
||||||
"max": 100
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]]></programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Disabling a provider</title>
|
|
||||||
<para>
|
|
||||||
You can disable a provider by setting the enabled field for the provider to false in <literal>keycloak-server.json</literal>.
|
|
||||||
For example to disable the Infinispan user cache provider add:
|
|
||||||
<programlisting><![CDATA[{
|
|
||||||
"userCache": {
|
|
||||||
"infinispan" : {
|
|
||||||
"enabled": false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}]]></programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Available SPIs</title>
|
|
||||||
<para>
|
|
||||||
Here's a list of the available SPIs and a brief description. For more details on each SPI refer to
|
|
||||||
individual
|
|
||||||
sections.
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Account</term>
|
|
||||||
<listitem>
|
|
||||||
Provides the account manage console pages. The default implementation uses FreeMarker templates.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Connections Infinispan</term>
|
|
||||||
<listitem>
|
|
||||||
Loads and configures Infinispan connections. The default implementation can load connections
|
|
||||||
from
|
|
||||||
the Infinispan subsystem, or alternatively can be manually configured in keycloak-server.json.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Connections Jpa</term>
|
|
||||||
<listitem>
|
|
||||||
Loads and configures Jpa connections. The default implementation can load datasources
|
|
||||||
from
|
|
||||||
WildFly/EAP, or alternatively can be manually configured in keycloak-server.json.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Connections Jpa Updater</term>
|
|
||||||
<listitem>
|
|
||||||
Updates database schema. The default implementation uses Liquibase.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Connections Mongo</term>
|
|
||||||
<listitem>
|
|
||||||
Loads and configures MongoDB connections. The default implementation is configured in
|
|
||||||
keycloak-server.json.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Email</term>
|
|
||||||
<listitem>
|
|
||||||
Formats and sends email. The default implementation uses FreeMarker templates and JavaMail.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Events Listener</term>
|
|
||||||
<listitem>
|
|
||||||
Listen to user related events for example user login success and failures. Keycloak provides two
|
|
||||||
implementations out of box. One that logs events to the server log and another that can send
|
|
||||||
email
|
|
||||||
notifications to users on certain events.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Events Store</term>
|
|
||||||
<listitem>
|
|
||||||
Store user related events so they can be viewed through the admin console and account management
|
|
||||||
console.
|
|
||||||
Keycloak provides implementations for Relational Databases and MongoDB.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Export</term>
|
|
||||||
<listitem>
|
|
||||||
Exports the Keycloak database. Keycloak provides implementations that export to JSON files
|
|
||||||
either
|
|
||||||
as a single file, multiple files in a directory or a encrypted ZIP archive.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Import</term>
|
|
||||||
<listitem>
|
|
||||||
Imports an exported Keycloak database. Keycloak provides implementations that import from JSON
|
|
||||||
files either
|
|
||||||
as a single file, multiple files in a directory or a encrypted ZIP archive.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Login</term>
|
|
||||||
<listitem>
|
|
||||||
Provides the login pages. The default implementation uses FreeMarker templates.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Login Protocol</term>
|
|
||||||
<listitem>
|
|
||||||
Provides protocols. Keycloak provides implementations of OpenID Connect and SAML 2.0.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Realm</term>
|
|
||||||
<listitem>
|
|
||||||
Provides realm and application meta-data. Keycloak provides implementations for Relational
|
|
||||||
Databases
|
|
||||||
and MongoDB.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Realm Cache</term>
|
|
||||||
<listitem>
|
|
||||||
Caches realm and application meta-data to improve performance. Keycloak provides a basic
|
|
||||||
in-memory
|
|
||||||
cache and a Infinispan cache.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Theme</term>
|
|
||||||
<listitem>
|
|
||||||
Allows creating themes to customize look and feel. Keycloak provides implementations that can
|
|
||||||
load
|
|
||||||
themes from the file-system or classpath.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Timer</term>
|
|
||||||
<listitem>
|
|
||||||
Executes scheduled tasks. Keycloak provides a basic implementation based on java.util.Timer.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>User</term>
|
|
||||||
<listitem>
|
|
||||||
Provides users and role-mappings. Keycloak provides implementations for Relational Databases
|
|
||||||
and MongoDB.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>User Cache</term>
|
|
||||||
<listitem>
|
|
||||||
Caches users and role-mappings to improve performance. Keycloak provides a basic in-memory
|
|
||||||
cache and a Infinispan cache.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>User Federation</term>
|
|
||||||
<listitem>
|
|
||||||
Support syncing users from an external source. Keycloak provides implementations for LDAP and
|
|
||||||
Active Directory.
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>User Sessions</term>
|
|
||||||
<listitem>
|
|
||||||
Provides users session information. Keycloak provides implementations for basic in-memory,
|
|
||||||
Infinispan,
|
|
||||||
Relational Databases and MongoDB
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,419 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="proxy">
|
|
||||||
<title>Keycloak Security Proxy</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Proxy Install and Run</title>
|
|
||||||
<para>Download the keycloak proxy distribution from the Keycloak download pages and unzip it.
|
|
||||||
<programlisting>
|
|
||||||
$ unzip keycloak-proxy-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To run it you must have a proxy config file (which we'll discuss in a moment).
|
|
||||||
<programlisting>
|
|
||||||
$ java -jar bin/launcher.jar [your-config.json]
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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 <literal>proxy.json</literal>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Proxy Configuration</title>
|
|
||||||
<para>
|
|
||||||
Here's an example configuration file.
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
{
|
|
||||||
"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
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Basic Config</title>
|
|
||||||
<para>
|
|
||||||
The basic configuration options for the server are as follows:
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>target-url</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The URL this server is proxying <emphasis>REQUIRED.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>send-access-token</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Boolean flag. If true, this will send the access token via the KEYCLOAK_ACCESS_TOKEN header to the
|
|
||||||
proxied server. <emphasis>OPTIONAL.</emphasis>. Default is false.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>bind-address</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
DNS name or IP address to bind the proxy server's sockets to.
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. The default value is <emphasis>localhost</emphasis>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>http-port</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Port to listen for HTTP requests. If you do not specify this value, then the proxy will
|
|
||||||
not listen for regular HTTP requests.
|
|
||||||
<emphasis>OPTIONAL.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>https-port</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Port to listen for HTTPS requests. If you do not specify this value, then the proxy will
|
|
||||||
not listen for HTTPS requests.
|
|
||||||
<emphasis>OPTIONAL.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>keystore</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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 <literal>classpath:</literal>
|
|
||||||
it will look for this file in the classpath.
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. If you have enabled HTTPS, but have not defined a keystore, the proxy
|
|
||||||
will auto-generate a self-signed certificate and use that.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>buffer-size</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
HTTP server socket buffer size. Usually the default is good enough. <emphasis>OPTIONAL.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>buffers-per-region</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
HTTP server socket buffers per region. Usually the default is good enough. <emphasis>OPTIONAL.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>io-threads</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Number of threads to handle IO. Usually default is good enough. <emphasis>OPTIONAL.</emphasis>.
|
|
||||||
The default is the number of available processors * 2.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>worker-threads</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Number of threads to handle requests. Usually the default is good enough. <emphasis>OPTIONAL.</emphasis>.
|
|
||||||
The default is the number of available processors * 16.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Application Config</title>
|
|
||||||
<para>
|
|
||||||
Next under the <literal>applications</literal> array attribute, you can define one or more applications per host you are proxying.
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>base-path</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The base context root for the application. Must start with '/' <emphasis>REQUIRED.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>error-page</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If the proxy has an error, it will display the target application's error page relative URL <emphasis>OPTIONAL.</emphasis>.
|
|
||||||
This is a relative path to the base-path. In the example above it would be <literal>/customer-portal/error.html</literal>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>adapter-config</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
<emphasis>REQUIRED.</emphasis>. Same configuration as any other keycloak adapter. See <link linkend='adapter-config'>Adapter Config</link>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Constraint Config</title>
|
|
||||||
<para>
|
|
||||||
Next under each application you can define one or more constraints in the <literal>constraints</literal> 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.
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>pattern</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
URL pattern to match relative to the base-path of the application. Must start with '/' <emphasis>REQUIRED.</emphasis>.
|
|
||||||
You may only have one wildcard and it must come at the end of the pattern. Valid <literal>/foo/bar/*</literal> and <literal>/foo/*.txt</literal>
|
|
||||||
Not valid: <literal>/*/foo/*</literal>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>roles-allowed</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Array of strings of roles allowed to access this url pattern. <emphasis>OPTIONAL.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>methods</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Array of strings of HTTP methods that will exclusively match this pattern and HTTP request. <emphasis>OPTIONAL.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>excluded-methods</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Array of strings of HTTP methods that will be ignored when match this pattern. <emphasis>OPTIONAL.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>deny</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Deny all access to this URL pattern. <emphasis>OPTIONAL.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>permit</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Permit all access without requiring authentication or a role mapping. <emphasis>OPTIONAL.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>permit-and-inject</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Permit all access, but inject the headers, if user is already authenticated.<emphasis>OPTIONAL.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>authenticate</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Require authentication for this pattern, but no role mapping. <emphasis>OPTIONAL.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Header Names Config</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>keycloak-subject</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
e.g. MYAPP_USER_ID
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>keycloak-username</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
e.g. MYAPP_USER_NAME
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>keycloak-email</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
e.g. MYAPP_USER_EMAIL
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>keycloak-name</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
e.g. MYAPP_USER_ID
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>keycloak-access-token</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
e.g. MYAPP_ACCESS_TOKEN
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Keycloak Identity Headers</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>KEYCLOAK_SUBJECT</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
User id. Corresponds to JWT <literal>sub</literal> and will be the user id Keycloak uses to store
|
|
||||||
this user.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>KEYCLOAK_USERNAME</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Username. Corresponds to JWT <literal>preferred_username</literal>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>KEYCLOAK_EMAIL</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Email address of user if set.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>KEYCLOAK_NAME</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Full name of user if set.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>KEYCLOAK_ACCESS_TOKEN</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
Header field names can be configured using a map of <literal>header-names</literal> in configuration file:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
{
|
|
||||||
"header-names" {
|
|
||||||
"keycloak-subject": "MY_SUBJECT"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,43 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="recaptcha">
|
|
||||||
<title>Recaptcha Support on Registration</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
To safeguard registration against bots, Keycloak has integration with Google Recaptcha. To enable this you
|
|
||||||
need to first go to <ulink url="https://developers.google.com/recaptcha/">Google Recaptcha</ulink>
|
|
||||||
and create an API key so that you can get your recaptcha site key and secret. (FYI, localhost works by default
|
|
||||||
so you don't have to specify a domain).
|
|
||||||
</para>
|
|
||||||
<para>Next, go to the Keycloak Admin Console. Go to
|
|
||||||
Authentication->Flows page. Select the 'registration' flow. Set the 'Recaptcha' requirement to 'Required'. Click
|
|
||||||
on the 'Configure' button and enter in the Recaptcha site key and secret.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Finally, you have to change Keycloak's default security headers. In the Admin Console, go to Settings->Security Defenses
|
|
||||||
of your realm. Add a space and <literal>https://www.google.com</literal> to the values of both the <literal>X-Frame-Options</literal>
|
|
||||||
and <literal>Content-Security-Policy</literal> headers. i.e.
|
|
||||||
<programlisting>
|
|
||||||
frame-src 'self' https://www.google.com
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
That's it! You may want to edit register.ftl in your login theme to muck around with the placement and styling
|
|
||||||
of the recaptcha button. Up to you.
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,48 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="roles">
|
|
||||||
<title>Roles</title>
|
|
||||||
<para>
|
|
||||||
In Keycloak, roles can be defined globally at the realm level, or individually per application.
|
|
||||||
Each role has a name which must be unique at the level it is defined in, i.e. you can have only one "admin" role at
|
|
||||||
the realm level. You may have that a role named "admin" within an Application too, but "admin" must be unique
|
|
||||||
for that application.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The description of a role is displayed in the OAuth Grant page when Keycloak is processing a browser OAuth
|
|
||||||
Grant request. Look for more features being added here in the future like internationalization and other fine
|
|
||||||
grain options.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Composite Roles</title>
|
|
||||||
<para>
|
|
||||||
Any realm or application level role can be turned into a Composite Role. A Composite Role is a role that has
|
|
||||||
one or more additional roles associated with it. I guess another term for it could be Role Group.
|
|
||||||
When a composite role is mapped to the user, the user gains the permission of that role, plus any other role the
|
|
||||||
composite is associated with. This association is dynamic. So, if you add or remove an associated role from
|
|
||||||
the composite, then all users that are mapped to the composite role will automatically have those permissions
|
|
||||||
added or removed. Composites can also be used to define Client scopes.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Composite roles can be associated with any type of role Realm or Application. In the admin console simple
|
|
||||||
flip the composite switch in the Role detail, and you will get a screen that will allow you to associate roles
|
|
||||||
with the composite.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,355 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="saml">
|
|
||||||
<title>SAML SSO</title>
|
|
||||||
<para>
|
|
||||||
Keycloak supports SAML 2.0 for registered applications. Both POST and Redirect bindings are supported. You can
|
|
||||||
choose
|
|
||||||
to require client signature validation and can have the server sign and/or encrypt responses as well. We do not
|
|
||||||
yet support logout via redirects. All logouts happen via a background POST binding request to the application
|
|
||||||
that will be logged out. We do not support SAML 1.1 either. If you want support for either of those, please
|
|
||||||
log a JIRA request and we'll schedule it.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
When you create an application in the admin console, you can choose which protocol the application will log in
|
|
||||||
with.
|
|
||||||
In the application create screen, choose
|
|
||||||
<literal>saml</literal>
|
|
||||||
from the protocol list. After that there
|
|
||||||
are a bunch of configuration options. Here is a description of each item:
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Client ID</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This value must match the issuer value sent with AuthNRequests. Keycloak will pull the issuer
|
|
||||||
from the Authn SAML request and match it to a client by this value.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Include AuthnStatement</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
SAML login responses may specify the authentication method used (password, etc.) as well as
|
|
||||||
a timestamp of the login. Setting this to on will include that statement in the response
|
|
||||||
document.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Multi-valued Roles</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If this switch is off, any user role mappings will have a corresponding attribute created for
|
|
||||||
it.
|
|
||||||
If this switch is turn on, only one role attribute will be created, but it will have
|
|
||||||
multiple values within in.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Sign Documents</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
When turned on, Keycloak will sign the document using the realm's private key.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Sign Assertions</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
With the
|
|
||||||
<literal>Sign Documents</literal>
|
|
||||||
switch signs the whole document. With this setting
|
|
||||||
you just assign the assertions of the document.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Signature Algorithm</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Choose between a variety of algorithms for signing SAML documents.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Encrypt Assertions</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Encrypt assertions in SAML documents with the realm's private key. The AES algorithm is used
|
|
||||||
with a key size of 128 bits.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Client Signature Required</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Expect that documents coming from a client are signed. Keycloak will validate this signature
|
|
||||||
using the client keys set up in the
|
|
||||||
<literal>Application Keys</literal>
|
|
||||||
submenu item.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Force POST Binding</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
By default, Keycloak will respond using the initial SAML binding of the original request. By
|
|
||||||
turning
|
|
||||||
on this switch, you will force Keycloak to always respond using the SAML POST Binding even if
|
|
||||||
the
|
|
||||||
original request was the Redirect binding.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Front Channel Logout</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If true, this application requires a browser redirect to be able to perform a logout. For
|
|
||||||
example,
|
|
||||||
the application may require a cookie to be reset which could only be done by a done via a
|
|
||||||
redirect.
|
|
||||||
If this switch is false, then Keycloak will invoke a background SAML request to logout the
|
|
||||||
application.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Force Name ID Format</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If the request has a name ID policy, ignore it and used the value configured in the admin
|
|
||||||
console
|
|
||||||
under Name ID Format
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Name ID Format</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Name ID Format for the subject. If no name ID policy is specified in the request or if the
|
|
||||||
Force Name ID Format attribute is true, this value is used. Properties used for each of the
|
|
||||||
respective formats are defined below.
|
|
||||||
</para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>username</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Format:
|
|
||||||
<literal>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</literal>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Source:
|
|
||||||
<literal>UserModel.userName</literal>
|
|
||||||
property
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>email</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Format:
|
|
||||||
<literal>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</literal>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Source:
|
|
||||||
<literal>UserModel.email</literal>
|
|
||||||
property
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>transient</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Format:
|
|
||||||
<literal>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</literal>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Source:<literal>G-$randomUuid</literal>, I.E.
|
|
||||||
<literal>G-5ef5b38f-864f-41ad-82a0-04ade9139500</literal>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>persistent</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Format:
|
|
||||||
<literal>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</literal>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The persistent identifier will be evaluated in the following order. If one step
|
|
||||||
does not yield a value, processing will continue on to the next until a value is
|
|
||||||
found.
|
|
||||||
</para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
1) saml.persistent.name.id.for.$clientId
|
|
||||||
<literal>UserModel</literal> attribute
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
identifier unique to this client/user pair.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
2) saml.persistent.name.id.for.*
|
|
||||||
<literal>UserModel</literal> attribute
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
user identifier for all clients, unless otherwise overridden by a
|
|
||||||
$clientId attribute.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>
|
|
||||||
3) G-$randomUuid
|
|
||||||
</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
I.E.<literal>G-5ef5b38f-864f-41ad-82a0-04ade9139500</literal>. If
|
|
||||||
neither a $clientId or wildcard user attribute is found, a persistent
|
|
||||||
identifier will be generated for the given client. Note that once this
|
|
||||||
identifier has been generated, a user attribute with the key
|
|
||||||
<emphasis>saml.persistent.name.id.for.$clientId</emphasis>
|
|
||||||
will be persisted and used on all subsequent requests against the given
|
|
||||||
client.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Master SAML Processing URL</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This URL will be used for all SAML requests and responsed directed to the SP. It will be used
|
|
||||||
as the Assertion Consumer Service URL and the Single Logout Service URL. If a login request
|
|
||||||
contains the Assertion Consumer Service URL, that will take precedence, but this URL must be
|
|
||||||
valided
|
|
||||||
by a registered Valid Redirect URI pattern
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Assertion Consumer Service POST Binding URL</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
POST Binding URL for the Assertion Consumer Service.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Assertion Consumer Service Redirect Binding URL</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Redirect Binding URL for the Assertion Consumer Service.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Logout Service POST Binding URL</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
POST Binding URL for the Logout Service.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Logout Service Redirect Binding URL</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Redirect Binding URL for the Logout Service.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For login to work, Keycloak needs to be able to resolve the URL for the Assertion Consumer Service of the SP. If
|
|
||||||
you are relying on the SP to provide this URL in the login request, then you must register valid redirect uri
|
|
||||||
patterns
|
|
||||||
so that this URL can be validated. You can set the Master SAML Processing URL as well, or alternatively, you can
|
|
||||||
specify the Assertion Consumer Service URL per binding.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For logout to work, you must specify a Master SAML Processing URL, or the Loging Service URL for the binding
|
|
||||||
you want Keycloak to use.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
One thing to note is that roles are not treated as a hierarchy. So, any role mappings will just be added
|
|
||||||
to the role attributes in the SAML document using their basic name. So, if you have multiple application roles
|
|
||||||
you might have name collisions. You can use the Scope Mapping menu item to control which role mappings are set
|
|
||||||
in the response.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>SAML Entity Descriptor</title>
|
|
||||||
<para>
|
|
||||||
If you go into the admin console in the application list menu page you will see an
|
|
||||||
<literal>Import</literal>
|
|
||||||
button. If you click on that you can import SAML Service Provider definitions using the
|
|
||||||
<ulink url="http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf">Entity Descriptor
|
|
||||||
</ulink>
|
|
||||||
format described in SAML 2.0. You should review all the information there to make sure everything is set up
|
|
||||||
correctly.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Each realm has a URL where you can view the XML entity descriptor for the IDP.
|
|
||||||
<literal>root/auth/realms/{realm}/protocol/saml/descriptor</literal>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>IDP Initiated Login</title>
|
|
||||||
<para>
|
|
||||||
IDP Initiated Login is a feature that where you can set up a URL on the Keycloak server that will log you
|
|
||||||
into a specific application/client. To set this up
|
|
||||||
go to the client page in the admin console of the client you want to set this up for. Specify the<literal>
|
|
||||||
IDP Initiated SSO URL Name</literal>. This is a simple string
|
|
||||||
with no whitespace in it. After this you can reference your client at the following URL:
|
|
||||||
<literal>root/auth/realms/{realm}/protocol/saml/clients/{url-name}</literal>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If your client requires a special relay state, you can also configure this in the admin console.
|
|
||||||
Alternatively, you can specify the relay state in a
|
|
||||||
<literal>RelayState</literal>
|
|
||||||
query parameter, i.e. :
|
|
||||||
<literal>root/auth/realms/{realm}/protocol/saml/clients/{url-name}?RelayState=thestate</literal>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,194 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="security_vulnerabilities">
|
|
||||||
<title>Security Vulnerabilities</title>
|
|
||||||
<para>
|
|
||||||
This chapter discusses possible security vulnerabilities Keycloak could have, how Keycloak mitigates those
|
|
||||||
vulnerabilities, and what steps you need to do to configure Keycloak to mitigate some vulnerabilities. A good list
|
|
||||||
of potential vulnerabilities and what security implementations should do to mitigate them can be found in the
|
|
||||||
<ulink url="http://tools.ietf.org/html/rfc6819">OAuth 2.0 Threat Model</ulink> document put out by the IETF. Many of those vulnerabilities are discussed here.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>SSL/HTTPS Requirement</title>
|
|
||||||
<para>
|
|
||||||
If you do not use SSL/HTTPS for all communication between the Keycloak auth server and the clients it secures
|
|
||||||
you will be very vulnerable to man in the middle attacks. OAuth 2.0/OpenID Connect uses access tokens for
|
|
||||||
security. Without SSL/HTTPS, attackers can sniff your network and obtain an access token. Once they have an
|
|
||||||
access token they can do any operation that the token has been given permission for.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Keycloak has <link linkend="ssl_modes">three modes for SSL/HTTPS</link>. SSL can be hard to set up, so out of the box, Keycloak allows
|
|
||||||
non-HTTPS communication over private IP addresses like localhost, 192.168.x.x, and other private IP addresses.
|
|
||||||
In production, you should make sure SSL is enabled and required across the board.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
On the adapter/client side, Keycloak allows you to turn off the SSL trust manager. The trust manager ensures
|
|
||||||
identity the client is talking to. It checks the DNS domain name against the server's certificate. In production
|
|
||||||
you should make sure that each of your client adapters is configured to use a truststore. Otherwise you are vulnerable
|
|
||||||
to DNS man in the middle attacks.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>CSRF Attacks</title>
|
|
||||||
<para>
|
|
||||||
Cross-site request forgery (CSRF) is a web-based attack whereby HTTP
|
|
||||||
requests are transmitted from a user that the web site trusts or has
|
|
||||||
authenticated (e.g., via HTTP redirects or HTML forms). Any site that uses
|
|
||||||
cookie based authentication is vulnerable for these types of attacks. These attacks are mitigated
|
|
||||||
by matching a state cookie against a posted form or query parameter.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
OAuth 2.0 login specification requires that a state cookie be used and matched against a transmitted state
|
|
||||||
parameter. Keycloak fully implements this part of the specification so all logins are protected.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The Keycloak adminstration console is a pure Javascript/HTML5 application that makes REST calls to the
|
|
||||||
backend Keycloak admin API. These calls all require bearer token authentication and are made via Javascript
|
|
||||||
Ajax calls. CSRF does not apply here. The admin REST API can also be configured to validate CORS origins
|
|
||||||
as well.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The only part of Keycloak that really falls into CSRF is the user account management pages. To mitigate this
|
|
||||||
Keycloak sets a state cookie and also embeds the value of this state cookie within hidden form fields or
|
|
||||||
query parameters in action links. This query or form parameter is checked against the state cookie to verify
|
|
||||||
that the call was made by the user.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Clickjacking</title>
|
|
||||||
<para>
|
|
||||||
With clickjacking, a malicious site loads the target site in a
|
|
||||||
transparent iFrame overlaid on top of a set of dummy
|
|
||||||
buttons that are carefully constructed to be placed directly under
|
|
||||||
important buttons on the target site. When a user clicks a visible
|
|
||||||
button, they are actually clicking a button (such as an "Authorize"
|
|
||||||
button) on the hidden page. An attacker can steal a user's authentication credentials and
|
|
||||||
access their resources.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
By default, every response by Keycloak sets some specific browser headers that can prevent this from happening
|
|
||||||
specifically <ulink url="http://tools.ietf.org/html/rfc7034">X-FRAME_OPTIONS</ulink> and <ulink url="http://www.w3.org/TR/CSP/">Content-Security-Policy</ulink>. You
|
|
||||||
should take a look at both of these headers. In the admin console you can specify the values these headers will
|
|
||||||
have. By default, Keycloak only sets up a same-origin policy for iframes.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Compromised Access Codes</title>
|
|
||||||
<para>
|
|
||||||
It would be very hard for an attacker to compromise Keycloak access codes. Keycloak generates a cryptographically
|
|
||||||
strong random value for its access codes so it would be very hard to guess an access token.
|
|
||||||
An access code can only be turned into an access token once so it can't be replayed. In the admin console
|
|
||||||
you can specify how long an access token is valid for. This value should be really short. Like a seconds.
|
|
||||||
Just long enough for the client to make the request to turn the code into an token.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Compromised access and refresh tokens</title>
|
|
||||||
<para>
|
|
||||||
There's a few things you can do to mitigate access tokens and refresh tokens from being stolen.
|
|
||||||
Most importantly is to enforce SSL/HTTPS communication between Keycloak and its clients and applications.
|
|
||||||
Short lifespans (minutes) for access tokens allows Keycloak to check the validity of a refresh token. Making
|
|
||||||
sure refresh tokens always stay private to the client and are never transmitted ever is very important as well.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If an access token or refresh token is compromised, the first thing you should do is go to the admin console
|
|
||||||
and push a not-before revocation policy to all applications. This will enforce that any tokens issued
|
|
||||||
prior to that date are now invalid. You can also disable specific applications, clients, and users if you
|
|
||||||
feel that any one of those entities is completely compromised.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Open redirectors</title>
|
|
||||||
<para>
|
|
||||||
An attacker could use the end-user authorization endpoint and the
|
|
||||||
redirect URI parameter to abuse the authorization server as an open
|
|
||||||
redirector. An open redirector is an endpoint using a parameter to
|
|
||||||
automatically redirect a user agent to the location specified by the
|
|
||||||
parameter value without any validation. An attacker could utilize a user's trust in an authorization
|
|
||||||
server to launch a phishing attack.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Keycloak requires that all registered applications and clients register at least one redirection uri pattern.
|
|
||||||
Any time a client asks Keycloak to perform a redirect (on login or logout for example), Keycloak will
|
|
||||||
check the redirect uri vs. the list of valid registered uri patterns. It is important that clients and
|
|
||||||
applications register as specific a URI pattern as possible to mitigate open redirector attacks.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="brute-force-attacks">
|
|
||||||
<title>Password guess: brute force attacks</title>
|
|
||||||
<para>
|
|
||||||
A brute force attack happens when an attacker is trying to guess a user's password. Keycloak has some
|
|
||||||
limited brute force detection capabilities. If turned on, a user account will be temporarily disabled
|
|
||||||
if a threshold of login failures is reached. The downside of this is that this makes Keycloak vulnerable
|
|
||||||
to denial of service attacks. Eventually we will expand this functionality to take client IP address into
|
|
||||||
account when deciding whether to block a user.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Another thing you can do to prevent password guessing is to point a tool like <ulink url="http://fail2ban.org">Fail2Ban</ulink> to the Keycloak
|
|
||||||
server's log file. Keycloak logs every login failure and client IP address that had the failure.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In the admin console, per realm, you can set up a password policy to enforce that users pick hard to guess passwords.
|
|
||||||
A password has to match all policies. The password policies that can be configured are hash iterations, length, digits,
|
|
||||||
lowercase, uppercase, special characters, not username, regex patterns, password history and force expired password update.
|
|
||||||
Force expired password update policy forces or requires password updates after specified span of time. Password history policy
|
|
||||||
restricts a user from resetting his password to N old expired passwords. Multiple regex patterns can be specified.
|
|
||||||
If there's more than one regex added, password has to match all fully.
|
|
||||||
Increasing number of Hash Iterations (n) does not worsen anything (and certainly not the cipher) and it greatly increases the
|
|
||||||
resistance to dictionary attacks. However the drawback to increasing n is that it has some cost (CPU usage, energy, delay) for
|
|
||||||
the legitimate parties. Increasing n also slightly increases the odds that a random password gives the same result as the right
|
|
||||||
password due to hash collisions, and is thus a false but accepted password; however that remains very unlikely, in the order of
|
|
||||||
n*[1/(2^256)] for practical values of n, and can be entirely ignored in practice. Keycloak also uses PBKDF2 internally to
|
|
||||||
cryptographically derive passwords to refine and improve the ratio of cost between attacker and legitimate parties.
|
|
||||||
Good practice is to pay attention to the time complexity of hash_password and hash; then increase n as much as tolerable in
|
|
||||||
the situation(s) at hand and and revise parameters such as n every few years to account for time complexity trade off.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Finally, the best way to mitigate against brute force attacks is to require user to set up a one-time-password (OTP).
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Password database compromised</title>
|
|
||||||
<para>
|
|
||||||
Keycloak does not store passwords in raw text. It stores a hash of them. Because of performance reasons,
|
|
||||||
Keycloak only hashes passwords once. While a human could probably never crack a hashed password, it is very
|
|
||||||
possible that a computer could. The security community suggests around 20,000 (yes thousand!) hashing iterations
|
|
||||||
to be done to each password. This number grows every year due to increasing computing power (It was 1000 12 years ago).
|
|
||||||
The problem with this is that password hashing is a huge performance hit as each login would require the entered
|
|
||||||
password to be hashed that many times and compared to the stored hash. So, its up to the admin to configure the
|
|
||||||
password hash iterations. This can be done in the admin console password policy configuration. Again, the default
|
|
||||||
value is 1 as we thought it might be more important for Keycloak to scale out of the box. There's a lot of
|
|
||||||
other measures admins can do to protect their password databases.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>SQL Injection attacks</title>
|
|
||||||
<para>
|
|
||||||
At this point in time, there is no knowledge of any SQL injection vulnerabilities in Keycloak
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Limiting Scope</title>
|
|
||||||
<para>
|
|
||||||
Using the <literal>Scope</literal> menu in the admin console for clients, you can control
|
|
||||||
exactly which role mappings will be included within the token sent back to the client application. This
|
|
||||||
allows you to limit the scope of permissions given to the client which is great if the client isn't
|
|
||||||
very trusted and is known to not being very careful with its tokens.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,75 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="service-accounts">
|
|
||||||
<title>Service Accounts</title>
|
|
||||||
<para>
|
|
||||||
Keycloak allows you to obtain an access token dedicated to some Client Application (not to any user).
|
|
||||||
See <ulink url="http://tools.ietf.org/html/rfc6749#section-4.4">Client Credentials Grant</ulink>
|
|
||||||
from OAuth 2.0 spec.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To use it you must have
|
|
||||||
registered a valid confidential Client and you need to check the switch <literal>Service Accounts Enabled</literal> in Keycloak
|
|
||||||
admin console for this client. In tab <literal>Service Account Roles</literal> you can configure the roles available to the service account retrieved on behalf of this client.
|
|
||||||
Don't forget that you need those roles to be available in Scopes of this client as well (unless you have <literal>Full Scope Allowed</literal> on).
|
|
||||||
As in normal login, roles from access token are intersection of scopes and the service account roles.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The REST URL to invoke on is <literal>/{keycloak-root}/realms/{realm-name}/protocol/openid-connect/token</literal>.
|
|
||||||
Invoking on this URL is a POST request and requires you to post the client credentials. By default, client credentials are
|
|
||||||
represented by clientId and clientSecret of the client in <literal>Authorization: Basic</literal> header, but you can also
|
|
||||||
authenticate client with signed JWT assertion or any other custom mechanism for client authentication. See
|
|
||||||
<link linkend="client_authentication">Client Authentication</link> section for more details. You also need to use parameter <literal>grant_type=client_credentials</literal> as per OAuth2 specification.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For example the POST invocation to retrieve service account can look like this:
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
POST /auth/realms/demo/protocol/openid-connect/token
|
|
||||||
Authorization: Basic cHJvZHVjdC1zYS1jbGllbnQ6cGFzc3dvcmQ=
|
|
||||||
Content-Type: application/x-www-form-urlencoded
|
|
||||||
|
|
||||||
grant_type=client_credentials]]>
|
|
||||||
</programlisting>
|
|
||||||
The response would be this <ulink url="http://tools.ietf.org/html/rfc6749#section-4.4.3">standard JSON document</ulink> from the OAuth 2.0 specification.
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
HTTP/1.1 200 OK
|
|
||||||
Content-Type: application/json;charset=UTF-8
|
|
||||||
Cache-Control: no-store
|
|
||||||
Pragma: no-cache
|
|
||||||
|
|
||||||
{
|
|
||||||
"access_token":"2YotnFZFEjr1zCsicMWpAA",
|
|
||||||
"token_type":"bearer",
|
|
||||||
"expires_in":60,
|
|
||||||
"refresh_token":"tGzv3JOkF0XG5Qx2TlKWIA",
|
|
||||||
"refresh_expires_in":600,
|
|
||||||
"id_token":"tGzv3JOkF0XG5Qx2TlKWIA",
|
|
||||||
"not-before-policy":0,
|
|
||||||
"session_state":"234234-234234-234234"
|
|
||||||
}]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The retrieved access token can be refreshed or logged out by out-of-bound request.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
See the example application <literal>service-account</literal>
|
|
||||||
from the main Keycloak <literal>demo</literal> example.
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,77 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Java Servlet Filter Adapter</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<warning>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
</warning>
|
|
||||||
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
If you notice above, there are two url-patterns. <literal>/protected/*</literal> are just the files we want protected.
|
|
||||||
<literal>/keycloak/*</literal> 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 <literal>http[s]://hostname/{context-root}/keycloak</literal>. There is an example of this in the distribution.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To use this filter, include this maven artifact in your WAR poms
|
|
||||||
</para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-servlet-filter-adapter</artifactId>
|
|
||||||
<version>&project.version;</version>
|
|
||||||
</dependency>
|
|
||||||
]]></programlisting>
|
|
||||||
</section>
|
|
|
@ -1,60 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="social-config">
|
|
||||||
<title>Social Login Config</title>
|
|
||||||
<para>
|
|
||||||
To enable log in with a social network you need to enable social login for your realm and configure one or more
|
|
||||||
social providers.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Enable social login</title>
|
|
||||||
<para>
|
|
||||||
To configure social login, open the <literal>Keycloak Admin Console</literal>, select your realm from the
|
|
||||||
drop-down box in the top left corner. In the <literal>Login Options</literal> section click on
|
|
||||||
<literal>Social login</literal> to set it to <literal>ON</literal>. Click save settings, then click on
|
|
||||||
<literal>Social</literal> in the menu at the top.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To enable a social provider select the provider you want from the drop-down and click on
|
|
||||||
<literal>Add Provider</literal>. Then continue to the section below that provides specific instructions for
|
|
||||||
the provider you are adding.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Social-only login</title>
|
|
||||||
<para>
|
|
||||||
It's possible to configure a realm to only allow social login. To do this open the <literal>Keycloak Admin Console</literal>,
|
|
||||||
select your realm from the drop-down box in the top left corner. Click the <literal>Credentials</literal> tab, and
|
|
||||||
click on the <literal>x</literal> next to <literal>password</literal> in the <literal>Required User Credentials</literal>.
|
|
||||||
This will disable login with username and password.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="social-callbackurl">
|
|
||||||
<title>Social Callback URL</title>
|
|
||||||
<para>
|
|
||||||
There is a single callback url used by all realms and social providers. This makes it possible to share
|
|
||||||
the configuration for a social network between multiple realms. An example callback url is
|
|
||||||
<literal>http://localhost:8080/auth/rest/social/callback</literal>. To get the callback url for your server
|
|
||||||
replace <literal>http://localhost:8080</literal> with the base address of your server. You can also
|
|
||||||
find the callback url in the Keycloak Admin Console under social settings.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
|
@ -1,62 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="social-facebook">
|
|
||||||
<title>Facebook</title>
|
|
||||||
<para>
|
|
||||||
To enable login with Facebook you first have to create an app in the
|
|
||||||
<ulink url="https://developers.facebook.com/">Facebook Developer Console</ulink>. Then you need to copy
|
|
||||||
the client id and secret into the Keycloak Admin Console.
|
|
||||||
</para>
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Log in to the <ulink url="https://developers.facebook.com/">Facebook Developer Console</ulink>. Click
|
|
||||||
<literal>Apps</literal> in the menu and select <literal>Create a New App</literal>. Use any value for
|
|
||||||
<literal>Display Name</literal> and <literal>Category</literal> you want, then click the
|
|
||||||
<literal>Create App</literal> button. Wait for the project to be created (this may take a while). If after
|
|
||||||
creating the app you are not redirected to the app settings, click on <literal>Apps</literal> in the
|
|
||||||
menu and select the app you created.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Once the app has been created click on <literal>Settings</literal> in sidebar on the left. You must specify
|
|
||||||
a contact email. Save your changes. Then click
|
|
||||||
on <literal>Advanced</literal>. Under <literal>Security</literal> make sure
|
|
||||||
<literal>Client OAuth Login</literal> is enabled. In <literal>Valid OAuth redirect URIs</literal> insert
|
|
||||||
the <link linkend="social-callbackurl">social callback url</link>. Scroll down and click on the
|
|
||||||
<literal>Save Changes</literal> button.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Click <literal>Status & Review</literal> and select <literal>YES</literal> for <literal>Do you want
|
|
||||||
to make this app and all its live features available to the general public?</literal>. You will
|
|
||||||
not be able to set this until you have provided a contact email in the general settings of this application.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Click <literal>Basic</literal>. Copy <literal>App ID</literal> and <literal>App Secret</literal>
|
|
||||||
(click <literal>show</literal>) from the <ulink url="https://developers.facebook.com/">Facebook Developer Console</ulink> into the
|
|
||||||
settings page in the Keycloak Admin Console as the <literal>Key</literal> and <literal>Secret</literal>. Then
|
|
||||||
click <literal>Save</literal> in the Keycloak Admin Console to enable login with Facebook.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</section>
|
|
|
@ -1,44 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="social-github">
|
|
||||||
<title>GitHub</title>
|
|
||||||
<para>
|
|
||||||
To enable login with GitHub you first have to create an application in
|
|
||||||
<link xlink:href="https://github.com/settings/applications">GitHub Settings</link>. Then you need to copy
|
|
||||||
the client id and secret into the Keycloak Admin Console.
|
|
||||||
</para>
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Log in to <link xlink:href="https://github.com/settings/applications">GitHub Settings</link>. Click the
|
|
||||||
<literal>Register new application</literal> button. Use any value for <literal>Application name</literal>,
|
|
||||||
<literal>Homepage URL</literal> and <literal>Application Description</literal> you want. In <literal>Authorization callback URL</literal>
|
|
||||||
enter the <link linkend="social-callbackurl">social callback url</link> for your realm. Click the
|
|
||||||
<literal>Register application</literal> button.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Copy <literal>Client ID</literal> and <literal>Client secret</literal> from the
|
|
||||||
<link xlink:href="https://github.com/settings/applications">GitHub Settings</link> into the settings
|
|
||||||
page in the Keycloak Admin Console as the <literal>Key</literal> and <literal>Secret</literal>. Then click
|
|
||||||
<literal>Save</literal> in the Keycloak Admin Console to enable login with GitHub.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</section>
|
|
|
@ -1,67 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="social-google">
|
|
||||||
<title>Google</title>
|
|
||||||
<para>
|
|
||||||
To enable login with Google you first have to create a project and a client in the
|
|
||||||
<ulink url="https://cloud.google.com/console/project">Google Developer Console</ulink>. Then you need to copy
|
|
||||||
the client id and secret into the Keycloak Admin Console.
|
|
||||||
</para>
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Log in to the <ulink url="https://cloud.google.com/console/project">Google Developer Console</ulink>. Click the
|
|
||||||
<literal>Create Project</literal> button. Use any value for <literal>Project name</literal> and
|
|
||||||
<literal>Project ID</literal> you want, then click the <literal>Create</literal> button. Wait for the project to
|
|
||||||
be created (this may take a while).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Once the project has been created click on <literal>APIs & auth</literal> in sidebar on the left. To retrieve
|
|
||||||
user profiles the <literal>Google+ API</literal> has to be enabled. Scroll down to find it in the list. If its
|
|
||||||
status is <literal>OFF</literal>, click on <literal>OFF</literal> to enable it (it should move to the top of
|
|
||||||
the list and the status should be <literal>ON</literal>).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Now click on the <literal>Consent screen</literal> link on the sidebar menu on the left. You must specify
|
|
||||||
a project name and choose an email for the consent screen. Otherwise users will get a login error. There's
|
|
||||||
other things you can configure here like what the consent screen looks like. Feel free to play around with this.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Now click <literal>Credentials</literal> in the sidebar on the left. Then click
|
|
||||||
<literal>Create New Client ID</literal>. Select <literal>Web application</literal> as
|
|
||||||
<literal>Application type</literal>. Empty the <literal>Authorized Javascript origins</literal> textarea. In
|
|
||||||
<literal>Authorized redirect URI</literal> enter the <link linkend="social-callbackurl">social callback url</link>
|
|
||||||
for your realm. Click the <literal>Create Client ID</literal> button.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Copy <literal>Client ID</literal> and <literal>Client secret</literal> from the
|
|
||||||
<ulink url="https://cloud.google.com/console/project">Google Developer Console</ulink> into the settings
|
|
||||||
page in the Keycloak Admin Console as the <literal>Key</literal> and <literal>Secret</literal>. Then click
|
|
||||||
<literal>Save</literal> in the Keycloak Admin Console to enable login with Google.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
</section>
|
|
|
@ -1,29 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="social-spi">
|
|
||||||
<title>Social Provider SPI</title>
|
|
||||||
<para>
|
|
||||||
Keycloak provides an SPI to make it easy to add additional social providers. This is done by implementing
|
|
||||||
<literal>org.keycloak.social.SocialProvider</literal> in <literal>social/core</literal>
|
|
||||||
and adding a provider configuration file (<literal>META-INF/services/org.keycloak.social.SocialProvider</literal>).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
A good reference for implementing a Social Provider is the Google provider which you can find in <literal>social/google</literal>
|
|
||||||
on GitHub or in the source download.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
|
@ -1,55 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="social-twitter">
|
|
||||||
<title>Twitter</title>
|
|
||||||
<para>
|
|
||||||
To enable login with Twtter you first have to create an application in the
|
|
||||||
<link xlink:href="https://dev.twitter.com/apps">Twitter Developer Console</link>. Then you need to copy
|
|
||||||
the consumer key and secret into the Keycloak Admin Console.
|
|
||||||
</para>
|
|
||||||
<orderedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Log in to the <link xlink:href="https://dev.twitter.com/apps">Twitter Developer Console</link>. Click the
|
|
||||||
<literal>Create a new application</literal> button. Use any value for <literal>Name</literal>,
|
|
||||||
<literal>Description</literal> and <literal>Website</literal> you want. Insert the social callback url
|
|
||||||
in <literal>Callback URL</literal>. Then click <literal>Create your Twitter application</literal>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Now click on <literal>Settings</literal> and tick the box <literal>Allow this application to be used to Sign in with Twitter</literal>,
|
|
||||||
then click on <literal>Update this Twitter application's settings</literal>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Now click <literal>API Keys</literal> tab. Copy <literal>API key</literal> and <literal>API secret</literal> from the
|
|
||||||
<link xlink:href="https://dev.twitter.com/apps">Twitter Developer Console</link> into the settings
|
|
||||||
page in the Keycloak Admin Console as the <literal>Key</literal> and <literal>Secret</literal>. Then click
|
|
||||||
<literal>Save</literal> in the Keycloak Admin Console to enable login with Twitter.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</orderedlist>
|
|
||||||
<tip>
|
|
||||||
<para>
|
|
||||||
Twitter doesn't allow <literal>localhost</literal> in the redirect URI. To test on a local server
|
|
||||||
replace <literal>localhost</literal> with <literal>127.0.0.1</literal>.
|
|
||||||
</para>
|
|
||||||
</tip>
|
|
||||||
</section>
|
|
|
@ -1,89 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="spring-boot-adapter">
|
|
||||||
<title>Spring Boot Adapter</title>
|
|
||||||
<para>
|
|
||||||
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 (<literal>application.properties</literal>). Let's go over these steps.
|
|
||||||
</para>
|
|
||||||
<section id="spring-boot-adapter-installation">
|
|
||||||
<title>Adapter Installation</title>
|
|
||||||
<para>
|
|
||||||
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):
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="spring-boot-adapter-configuration">
|
|
||||||
<title>Required Spring Boot Adapter Configuration</title>
|
|
||||||
<para>
|
|
||||||
This section describes how to configure your Spring Boot app to use Keycloak.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Instead of a <literal>keycloak.json</literal> file, you configure the realm for the Spring
|
|
||||||
Boot Keycloak adapter via the normal Spring Boot configuration. For example:
|
|
||||||
</para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
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
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
You also need to specify the J2EE security config that would normally go in the <literal>web.xml</literal>.
|
|
||||||
Here's an example configuration:
|
|
||||||
</para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
keycloak.securityConstraints[0].securityCollections[0].name = insecure stuff
|
|
||||||
keycloak.securityConstraints[0].securityCollections[0].authRoles[0] = admin
|
|
||||||
keycloak.securityConstraints[0].securityCollections[0].authRoles[1] = 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
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
|
@ -1,312 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="spring-security-adapter">
|
|
||||||
<title>Spring Security Adapter</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Unlike the other Keycloak Adapters, you should not configure your security in web.xml. However, keycloak.json is still required.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Adapter Installation</title>
|
|
||||||
<para>
|
|
||||||
Add Keycloak Spring Security adapter as a dependency to your Maven POM or Gradle build.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-spring-security-adapter</artifactId>
|
|
||||||
<version>&project.version;</version>
|
|
||||||
</dependency>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Spring Security Configuration</title>
|
|
||||||
<para>
|
|
||||||
The Keycloak Spring Security adapter takes advantage of Spring Security's flexible security configuration syntax.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Java Configuration</title>
|
|
||||||
<para>
|
|
||||||
Keycloak provides a KeycloakWebSecurityConfigurerAdapter as a convenient base class for creating a
|
|
||||||
<ulink url="http://docs.spring.io/spring-security/site/docs/4.0.x/apidocs/org/springframework/security/config/annotation/web/WebSecurityConfigurer.html">WebSecurityConfigurer</ulink>
|
|
||||||
instance. The implementation allows customization by overriding methods. While its use is not required, it greatly simplifies your security context configuration.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
@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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You must provide a session authentication strategy bean which should be of type
|
|
||||||
<code>RegisterSessionAuthenticationStrategy</code> for public or confidential applications and
|
|
||||||
<code>NullAuthenticatedSessionStrategy</code> for bearer-only applications.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Spring Security's <code>SessionFixationProtectionStrategy</code> 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.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>XML Configuration</title>
|
|
||||||
<para>
|
|
||||||
While Spring Security's XML namespace simplifies configuration, customizing the configuration can be a bit
|
|
||||||
verbose.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<?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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Multi Tenancy</title>
|
|
||||||
<para>
|
|
||||||
The Keycloak Spring Security adapter also supports multi tenancy. Instead of injecting
|
|
||||||
<literal>AdapterDeploymentContextFactoryBean</literal> with the path to <literal>keycloak.json</literal> you
|
|
||||||
can inject an implementation of the <literal>KeycloakConfigResolver</literal> interface. More details on how
|
|
||||||
to implement the <literal>KeycloakConfigResolver</literal> can be found in <xref linkend="multi_tenancy" />.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Naming Security Roles</title>
|
|
||||||
<para>
|
|
||||||
Spring Security, when using role-based authentication, requires that role names start with <code>ROLE_</code>.
|
|
||||||
For example, an administrator role must be declared in Keycloak as <code>ROLE_ADMIN</code> or similar, not simply
|
|
||||||
<code>ADMIN</code>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The class <code>org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider</code>
|
|
||||||
supports an optional <code>org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper</code>
|
|
||||||
which can be used to map roles coming from Keycloak to roles recognized by Spring Security. Use, for example,
|
|
||||||
<code>org.springframework.security.core.authority.mapping.SimpleAuthorityMapper</code> to insert the
|
|
||||||
<code>ROLE_</code> prefix and convert the role name to upper case. The class is part of Spring Security
|
|
||||||
Core module.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Client to Client Support</title>
|
|
||||||
<para>
|
|
||||||
To simplify communication between clients, Keycloak provides an extension of Spring's <code>RestTemplate</code> that
|
|
||||||
handles bearer token authentication for you. To enable this feature your security configuration must add the
|
|
||||||
<code>KeycloakRestTemplate</code> bean. Note that it must be scoped as a prototype to function correctly.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For Java configuration:
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For XML configuration:
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<bean id="keycloakRestTemplate" class="org.keycloak.adapters.springsecurity.client.KeycloakRestTemplate" scope="prototype">
|
|
||||||
<constructor-arg name="factory" ref="keycloakClientRequestFactory" />
|
|
||||||
</bean>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Your application code can then use <code>KeycloakRestTemplate</code> any time it needs to make a call to another
|
|
||||||
client. For example:
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
|
|
||||||
@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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Spring Boot Configuration</title>
|
|
||||||
<para>
|
|
||||||
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
|
|
||||||
<code>FilterRegistrationBean</code>s to your security configuration to prevent the Keycloak filters from being
|
|
||||||
registered
|
|
||||||
twice.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
@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;
|
|
||||||
}
|
|
||||||
|
|
||||||
...
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
|
@ -1,318 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="themes">
|
|
||||||
<title>Themes</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Keycloak provides theme support for web pages and emails. This allows customizing the look
|
|
||||||
and feel of end-user facing pages so they can be integrated with your applications.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Theme types</title>
|
|
||||||
<para>
|
|
||||||
A theme can support several types to customize different aspects of Keycloak. The types currently available
|
|
||||||
are:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>Account - Account management</listitem>
|
|
||||||
<listitem>Admin - Admin console</listitem>
|
|
||||||
<listitem>Email - Emails</listitem>
|
|
||||||
<listitem>Login - Login forms</listitem>
|
|
||||||
<listitem>Welcome - Welcome pages</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Configure theme</title>
|
|
||||||
<para>
|
|
||||||
All theme types, except welcome, is configured through <literal>Keycloak Admin Console</literal>. To change
|
|
||||||
the theme used for a realm open the <literal>Keycloak Admin Console</literal>, select your realm
|
|
||||||
from the drop-down box in the top left corner. Under <literal>Settings</literal> click on <literal>Theme</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To set the theme for the <literal>master</literal> Keycloak admin console set the admin console theme for
|
|
||||||
the <literal>master</literal> realm. To set the theme for per realm admin access control set the admin console
|
|
||||||
theme for the corresponding realm.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To change the welcome theme you need to edit <literal>standalone/configuration/keycloak-server.json</literal>
|
|
||||||
and add <literal>welcomeTheme</literal> to the theme element, for example:
|
|
||||||
<programlisting>
|
|
||||||
"theme": {
|
|
||||||
...
|
|
||||||
"welcomeTheme": "custom-theme"
|
|
||||||
}
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Default themes</title>
|
|
||||||
<para>
|
|
||||||
Keycloak comes bundled with default themes in the server's root <literal>themes</literal> directory.
|
|
||||||
You should not edit the bundled themes directly. Instead create a new theme that extends a
|
|
||||||
bundled theme.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Creating a theme</title>
|
|
||||||
<para>
|
|
||||||
A theme consists of:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem><ulink url="http://freemarker.org">FreeMarker</ulink> templates</listitem>
|
|
||||||
<listitem>Stylesheets</listitem>
|
|
||||||
<listitem>Scripts</listitem>
|
|
||||||
<listitem>Images</listitem>
|
|
||||||
<listitem>Message bundles</listitem>
|
|
||||||
<listitem>Theme properties</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
A theme can extend another theme. When extending a theme you can override individual files (templates, stylesheets, etc.).
|
|
||||||
The recommended way to create a theme is to extend the base theme. The base theme provides templates
|
|
||||||
and a default message bundle. If you decide to override templates bear in mind that you may need to update
|
|
||||||
your templates when upgrading to a new release to include any changes made to the original template.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Before creating a theme it's a good idea to disable caching as this makes it possible to edit theme resources
|
|
||||||
without restarting the server. To do this open <literal>../standalone/configuration/keycloak-server.json</literal>
|
|
||||||
for <literal>theme</literal> set <literal>staticMaxAge</literal> to <literal>-1</literal> and
|
|
||||||
<literal>cacheTemplates</literal> and <literal>cacheThemes</literal> to <literal>false</literal>. For example:
|
|
||||||
<programlisting>[<![CDATA[
|
|
||||||
"theme": {
|
|
||||||
"default": "keycloak",
|
|
||||||
"staticMaxAge": -1,
|
|
||||||
"cacheTemplates": false,
|
|
||||||
"cacheThemes": false,
|
|
||||||
"folder": {
|
|
||||||
"dir": "${jboss.home.dir}/themes"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
]]></programlisting>
|
|
||||||
Remember to re-enable caching in production as it will significantly impact performance.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To create a new theme create a directory for the theme in the server's root <literal>themes</literal>.
|
|
||||||
The name of the directory should be the name of the theme. For example to create a theme called <literal>example-theme</literal>
|
|
||||||
create the directory <literal>themes/example-theme</literal>. Inside the theme
|
|
||||||
directory you then need to create a directory for each of the types your theme is going to provide. For example
|
|
||||||
to add the login type to the <literal>example-theme</literal> theme create the directory
|
|
||||||
<literal>themes/example-theme/login</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For each type create a file <literal>theme.properties</literal> which allows setting some configuration for
|
|
||||||
the theme, for example what theme it overrides and if it should import any themes. For the above example we
|
|
||||||
want to override the base theme and import common resources from the Keycloak theme. To do this create the
|
|
||||||
file <literal>themes/example-theme/login/theme.properties</literal> with following contents:
|
|
||||||
<programlisting>[<![CDATA[
|
|
||||||
parent=base
|
|
||||||
import=common/keycloak
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You have now created a theme with support for the login type. To check that it works open the admin console.
|
|
||||||
Select your realm and click on <literal>Themes</literal>. For <literal>Login Theme</literal> select
|
|
||||||
<literal>example-theme</literal> and click <literal>Save</literal>. Then open the login page for the realm.
|
|
||||||
You can do this either by login through your application or by opening <literal>http://localhost:8080/realms/<realm name>/account</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To see the effect of changing the parent theme, set <literal>parent=keycloak</literal> in <literal>theme.properties</literal>
|
|
||||||
and refresh the login page. To follow the rest of the documentation set it back to <literal>parent=base</literal>
|
|
||||||
before continuing.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Stylesheets</title>
|
|
||||||
<para>
|
|
||||||
A theme can have one or more stylesheets, to add a stylesheet create a file inside <literal>resources/css</literal>
|
|
||||||
(for example <literal>resources/css/styles.css</literal>) inside your theme folder. Then registering it
|
|
||||||
in <literal>theme.properties</literal> by adding:
|
|
||||||
</para>
|
|
||||||
<programlisting>styles=css/styles.css</programlisting>
|
|
||||||
<para>
|
|
||||||
The <literal>styles</literal> property supports a space separated list so you can add as many
|
|
||||||
as you want. For example:
|
|
||||||
</para>
|
|
||||||
<programlisting>styles=css/styles.css css/more-styles.css</programlisting>
|
|
||||||
For the example-theme above add <literal>example-theme/login/resources/css/styles.css</literal> with the
|
|
||||||
following content:
|
|
||||||
<programlisting>[<![CDATA[
|
|
||||||
#kc-form {
|
|
||||||
background-color: #000;
|
|
||||||
color: #fff;
|
|
||||||
padding: 20px;
|
|
||||||
}]]></programlisting>
|
|
||||||
Then edit <literal>example-theme/login/theme.properties</literal> and add <programlisting>styles=css/styles.css</programlisting>.
|
|
||||||
Refresh the login page to see your changes. It's not pretty, but you can see how easily you can modify the
|
|
||||||
styles for your theme.
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Scripts</title>
|
|
||||||
<para>
|
|
||||||
A theme can have one or more scripts, to add a script create a file inside <literal>resources/js</literal> (for example <literal>resources/js/script.js</literal>)
|
|
||||||
inside your theme folder. Then registering it in <literal>theme.properties</literal> by adding:
|
|
||||||
</para>
|
|
||||||
<programlisting>scripts=js/script.js</programlisting>
|
|
||||||
<para>
|
|
||||||
The <literal>scripts</literal> property supports a space separated list so you can add as many
|
|
||||||
as you want. For example:
|
|
||||||
</para>
|
|
||||||
<programlisting>scripts=js/script.js js/more-script.js</programlisting>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Images</title>
|
|
||||||
<para>
|
|
||||||
To make images available to the theme add them to <literal>resources/img</literal>. They can then be used
|
|
||||||
through stylesheets. For example:
|
|
||||||
</para>
|
|
||||||
<programlisting>body {
|
|
||||||
background-image: url('../img/image.jpg');
|
|
||||||
}</programlisting>
|
|
||||||
<para>
|
|
||||||
Or in templates, for example:
|
|
||||||
</para>
|
|
||||||
<programlisting><img src="${url.resourcesPath}/img/image.jpg"></programlisting>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Messages</title>
|
|
||||||
<para>
|
|
||||||
Text in the templates are loaded from message bundles. A theme that extends another theme will inherit
|
|
||||||
all messages from the parents message bundle, but can override individual messages. For example to replace
|
|
||||||
<literal>Username</literal> on the login form with <literal>Your Username</literal> create the file
|
|
||||||
<literal>messages/messages.properties</literal> inside your theme folder and add the following content:
|
|
||||||
</para>
|
|
||||||
<programlisting>username=Your Username</programlisting>
|
|
||||||
<para>
|
|
||||||
For the admin console, there is a second resource bundle named <literal>admin-messages.properties</literal>.
|
|
||||||
This resource bundle is converted to JSON and shipped to the console to be processed by
|
|
||||||
angular-translate. It is found in the same directory as messages.properties and can be overridden
|
|
||||||
in the same way as described above.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Modifying HTML</title>
|
|
||||||
<para>
|
|
||||||
Keycloak uses <ulink url="http://freemarker.org">Freemarker Templates</ulink> in order to generate HTML.
|
|
||||||
These templates are defined in <literal>.ftl</literal> files and can be overriden from the base theme.
|
|
||||||
Check out the Freemarker website on how to form a template file. To override the login template for the
|
|
||||||
<literal>example-theme</literal> copy <literal>themes/base/login/login.ftl</literal> to
|
|
||||||
<literal>themes/example-theme/login</literal> and open it in an editor. After the first line
|
|
||||||
(<#import ...>) add <literal><h1>HELLO WORLD!</h1></literal> then refresh the page.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Deploying themes</title>
|
|
||||||
<para>
|
|
||||||
Themes can be deployed to Keycloak by copying the theme directory to <literal>themes</literal>
|
|
||||||
or it can be deployed as a module. For a single server or during development just copying the theme is fine, but
|
|
||||||
in a cluster or domain it's recommended to deploy as a module.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To deploy a theme as a module you need to create an jar (it's basically just a zip with jar extension) with
|
|
||||||
the theme resources and a file <literal>META/keycloak-themes.json</literal> that describes the themes contained
|
|
||||||
in the archive. For example <literal>example-theme.jar</literal> with the contents:
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>META-INF/keycloak-themes.json</listitem>
|
|
||||||
<listitem>theme/example-theme/login/theme.properties</listitem>
|
|
||||||
<listitem>theme/example-theme/login/login.ftl</listitem>
|
|
||||||
<listitem>theme/example-theme/login/resources/css/styles.css</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
The contents of META-INF/keycloak-themes.json in this case would be:
|
|
||||||
<programlisting>[<![CDATA[
|
|
||||||
{
|
|
||||||
"themes": [{
|
|
||||||
"name" : "example-theme",
|
|
||||||
"types": [ "login" ]
|
|
||||||
}]
|
|
||||||
}
|
|
||||||
]]></programlisting>
|
|
||||||
As you can see a single jar can contain multiple themes and each theme can support one or more types.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The deploy the jar as a module to Keycloak you can either manually create the module or use <literal>jboss-cli</literal>.
|
|
||||||
It's simplest to use <literal>jboss-cli</literal> as it creates the required directories and module descriptor
|
|
||||||
for you. To deploy the above jar <literal>jboss-cli</literal> run:
|
|
||||||
<programlisting>[<![CDATA[
|
|
||||||
KEYCLOAK_HOME/bin/jboss-cli.sh --command="module add --name=org.example.exampletheme --resources=example-theme.jar"
|
|
||||||
]]></programlisting>
|
|
||||||
If you're on windows run <programlisting>KEYCLOAK_HOME/bin/jboss-cli.bat</programlisting>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This command creates <literal>modules/org/example/exampletheme/main</literal> containing <literal>example-theme.jar</literal>
|
|
||||||
and <literal>module.xml</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Once you've created the module you need to register it with Keycloak do this by editing
|
|
||||||
<literal>../standalone/configuration/keycloak-server.json</literal> and adding the module to <literal>theme/module/modules</literal>. For example:
|
|
||||||
<programlisting>[<![CDATA[
|
|
||||||
"theme": {
|
|
||||||
...
|
|
||||||
"module": {
|
|
||||||
"modules": [ "org.example.exampletheme" ]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]></programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
If a theme is deployed to <literal>themes</literal> and as a module the first is used.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>SPIs</title>
|
|
||||||
<para>
|
|
||||||
For full control of login forms and account management Keycloak provides a number of SPIs.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Account SPI</title>
|
|
||||||
<para>
|
|
||||||
The Account SPI allows implementing the account management pages using whatever web framework or templating
|
|
||||||
engine you want. To create an Account provider implement <literal>org.keycloak.account.AccountProviderFactory</literal>
|
|
||||||
and <literal>org.keycloak.account.AccountProvider</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Once you have deployed your account provider to Keycloak you need to configure <literal>keycloak-server.json</literal> to specify which provider should be used:
|
|
||||||
<programlisting>
|
|
||||||
"account": {
|
|
||||||
"provider": "custom-provider"
|
|
||||||
}
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Login SPI</title>
|
|
||||||
<para>
|
|
||||||
The Login SPI allows implementing the login forms using whatever web framework or templating
|
|
||||||
engine you want. To create a Login forms provider implement <literal>org.keycloak.login.LoginFormsProviderFactory</literal>
|
|
||||||
and <literal>org.keycloak.login.LoginFormsProvider</literal> in <literal>forms/login-api</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Once you have deployed your account provider to Keycloak you need to configure <literal>keycloak-server.json</literal> to specify which provider should be used:
|
|
||||||
<programlisting>
|
|
||||||
"login": {
|
|
||||||
"provider": "custom-provider"
|
|
||||||
}
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</chapter>
|
|
|
@ -1,117 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="timeouts">
|
|
||||||
<title>Cookie settings, Session Timeouts, and Token Lifespans</title>
|
|
||||||
<para>
|
|
||||||
Keycloak has a bunch of fine-grain settings to manage browser cookies, user login sessions, and token lifespans.
|
|
||||||
Sessions can be viewed and managed within the admin console for all users, and individually in the user's account
|
|
||||||
management pages. This chapter goes over configuration options for cookies, sessions, and tokens.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Remember Me</title>
|
|
||||||
<para>
|
|
||||||
If you go to the admin console page of Settings->General, you should see a <literal>Remember Me</literal> on/off switch.
|
|
||||||
Your realm sets a SSO cookie so that you only have to enter in your login credentials once.
|
|
||||||
This <literal>Remember Me</literal> admin config option, when turned on, will show a "Remember Me" checkbox on the user's login page.
|
|
||||||
If the user clicks this, the realm's SSO cookie will be persistent. This means that if the user closes their browser
|
|
||||||
they will still be logged in the next time they start up their browser.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="session-timeouts">
|
|
||||||
<title>Session Timeouts</title>
|
|
||||||
<para>
|
|
||||||
If you go to the Sesions and Tokens->Timeout Settings page of the Keycloak adminstration console there is a bunch of fine tuning
|
|
||||||
you can do as far as login session timeouts go.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <literal>SSO Session Idle Timeout</literal> is the idle time of a user session. If there is no activity
|
|
||||||
in the user's session for this amount of time, the user session will be destroyed, and the user will become logged
|
|
||||||
out. The idle time is refreshed with every action against the keycloak server for that session, i.e.: a user login,
|
|
||||||
SSO, a refresh token grant, etc.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <literal>SSO Session Max Lifespan</literal> setting is the maximum time a user session is allowed to be alive. This
|
|
||||||
max lifespan countdown starts from when the user first logs in and is never refreshed. This works great with <literal>Remember Me</literal>
|
|
||||||
in that it allow you to force a relogin after a set timeframe.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="token-timeouts">
|
|
||||||
<title>Token Timeouts</title>
|
|
||||||
<para>
|
|
||||||
The <literal>Access Token Lifespan</literal> is how long an access token is valid for. An access token contains everything
|
|
||||||
an application needs to authorize a client. It contains roles allowed as well as other user information. When
|
|
||||||
an access token expires, your application will attempt to refresh it using a refresh token that it obtained in the
|
|
||||||
initial login. The value of this configuration option should be however long you feel comfortable with the
|
|
||||||
application not knowing if the user's permissions have changed. This value is usually in minutes.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <code class="literal">Access Token Lifespan For Implicit Flow</code> is how long an access token is valid for when using OpenID Connect implicit flow.
|
|
||||||
With implicit flow, there is no refresh token available. That's why the lifespan is usually bigger than default Access Token Lifespan mentioned above.
|
|
||||||
See <ulink url="http://openid.net/specs/openid-connect-core-1_0.html#ImplicitFlowAuth">OpenID Connect specification</ulink> for details about implicit flow and
|
|
||||||
<link linkend="javascript-adapter">Javascript Adapter</link> for some additional details on how to use it in Keycloak.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <literal>Client login timeout</literal> is how long an access code is valid for. An access code is obtained
|
|
||||||
on the 1st leg of the OAuth 2.0 redirection protocol. This should be a short time limit. Usually seconds.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <literal>Login user action lifespan</literal> is how long a user is allowed to attempt a login. When a user tries
|
|
||||||
to login, they may have to change their password, set up TOTP, or perform some other action before they are redirected
|
|
||||||
back to your application as an authentnicated user. This value is relatively short and is usually measured in minutes.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="offline-access">
|
|
||||||
<title>Offline Access</title>
|
|
||||||
<para>
|
|
||||||
The Offline access is the feature described in <ulink url="http://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess">OpenID Connect specification</ulink> .
|
|
||||||
The idea is that during login, your client application will request Offline token instead of classic Refresh token.
|
|
||||||
Then the application can save this offline token in the database and can use it anytime later even if user is logged out.
|
|
||||||
This is useful for example if your application needs to do some "offline" actions on behalf of user even if user is not online. For example
|
|
||||||
periodic backup of some data every night etc.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Your application is responsible for persist the offline token in some storage (usually database) and then use it to
|
|
||||||
manually retrieve new access token from Keycloak server.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The difference between classic Refresh token and Offline token is, that offline token will never expire and is not subject of <literal>SSO Session Idle timeout</literal> .
|
|
||||||
The offline token is valid even after user logout or server restart. However you need to use offline token for refresh at least once per each 30 days (
|
|
||||||
The value can be changed in admin console. It is <literal>Offline Session Idle timeout</literal> ). Also if you enable option <literal>Revoke refresh tokens</literal>
|
|
||||||
, then each offline token can be used just once. So after refresh, you always need to store new offline token from refresh response into your DB instead of the previous one.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
User can revoke the offline tokens in Account management UI. The admin
|
|
||||||
user can revoke offline tokens for individual users in admin console (The <literal>Consent</literal> tab of particular user) and he can
|
|
||||||
see all the offline tokens of all users for particular client application in the settings of the client. Revoking of all offline tokens for particular
|
|
||||||
client is possible by set <literal>notBefore</literal> policy for the client.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For requesting the offline token, user needs to be in realm role <literal>offline_access</literal> and client needs to have
|
|
||||||
scope for this role. If client has <literal>Full scope allowed</literal>, the scope is granted by default. Also users are automatically
|
|
||||||
members of the role as it's the default role.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The client can request offline token by adding parameter <literal>scope=offline_access</literal>
|
|
||||||
when sending authorization request to Keycloak. The adapter automatically adds this parameter when you use it to access secured
|
|
||||||
URL of your application (ie. http://localhost:8080/customer-portal/secured?scope=offline_access ).
|
|
||||||
The <link linkend='direct-access-grants'>Direct Access Grant</link> or <link linkend="service-accounts">Service account</link> flows also support
|
|
||||||
offline tokens if you include <literal>scope=offline_access</literal> in the body of the authentication request. For more details,
|
|
||||||
see the <literal>offline-access-app</literal> example from Keycloak demo.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,109 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<section id="tomcat-adapter">
|
|
||||||
<title>Tomcat 6, 7 and 8 Adapters</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<section id="tomcat-adapter-installation">
|
|
||||||
<title>Adapter Installation</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You must unzip the adapter distro into Tomcat's <literal>lib/</literal> 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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
$ cd $TOMCAT_HOME/lib
|
|
||||||
$ unzip keycloak-tomcat6-adapter-dist.zip
|
|
||||||
or
|
|
||||||
$ unzip keycloak-tomcat7-adapter-dist.zip
|
|
||||||
or
|
|
||||||
$ unzip keycloak-tomcat8-adapter-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Required Per WAR Configuration</title>
|
|
||||||
<para>
|
|
||||||
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The first thing you must do is create a <literal>META-INF/context.xml</literal> file in your WAR package. This is
|
|
||||||
a Tomcat specific config file and you must define a Keycloak specific Valve.
|
|
||||||
</para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<Context path="/your-context-path">
|
|
||||||
<Valve className="org.keycloak.adapters.tomcat.KeycloakAuthenticatorValve"/>
|
|
||||||
</Context>]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
Next you must create
|
|
||||||
a <literal>keycloak.json</literal> adapter config file within the <literal>WEB-INF</literal> directory
|
|
||||||
of your WAR. The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
|
|
||||||
section.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Finally you must specify both a <literal>login-config</literal> and use standard servlet security to specify
|
|
||||||
role-base constraints on your URLs. Here's an example:
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
|
@ -1,342 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="user_federation">
|
|
||||||
<title>User Federation SPI and LDAP/AD Integration</title>
|
|
||||||
<para>
|
|
||||||
Keycloak can federate external user databases. Out of the box we have support for LDAP and Active Directory.
|
|
||||||
Before you dive into this, you should understand how Keycloak does federation.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Keycloak performs federation a bit differently than other products/projects. The vision of Keycloak is that it
|
|
||||||
is an out of the box solution that should provide a core set of feature irregardless of the backend user storage you
|
|
||||||
want to use. Because of this requirement/vision, Keycloak has a set data model that all of its services use.
|
|
||||||
Most of the time when you want to federate an external user store, much of the metadata that would be needed to
|
|
||||||
provide this complete feature set does not exist in that external store. For example your LDAP server may only
|
|
||||||
provide password validation, but not support TOTP or user role mappings. The Keycloak User Federation SPI was
|
|
||||||
written to support these completely variable configurations.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The way user federation works is that Keycloak will import your federated users on demand to its local storage. How
|
|
||||||
much metadata that is imported depends on the underlying federation plugin and how that plugin is configured. Some
|
|
||||||
federation plugins may only import the username into Keycloak storage, others might import everything from name,
|
|
||||||
address, and phone number, to user role mappings. Some plugins might want to import credentials directly into
|
|
||||||
Keycloak storage and let Keycloak handle credential validation. Others might want to handle credential validation
|
|
||||||
themselves. The goal of the Federation SPI is to support all of these scenarios.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>LDAP and Active Directory Plugin</title>
|
|
||||||
<para>
|
|
||||||
Keycloak comes with a built-in LDAP/AD plugin. By default, it is set up only to import username, email, first and last name, but you are free
|
|
||||||
to configure <link linkend='ldap_mappers'>mappers</link> and add more attributes or delete default ones.
|
|
||||||
It supports password validation via LDAP/AD protocols and different user metadata synchronization modes. To configure
|
|
||||||
a federated LDAP store go to the admin console. Click on the <literal>Users</literal> menu option to get you
|
|
||||||
to the user management page. Then click on the <literal>Federation</literal> submenu option. When
|
|
||||||
you get to this page there is an "Add Provider" select box. You should see "ldap" within this list. Selecting
|
|
||||||
"ldap" will bring you to the ldap configuration page.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Edit Mode</title>
|
|
||||||
<para>
|
|
||||||
Edit mode defines various synchronization options with your LDAP store depending on what privileges
|
|
||||||
you have.
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>READONLY</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Username, email, first and last name and other mapped attributes will be unchangeable. Keycloak will show an error
|
|
||||||
anytime anybody tries to update these fields. Also, password updates will not be supported.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>WRITABLE</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Username, email, first and last name, other mapped attributes and passwords can all be updated and will
|
|
||||||
be synchronized automatically with your LDAP store.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>UNSYNCED</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Any changes to username, email, first and last name, and passwords will be stored
|
|
||||||
in Keycloak local storage. It is up to you to figure out how to synchronize back to
|
|
||||||
LDAP.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Other config options</title>
|
|
||||||
<para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Display Name</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Name used when this provider is referenced in the admin console
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Priority</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The priority of this provider when looking up users or for adding registrations.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Sync Registrations</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If a new user is added through a registration page or admin console, should the user
|
|
||||||
be eligible to be synchronized to this provider.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Allow Kerberos authentication</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Enable Kerberos/SPNEGO authentication in realm with users data provisioned from LDAP. More info in <link linkend="kerberos">Kerberos section</link>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Other options</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The rest of the configuration options should be self explanatory. You can use tooltips in admin console
|
|
||||||
to see some more details about them.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Connect to LDAP over SSL</title>
|
|
||||||
<para>
|
|
||||||
When you configure secured connection URL to LDAP (for example <literal>ldaps://myhost.com:636</literal> ) the Keycloak will
|
|
||||||
use SSL for the communication with LDAP server. The important thing is to properly configure truststore on the Keycloak server side,
|
|
||||||
because SSL won't work if Keycloak can't trust the SSL connection with LDAP (Keycloak acts as the <literal>client</literal> here, when LDAP acts as server).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The global truststore for the Keycloak can be configured with Truststore SPI in the <literal>keycloak-server.json</literal> file and it's described in the details <link linkend="truststore">here</link>.
|
|
||||||
If you don't configure truststore SPI, the truststore will fallback to the default mechanism provided by Java (either the file provided by system property <literal>javax.net.ssl.trustStore</literal> or finally
|
|
||||||
the cacerts file from JDK if even the system property is not set).
|
|
||||||
</para>
|
|
||||||
<para>There is configuration property <literal>Use Truststore SPI</literal> in the LDAP federation provider configuration, where you can choose
|
|
||||||
whether Truststore SPI is used. By default, the value is <literal>ldaps only</literal>, which is fine for most of deployments, because attempt
|
|
||||||
to use Truststore SPI is done just if connection to LDAP starts with <literal>ldaps</literal> .
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Sync of LDAP users to Keycloak</title>
|
|
||||||
<para>
|
|
||||||
LDAP Federation Provider will automatically take care of synchronization (import) of needed LDAP users into Keycloak database.
|
|
||||||
For example once you first authenticate LDAP user <literal>john</literal> from Keycloak UI, LDAP Federation provider will
|
|
||||||
first import this LDAP user into Keycloak database and then authenticate against LDAP password.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Federation Provider imports just requested users by default, so if you click to <literal>View all users</literal>
|
|
||||||
in Keycloak admin console, you will see just those LDAP users, which were already authenticated/requested by Keycloak.
|
|
||||||
</para>
|
|
||||||
<para>If you want to sync all LDAP users into Keycloak database, you may configure and enable Sync, which is in
|
|
||||||
admin console on same page like the configuration of Federation provider itself. There are 2 types of sync:
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Full sync</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This will synchronize all LDAP users into Keycloak DB. Those LDAP users, which already exist in Keycloak and were
|
|
||||||
changed in LDAP directly will be updated in Keycloak DB (For example if user <literal>Mary Kelly</literal> was changed in LDAP to <literal>Mary Doe</literal>).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Changed users sync</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This will check LDAP and it will sync into Keycloak just those users, which were created or updated in LDAP from the time of last sync.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
In usual cases you may want to trigger full sync at the beginning, so you will import all LDAP users to Keycloak just once. Then you may setup
|
|
||||||
periodic sync of changed users, so Keycloak will periodically ask LDAP server for newly created or updated users and backport them to Keycloak DB.
|
|
||||||
Also you may want to trigger full sync again after some longer time or setup periodic full sync as well.
|
|
||||||
</para>
|
|
||||||
<para>In admin console, you can trigger sync directly or you can enable periodic changed or full sync.</para>
|
|
||||||
</section>
|
|
||||||
<section id="ldap_mappers">
|
|
||||||
<title>LDAP/Federation mappers</title>
|
|
||||||
<para>
|
|
||||||
LDAP mappers are <literal>listeners</literal>, which are triggered by LDAP Federation provider at various points and provide
|
|
||||||
another extension point to LDAP integration. They are triggered during import LDAP user into Keycloak, registration Keycloak user back to LDAP or when querying LDAP user from Keycloak.
|
|
||||||
When you create LDAP Federation provider, Keycloak will automatically provide set of builtin <literal>mappers</literal> for this provider.
|
|
||||||
You are free to change this set and create new mapper or update/delete existing ones.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
By default, we have those implementation of LDAP federation mapper:
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>User Attribute Mapper</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This allows to specify which LDAP attribute is mapped to which attribute of Keycloak User. So for example you can configure
|
|
||||||
that LDAP attribute <literal>mail</literal> is supposed to be mapped to the UserModel attribute <literal>email</literal> in Keycloak database.
|
|
||||||
For this mapper implementation, there is always one-to-one mapping (one LDAP attribute mapped to one Keycloak UserModel attribute)
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>FullName Mapper</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This allows to specify that fullname of user, which is saved in some LDAP attribute (usualy <literal>cn</literal> ) will be mapped to
|
|
||||||
<literal>firstName</literal> and <literal>lastname</literal> attributes of UserModel. Having <literal>cn</literal> to contain full name of user
|
|
||||||
is common case for some LDAP deployments.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Role Mapper</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This allows to configure role mappings from LDAP into Keycloak role mappings. One Role mapper can be used to map LDAP roles
|
|
||||||
(usually groups from particular branch of LDAP tree) into roles corresponding to either realm roles or client roles of specified client.
|
|
||||||
It's not a problem to configure more Role mappers for same LDAP provider. So for example you can specify that role mappings from groups under
|
|
||||||
<literal>ou=main,dc=example,dc=org</literal> will be mapped to realm role mappings and role mappings from
|
|
||||||
groups under <literal>ou=finance,dc=example,dc=org</literal> will be mapped to client role mappings of client <literal>finance</literal> .
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Hardcoded Role Mapper</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This mapper will grant specified Keycloak role to each Keycloak user linked with LDAP.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>Group Mapper</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This allows to configure group mappings from LDAP into Keycloak group mappings. Group mapper can be used to map LDAP groups from particular branch of LDAP tree
|
|
||||||
into groups in Keycloak. And it will also propagate user-group mappings from LDAP into user-group mappings in Keycloak.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You can choose to preserve group inheritance from LDAP as well, but this may fail as Keycloak inheritance is more restrictive than LDAP
|
|
||||||
(For example in Keycloak each group can have just one parent and there is no recursion allowed. In LDAP the recursion is possible and every group can be member of more
|
|
||||||
other groups too).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
As of now, the mapper doesn't provide mapping of LDAP roles-groups to Keycloak roles-groups
|
|
||||||
(For example when LDAP group <literal>cn=role1,ou=roles,dc=example,dc=com</literal> is member of LDAP group
|
|
||||||
<literal>cn=group1,ou=groups,dc=example,dc=com</literal> , we don't support the mapping of Keycloak role <literal>role1</literal> imported from LDAP to corresponding Keycloak group <literal>group1</literal> imported from LDAP).
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>MSAD User Account Mapper</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Mapper specific to Microsoft Active Directory (MSAD). It's able to tightly integrate the MSAD user account state into Keycloak account state (account enabled, password is expired etc).
|
|
||||||
It's using <literal>userAccountControl</literal> and <literal>pwdLastSet</literal> LDAP attributes for that (both are specific to MSAD and are not LDAP standard).
|
|
||||||
For example if pwdLastSet is 0, the Keycloak user is required to update password (there will be UPDATE_PASSWORD required action added to him in Keycloak). Or if userAccountControl
|
|
||||||
is 514 (disabled account) the Keycloak user is disabled as well etc.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For writable LDAP, the mapping is bi-directional and the state from Keycloak is propagated to LDAP (For example enable user
|
|
||||||
in Keycloak admin console will update the value of userAccountControl in MSAD and effectively enable him in MSAD as well).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
For writable LDAPs, mapper also provides mapping of error codes during MSAD user authentication to the
|
|
||||||
appropriate action in Keycloak. For example if MSAD user authentication fails due to the fact, that MSAD password is expired,
|
|
||||||
the mapper will allow user to authenticate into Keycloak, but it will add UPDATE_PASSWORD required action to the user, so user
|
|
||||||
must update his password.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
<para>By default, there is set of User Attribute mappers to map basic UserModel attributes username, first name, lastname and email to corresponding LDAP attributes. You are free to extend this and provide
|
|
||||||
more attribute mappings (For example to street, postalCode etc), delete firstName/lastname mapper and put fullName mapper instead, add role mappers etc.
|
|
||||||
Admin console provides tooltips, which should help on how to configure corresponding mappers.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
We have an example, which is showing LDAP integration and set of base mappers and sample mappers (mappers for street and postalCode) . It's in <literal>examples/ldap</literal>
|
|
||||||
in the Keycloak example distribution or demo distribution download. You can also check the example sources directly <ulink url="https://github.com/keycloak/keycloak/blob/master/examples/ldap">here</ulink> .
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>Writing your own LDAP Mapper</title>
|
|
||||||
<para>
|
|
||||||
For the more advanced usecases, you have the possibility to create your own implementation of LDAP mapper or just subclass from
|
|
||||||
some already existing mapper implementation. You will need to implement <literal>UserFederationMapperFactory</literal> interface. In most cases, instead of
|
|
||||||
creating <literal>UserFederationMapperFactory</literal> from scratch, you can create subclasses of <literal>AbstractLDAPFederationMapperFactory</literal>, which itself
|
|
||||||
implements <literal>UserFederationMapperFactory</literal>. Then you need to create mapper implementation, which will be subclass of
|
|
||||||
<literal>AbstractLDAPFederationMapper</literal> (this mapper implementation will be returned by <literal>YourAbstractLDAPFederationMapperFactorySubclass.createMapper</literal> method).
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
After your code is written you must package up all your classes within a JAR file. This jar file must contain a file called
|
|
||||||
<literal>org.keycloak.mappers.UserFederationMapperFactory</literal> within the <literal>META-INF/services directory</literal> of the JAR. This file is a list of fully
|
|
||||||
qualified classnames of all implementations of <literal>UserFederationMapperFactory</literal>. For more details, look at section for
|
|
||||||
<link linkend="write_federation_provider">Write your own federation provider</link> and at <link linkend="providers">Providers and SPI</link> section.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
<section id="write_federation_provider">
|
|
||||||
<title>Writing your own User Federation Provider</title>
|
|
||||||
<para>
|
|
||||||
The keycloak examples directory contains an example of a simple User Federation Provider backed by
|
|
||||||
a simple properties file. See <literal>examples/providers/federation-provider</literal>. Most of how
|
|
||||||
to create a federation provider is explained directly within the example code, but some information is here too.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Writing a User Federation Provider starts by implementing the <literal>UserFederationProvider</literal>
|
|
||||||
and <literal>UserFederationProviderFactory</literal> interfaces. Please see the Javadoc and example
|
|
||||||
for complete details on how to do this. Some important methods of note:
|
|
||||||
getUserByUsername() and getUserByEmail() require that you query your federated storage and if the user exists
|
|
||||||
create and import the user into Keycloak storage. How much metadata you import is fully up to you. This
|
|
||||||
import is done by invoking methods on the object returned <literal>KeycloakSession.userStorage()</literal>
|
|
||||||
to add and import user information. The proxy() method will be called whenever Keycloak has found an imported
|
|
||||||
UserModel. This allows the federation provider to proxy the UserModel which is useful if you want to support
|
|
||||||
external storage updates on demand.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
After your code is written you must package up all your classes within a JAR file. This jar file must
|
|
||||||
contain a file called <literal>org.keycloak.models.UserFederationProviderFactory</literal>
|
|
||||||
within the <literal>META-INF/services</literal> directory of the JAR. This file is a list
|
|
||||||
of fully qualified classnames of all implementations of <literal>UserFederationProviderFactory</literal>.
|
|
||||||
For more details on writing provider implementations and how to deploy to Keycloak refer to the
|
|
||||||
<link linkend='providers'>providers</link> section.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</chapter>
|
|
Before Width: | Height: | Size: 88 KiB |
Before Width: | Height: | Size: 59 KiB |
Before Width: | Height: | Size: 103 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 66 KiB |
Before Width: | Height: | Size: 80 KiB |
|
@ -1,37 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
|
||||||
<parent>
|
|
||||||
<artifactId>keycloak-parent</artifactId>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
<name>Keycloak Documentation</name>
|
|
||||||
<description/>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<artifactId>keycloak-docbook-parent</artifactId>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
|
|
||||||
<modules>
|
|
||||||
<module>auth-server-docs</module>
|
|
||||||
<module>saml-adapter-docs</module>
|
|
||||||
</modules>
|
|
||||||
</project>
|
|
|
@ -1,151 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<parent>
|
|
||||||
<artifactId>keycloak-docbook-parent</artifactId>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<version>2.0.0.CR1-SNAPSHOT</version>
|
|
||||||
<relativePath>../pom.xml</relativePath>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<artifactId>keycloak-saml-adapter-reference-guide-${translation}</artifactId>
|
|
||||||
<packaging>jdocbook</packaging>
|
|
||||||
<name>Keycloak SAML Client Adapter Guide (${translation})</name>
|
|
||||||
<description/>
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<repositories>
|
|
||||||
<repository>
|
|
||||||
<id>jboss</id>
|
|
||||||
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
|
|
||||||
</repository>
|
|
||||||
<!--
|
|
||||||
<repository>
|
|
||||||
<id>repo1.maven.org</id>
|
|
||||||
<url>http://repo1.maven.org/maven2</url>
|
|
||||||
</repository> -->
|
|
||||||
</repositories>
|
|
||||||
<pluginRepositories>
|
|
||||||
<pluginRepository>
|
|
||||||
<id>jboss</id>
|
|
||||||
<url>http://repository.jboss.org/nexus/content/groups/public/</url>
|
|
||||||
</pluginRepository>
|
|
||||||
<!--
|
|
||||||
<pluginRepository>
|
|
||||||
<id>maven2-repository.dev.java.net</id>
|
|
||||||
<url>http://download.java.net/maven/2</url>
|
|
||||||
</pluginRepository>
|
|
||||||
<pluginRepository>
|
|
||||||
<id>plugin repo1.maven.org</id>
|
|
||||||
<url>http://repo1.maven.org/maven2</url>
|
|
||||||
</pluginRepository>
|
|
||||||
-->
|
|
||||||
</pluginRepositories>
|
|
||||||
|
|
||||||
<build>
|
|
||||||
<plugins>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-deploy-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<skip>true</skip>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.jboss.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-jdocbook-plugin</artifactId>
|
|
||||||
<version>2.3.8</version>
|
|
||||||
<extensions>true</extensions>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.pressgang</groupId>
|
|
||||||
<artifactId>pressgang-xslt-ns</artifactId>
|
|
||||||
<version>2.0.2</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.jboss.pressgang</groupId>
|
|
||||||
<artifactId>pressgang-jdocbook-style</artifactId>
|
|
||||||
<type>jdocbook-style</type>
|
|
||||||
<version>2.0.2</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
<configuration>
|
|
||||||
<sourceDocumentName>master.xml</sourceDocumentName>
|
|
||||||
<masterTranslation>en-US</masterTranslation>
|
|
||||||
<sourceDirectory>${project.basedir}/reference/en</sourceDirectory>
|
|
||||||
<imageResource>
|
|
||||||
<directory>${project.basedir}/reference/en</directory>
|
|
||||||
<includes>
|
|
||||||
<include>images/*</include>
|
|
||||||
</includes>
|
|
||||||
</imageResource>
|
|
||||||
<formats>
|
|
||||||
<format>
|
|
||||||
<formatName>html_single</formatName>
|
|
||||||
<stylesheetResource>classpath:/xslt/org/jboss/xhtml-single.xsl</stylesheetResource>
|
|
||||||
<finalName>index.html</finalName>
|
|
||||||
<!-- <profilingTypeName>two_pass</profilingTypeName> -->
|
|
||||||
</format>
|
|
||||||
<format>
|
|
||||||
<formatName>html</formatName>
|
|
||||||
<stylesheetResource>classpath:/xslt/org/jboss/xhtml.xsl</stylesheetResource>
|
|
||||||
<finalName>index.html</finalName>
|
|
||||||
<!-- <profilingTypeName>two_pass</profilingTypeName> -->
|
|
||||||
</format>
|
|
||||||
<format>
|
|
||||||
<formatName>pdf</formatName>
|
|
||||||
<stylesheetResource>classpath:/xslt/org/jboss/pdf.xsl</stylesheetResource>
|
|
||||||
<finalName>${project.artifactId}.pdf</finalName>
|
|
||||||
</format>
|
|
||||||
<!--<format>-->
|
|
||||||
<!--<formatName>eclipse</formatName>-->
|
|
||||||
<!--<stylesheetResource>classpath:/xslt/org/jboss/eclipse.xsl</stylesheetResource>-->
|
|
||||||
<!--<finalName>${project.artifactId}.html</finalName>-->
|
|
||||||
<!--</format>-->
|
|
||||||
</formats>
|
|
||||||
<injections>
|
|
||||||
<injection>
|
|
||||||
<name>project.version</name>
|
|
||||||
<value>${project.version}</value>
|
|
||||||
</injection>
|
|
||||||
<injection>
|
|
||||||
<name>picketlink.version</name>
|
|
||||||
<value>${picketlink.version}</value>
|
|
||||||
</injection>
|
|
||||||
</injections>
|
|
||||||
<options>
|
|
||||||
<xmlTransformerType>saxon</xmlTransformerType>
|
|
||||||
<xincludeSupported>true</xincludeSupported>
|
|
||||||
<useRelativeImageUris>true</useRelativeImageUris>
|
|
||||||
<!-- TODO Probably obsolete after the upgrade to maven-jdocbook-plugin 2.3.0 -->
|
|
||||||
<docbookVersion>1.72.0</docbookVersion>
|
|
||||||
<!-- <localeSeparator>-</localeSeparator> -->
|
|
||||||
</options>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
</plugins>
|
|
||||||
</build>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<translation>en-US</translation>
|
|
||||||
</properties>
|
|
||||||
</project>
|
|
|
@ -1,84 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
|
|
||||||
"http://www.docbook.org/xml/4.4/docbookx.dtd"
|
|
||||||
[
|
|
||||||
<!ENTITY Overview SYSTEM "modules/overview.xml">
|
|
||||||
<!ENTITY AdapterConfig SYSTEM "modules/adapter-config.xml">
|
|
||||||
<!ENTITY JBossAdapter SYSTEM "modules/jboss-adapter.xml">
|
|
||||||
<!ENTITY TomcatAdapter SYSTEM "modules/tomcat-adapter.xml">
|
|
||||||
<!ENTITY Jetty9Adapter SYSTEM "modules/jetty9-adapter.xml">
|
|
||||||
<!ENTITY Jetty8Adapter SYSTEM "modules/jetty8-adapter.xml">
|
|
||||||
<!ENTITY FilterAdapter SYSTEM "modules/servlet-filter-adapter.xml">
|
|
||||||
<!ENTITY Assertions SYSTEM "modules/assertion-api.xml">
|
|
||||||
<!ENTITY Logout SYSTEM "modules/logout.xml">
|
|
||||||
<!ENTITY ErrorHandling SYSTEM "modules/adapter_error_handling.xml">
|
|
||||||
<!ENTITY DEBUGGING SYSTEM "modules/debugging.xml">
|
|
||||||
<!ENTITY Migrating SYSTEM "modules/MigrationFromOlderVersions.xml">
|
|
||||||
<!ENTITY IDP_REG SYSTEM "modules/idp-registration.xml">
|
|
||||||
]>
|
|
||||||
|
|
||||||
<book>
|
|
||||||
|
|
||||||
<bookinfo>
|
|
||||||
<title>Keycloak SAML Client Adapter Reference Guide</title>
|
|
||||||
<subtitle>SAML 2.0 Client Adapters</subtitle>
|
|
||||||
<releaseinfo>&project.version;</releaseinfo>
|
|
||||||
</bookinfo>
|
|
||||||
|
|
||||||
<toc/>
|
|
||||||
|
|
||||||
<preface id="preface" revision="1">
|
|
||||||
<title>Preface</title>
|
|
||||||
<para>
|
|
||||||
In some of the example listings, what is meant to be displayed on one line does not fit
|
|
||||||
inside the available page width. These lines have been broken up. A '\' at the end of a
|
|
||||||
line means that a break has been introduced to fit in the page, with the following lines
|
|
||||||
indented. So:
|
|
||||||
<programlisting>
|
|
||||||
Let's pretend to have an extremely \
|
|
||||||
long line that \
|
|
||||||
does not fit
|
|
||||||
This one is short
|
|
||||||
</programlisting>
|
|
||||||
Is really:
|
|
||||||
<programlisting>
|
|
||||||
Let's pretend to have an extremely long line that does not fit
|
|
||||||
This one is short
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</preface>
|
|
||||||
&Overview;
|
|
||||||
&AdapterConfig;
|
|
||||||
&JBossAdapter;
|
|
||||||
&TomcatAdapter;
|
|
||||||
&Jetty9Adapter;
|
|
||||||
&Jetty8Adapter;
|
|
||||||
&FilterAdapter;
|
|
||||||
&IDP_REG;
|
|
||||||
&Logout;
|
|
||||||
&Assertions;
|
|
||||||
&ErrorHandling;
|
|
||||||
&DEBUGGING;
|
|
||||||
&Migrating;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</book>
|
|
||||||
|
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="Migration_from_older_versions">
|
|
||||||
<title>Migration from older versions</title>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Version specific migration</title>
|
|
||||||
<section>
|
|
||||||
<title>Migrating to 1.9.0</title>
|
|
||||||
<simplesect>
|
|
||||||
<title>SAML SP Client Adapter Changes</title>
|
|
||||||
<para>
|
|
||||||
Keycloak SAML SP Client Adapter now requires a specific endpoint, <literal>/saml</literal> to be
|
|
||||||
registered with your IDP. The SamlFilter must also be bound to /saml in addition to any other binding it has.
|
|
||||||
This had to be done because SAML POST binding would eat the request input stream and this would be really
|
|
||||||
bad for clients that relied on it.
|
|
||||||
</para>
|
|
||||||
</simplesect>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,515 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="adapter-config">
|
|
||||||
<title>General Adapter Config</title>
|
|
||||||
<para>
|
|
||||||
Each SAML adapter supported by Keycloak can be configured by a simple XML text file. This is what one might
|
|
||||||
look like:
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<keycloak-saml-adapter>
|
|
||||||
<SP entityID="http://localhost:8081/sales-post-sig/"
|
|
||||||
sslPolicy="EXTERNAL"
|
|
||||||
nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
|
||||||
logoutPage="/logout.jsp"
|
|
||||||
forceAuthentication="false"
|
|
||||||
isPassive="false"
|
|
||||||
turnOffChangeSessionIdOnLogin="false">
|
|
||||||
<Keys>
|
|
||||||
<Key signing="true" >
|
|
||||||
<KeyStore resource="/WEB-INF/keystore.jks" password="store123">
|
|
||||||
<PrivateKey alias="http://localhost:8080/sales-post-sig/" password="test123"/>
|
|
||||||
<Certificate alias="http://localhost:8080/sales-post-sig/"/>
|
|
||||||
</KeyStore>
|
|
||||||
</Key>
|
|
||||||
</Keys>
|
|
||||||
<PrincipalNameMapping policy="FROM_NAME_ID"/>
|
|
||||||
<RoleMapping>
|
|
||||||
<Attribute name="Role"/>
|
|
||||||
</RoleMapping>
|
|
||||||
<IDP entityID="idp"
|
|
||||||
signaturesRequired="true">
|
|
||||||
<SingleSignOnService requestBinding="POST"
|
|
||||||
bindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<SingleLogoutService
|
|
||||||
requestBinding="POST"
|
|
||||||
responseBinding="POST"
|
|
||||||
postBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
|
||||||
redirectBindingUrl="http://localhost:8081/auth/realms/demo/protocol/saml"
|
|
||||||
/>
|
|
||||||
<Keys>
|
|
||||||
<Key signing="true">
|
|
||||||
<KeyStore resource="/WEB-INF/keystore.jks" password="store123">
|
|
||||||
<Certificate alias="demo"/>
|
|
||||||
</KeyStore>
|
|
||||||
</Key>
|
|
||||||
</Keys>
|
|
||||||
</IDP>
|
|
||||||
</SP>
|
|
||||||
</keycloak-saml-adapter>]]>
|
|
||||||
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Some of these configuration switches may be adapter specific and some are common across all adapters.
|
|
||||||
For Java adapters you can use <literal>${...}</literal> enclosure as System property replacement.
|
|
||||||
For example <literal>${jboss.server.config.dir}</literal>.
|
|
||||||
</para>
|
|
||||||
<section>
|
|
||||||
<title>SP Element</title>
|
|
||||||
<para>
|
|
||||||
Here is the explanation of the SP element attributes
|
|
||||||
</para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<SP entityID="sp"
|
|
||||||
sslPolicy="ssl"
|
|
||||||
nameIDPolicyFormat="format"
|
|
||||||
forceAuthentication="true"
|
|
||||||
isPassive="false">
|
|
||||||
...
|
|
||||||
</SP>]]></programlisting>
|
|
||||||
<para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>entityID</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This is the identifier for this client. The IDP needs this value to determine
|
|
||||||
who the client is that is communicating with it.
|
|
||||||
<emphasis>REQUIRED.</emphasis>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>sslPolicy</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This is the SSL policy the adapter will enforce. Valid values are:
|
|
||||||
ALL, EXTERNAL, and NONE. For ALL, all requests must come in via HTTPS. For
|
|
||||||
EXTERNAL, only non-private IP addresses must come over the wire via HTTPS. For
|
|
||||||
NONE, no requests are required to come over via HTTPS. This is
|
|
||||||
<emphasis>OPTIONAL.</emphasis> and defaults to EXTERNAL.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>nameIDPolicyFormat</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
SAML clients can request a specific NameID Subject format. Fill in this value
|
|
||||||
if you want a specific format. It must be a standard SAML format identifier, i.e.
|
|
||||||
<literal>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</literal>
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. By default, no special format is requested.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>forceAuthentication</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
SAML clients can request that a user is re-authenticated even if
|
|
||||||
they are already logged in at the IDP. Set this to <literal>true</literal> if you
|
|
||||||
want this.
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. Set to <literal>false</literal> by default.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>isPassive</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
SAML clients can request that a user is never asked to authenticate even if
|
|
||||||
they are not logged in at the IDP. Set this to <literal>true</literal> if you want this.
|
|
||||||
Do not use together with <literal>forceAuthentication</literal> as they are opposite.
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. Set to <literal>false</literal> by default.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>turnOffChangeSessionIdOnLogin</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
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 <emphasis>OPTIONAL</emphasis>. The default value is <emphasis>false</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="sp_keys">
|
|
||||||
<title>SP Keys and Key elements</title>
|
|
||||||
<para>
|
|
||||||
If the IDP requires that the SP sign all of its requests and/or if the IDP will
|
|
||||||
encrypt assertions, you must define the keys used to do this. For client signed
|
|
||||||
documents you must define both the private and public key or certificate that will
|
|
||||||
be used to sign documents. For encryption, you only have to define the private key
|
|
||||||
that will be used to decrypt.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
There are two ways to describe your keys. Either they are stored within a Java KeyStore
|
|
||||||
or you can cut and paste the keys directly within <literal>keycloak-saml.xml</literal>
|
|
||||||
in the PEM format.
|
|
||||||
</para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<Keys>
|
|
||||||
<Key signing="true" >
|
|
||||||
<KeyStore resource="/WEB-INF/keystore.jks" password="store123">
|
|
||||||
<PrivateKey alias="http://localhost:8080/sales-post-sig/" password="test123"/>
|
|
||||||
<Certificate alias="http://localhost:8080/sales-post-sig/"/>
|
|
||||||
</KeyStore>
|
|
||||||
</Key>
|
|
||||||
</Keys>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
The <literal>Key</literal> element has two optional attributes <literal>signing</literal>
|
|
||||||
and <literal>encryption</literal>. When set to true these tell the adapter what the
|
|
||||||
key will be used for. If both attributes are set to true, then the key will be used for both
|
|
||||||
signing documents and decrypting encrypted assertions. You must set at least one of these
|
|
||||||
attributes to true.
|
|
||||||
</para>
|
|
||||||
<section id="keystore">
|
|
||||||
<title>KeyStore element</title>
|
|
||||||
<para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>file</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
File path to the key store.
|
|
||||||
<emphasis>OPTIONAL.</emphasis> The file or resource attribute
|
|
||||||
must be set.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>resource</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
WAR resource path to the KeyStore. This is a path used in method call to ServletContext.getResourceAsStream().
|
|
||||||
<emphasis>OPTIONAL.</emphasis> The file or resource attribute
|
|
||||||
must be set.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>password</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
The password of the KeyStore
|
|
||||||
<emphasis>REQUIRED.</emphasis>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You can and must also specify references to your private keys and certificates within
|
|
||||||
the Java KeyStore. The <literal>PrivateKey</literal> and <literal>Certificate</literal>
|
|
||||||
elements do this. The <literal>alias</literal> attribute defines the alias within the
|
|
||||||
KeyStore for the key. For <literal>PrivateKey</literal>, a password is required to access this key
|
|
||||||
specify that value in the <literal>password</literal> attribute.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section id="key_pems">
|
|
||||||
<title>Key PEMS</title>
|
|
||||||
<para>
|
|
||||||
Within the <literal>Key</literal> element you alternatively declare your keys and certificates
|
|
||||||
directly using the sub elements <literal>PrivateKeyPem</literal>, <literal>PublicKeyPem</literal>, and
|
|
||||||
<literal>CertificatePem</literal>. The values contained in these elements must conform to the
|
|
||||||
PEM key format. You usually use this option if you are generating keys using <literal>openssl</literal>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>SP PrincipalNameMapping element</title>
|
|
||||||
<para>
|
|
||||||
This element is optional. When creating a Java Principal object that you obtain from
|
|
||||||
methods like HttpServletRequest.getUserPrincipal(), you can define what name that is returned
|
|
||||||
by the Principal.getName() method. The <literal>policy</literal> attribute defines the
|
|
||||||
policy used to populate this value. The values are <literal>FROM_NAME_ID</literal>. This policy
|
|
||||||
just grabs whatever the SAML subject value is. The other is <literal>FROM_ATTRIBUTE</literal>. This will
|
|
||||||
pull the value of Principal.getName() from one of the attributes in the SAML assertion received from the server.
|
|
||||||
The default value is <literal>FROM_NAME_ID</literal>.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>RoleIdentifiers element</title>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<RoleIdentifiers>
|
|
||||||
<Attribute name="Role"/>
|
|
||||||
<Attribute name="member"/>
|
|
||||||
<Attribute name="memberOf"/>
|
|
||||||
</RoleIdentifiers>
|
|
||||||
]]></programlisting>
|
|
||||||
<para>
|
|
||||||
This element is optional. It defines which SAML attribute values in the assertion should be
|
|
||||||
mapped to a Java EE role. By default <literal>Role</literal> attribute values are converted
|
|
||||||
to Java EE roles. Some IDPs send roles via a <literal>member</literal> or <literal>memberOf</literal>
|
|
||||||
attribute assertion. You define one or more <literal>Attribute</literal> elements to specify
|
|
||||||
which SAML attributes must be converted into roles.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>IDP Element</title>
|
|
||||||
<para>
|
|
||||||
Everything in the IDP element describes the settings for the IDP the SP is communicating
|
|
||||||
with.
|
|
||||||
</para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<IDP entityID="idp"
|
|
||||||
signaturesRequired="true"
|
|
||||||
signatureAlgorithm="RSA_SHA1"
|
|
||||||
signatureCanonicalizationMethod="http://www.w3.org/2001/10/xml-exc-c14n#">
|
|
||||||
...
|
|
||||||
</IDP>]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>entityID</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This is the issuer ID of the IDP.
|
|
||||||
<emphasis>REQUIRED.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>signaturesRequired</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
If set to true, the client adapter will sign every document
|
|
||||||
it sends to the IDP. Also, the client will expect that the IDP
|
|
||||||
will be signing an documents sent to it. This switch sets
|
|
||||||
the default for all request and response types, but you will see
|
|
||||||
later that you have some fine grain control over this.
|
|
||||||
<emphasis>OPTIONAL.</emphasis>
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>signatureAlgorithm</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This is the signature algorithm that the IDP expects signed documents
|
|
||||||
to use
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. The default value is RSA_SHA256, but
|
|
||||||
you can also use RSA_SHA1, RSA_256, RSA_512, and DSA_SHA1.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>signatureCanonicalizationMethod</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This is the signature canonicalization method that the IDP expects signed documents
|
|
||||||
to use
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. The default value is <literal>http://www.w3.org/2001/10/xml-exc-c14n#</literal>
|
|
||||||
and should be good for most IDPs.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>IDP SingleSignOnService sub element</title>
|
|
||||||
<para>
|
|
||||||
The <literal>SignleSignOnService</literal> sub element defines the
|
|
||||||
login SAML endpoint of the IDP.
|
|
||||||
</para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<SingleSignOnService signRequest="true"
|
|
||||||
validateResponseSignature="true"
|
|
||||||
requestBinding="post"
|
|
||||||
bindingUrl="url"/>
|
|
||||||
]]></programlisting>
|
|
||||||
<para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>signRequest</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Should the client sign authn requests?
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. Defaults to whatever the
|
|
||||||
IDP <literal>signaturesRequired</literal> element value is.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>validateResponseSignature</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Should the client expect the IDP to sign the assertion response document
|
|
||||||
sent back from an auhtn request?
|
|
||||||
<emphasis>OPTIONAL.</emphasis> Defaults to whatever the
|
|
||||||
IDP <literal>signaturesRequired</literal> element value is.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>requestBinding</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This is the SAML binding type used for communicating with the IDP
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. The default value is POST, but
|
|
||||||
you can set it to REDIRECT as well.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>responseBinding</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
SAML allows the client to request what binding type it wants authn responses
|
|
||||||
to use. The values of this can be POST or REDIRECT
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. The default is that the client will not request
|
|
||||||
a specific binding type for responses.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>bindingUrl</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This is the URL for the ID login service that the client will send requests to.
|
|
||||||
<emphasis>REQUIRED.</emphasis>.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section> <section>
|
|
||||||
<title>IDP SingleLogoutService sub element</title>
|
|
||||||
<para>
|
|
||||||
The <literal>SingleLogoutService</literal> sub element defines the
|
|
||||||
logout SAML endpoint of the IDP.
|
|
||||||
</para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<SingleLogoutService validateRequestSignature="true"
|
|
||||||
validateResponseSignature="true"
|
|
||||||
signRequest="true"
|
|
||||||
signResponse="true"
|
|
||||||
requestBinding="redirect"
|
|
||||||
responseBinding="post"
|
|
||||||
postBindingUrl="posturl"
|
|
||||||
redirectBindingUrl="redirecturl">
|
|
||||||
]]></programlisting>
|
|
||||||
<para>
|
|
||||||
<variablelist>
|
|
||||||
<varlistentry>
|
|
||||||
<term>signRequest</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Should the client sign logout requests it makes to the IDP?
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. Defaults to whatever the
|
|
||||||
IDP <literal>signaturesRequired</literal> element value is.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>signResponse</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Should the client sign logout responses it sends to the IDP requests?
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. Defaults to whatever the
|
|
||||||
IDP <literal>signaturesRequired</literal> element value is.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>validateRequestSignature</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Should the client expect signed logout request documents from the IDP?
|
|
||||||
<emphasis>OPTIONAL.</emphasis> Defaults to whatever the
|
|
||||||
IDP <literal>signaturesRequired</literal> element value is.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>validateResponseSignature</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Should the client expect signed logout response documents from the IDP?
|
|
||||||
<emphasis>OPTIONAL.</emphasis> Defaults to whatever the
|
|
||||||
IDP <literal>signaturesRequired</literal> element value is.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>requestBinding</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This is the SAML binding type used for communicating SAML requests to the IDP
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. The default value is POST, but
|
|
||||||
you can set it to REDIRECT as well.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>responseBinding</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This is the SAML binding type used for communicating SAML responses to the IDP
|
|
||||||
The values of this can be POST or REDIRECT
|
|
||||||
<emphasis>OPTIONAL.</emphasis>. The default value is POST, but
|
|
||||||
you can set it to REDIRECT as well.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>postBindingUrl</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This is the URL for the IDP's logout service when using the POST binding.
|
|
||||||
<emphasis>REQUIRED</emphasis> if using the POST binding at all.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
<varlistentry>
|
|
||||||
<term>redirectBindingUrl</term>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
This is the URL for the IDP's logout service when using the REDIRECT binding.
|
|
||||||
<emphasis>REQUIRED</emphasis> if using the REDIRECT binding at all.
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
</varlistentry>
|
|
||||||
</variablelist>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>IDP Keys subelement</title>
|
|
||||||
<para>
|
|
||||||
The Keys sub element of IDP is only used to define the certificate or
|
|
||||||
public key to use to verify documents signed by the IDP. It is defined
|
|
||||||
in the same way as the <link linkend="sp_keys">SP's Key's element</link>. But
|
|
||||||
again, you only have to define one certificate or public key reference.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</chapter>
|
|
|
@ -1,59 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="adapter_error_handling">
|
|
||||||
<title>Error Handling</title>
|
|
||||||
<para>
|
|
||||||
Keycloak has some error handling facilities for servlet based client adapters. When an error is encountered in
|
|
||||||
authentication, keycloak will call <literal>HttpServletResponse.sendError()</literal>. You can set up an error-page
|
|
||||||
within your <literal>web.xml</literal> file to handle the error however you want. Keycloak may throw
|
|
||||||
400, 401, 403, and 500 errors.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<error-page>
|
|
||||||
<error-code>404</error-code>
|
|
||||||
<location>/ErrorHandler</location>
|
|
||||||
</error-page>]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Keycloak also sets an <literal>HttpServletRequest</literal> attribute that you can retrieve. The attribute name
|
|
||||||
is <literal>org.keycloak.adapters.spi.AuthenticationError</literal>. Typecast this object to:
|
|
||||||
<literal>org.keycloak.adapters.saml.SamlAuthenticationError</literal>. This class can tell you exactly what happened.
|
|
||||||
If this attribute is not set, then the adapter was not responsible for the error code.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
public class SamlAuthenticationError implements AuthenticationError {
|
|
||||||
public static enum Reason {
|
|
||||||
EXTRACTION_FAILURE,
|
|
||||||
INVALID_SIGNATURE,
|
|
||||||
ERROR_STATUS
|
|
||||||
}
|
|
||||||
|
|
||||||
public Reason getReason() {
|
|
||||||
return reason;
|
|
||||||
}
|
|
||||||
public StatusResponseType getStatus() {
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,126 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="assertions">
|
|
||||||
<title>Obtaining Assertion Attributes</title>
|
|
||||||
<para>
|
|
||||||
After a successful SAML login, your application code may want to obtain attribute values passed with the SAML assertion.
|
|
||||||
<literal>HttpServletRequest.getUserPrincipal</literal> returns a Principal object that you can typecast into a
|
|
||||||
Keycloak specific class called <literal>org.keycloak.adapters.saml.SamlPrincipal</literal>. This object allows
|
|
||||||
you to look at the raw assertion and also has convenience functions to look up attribute values.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
package org.keycloak.adapters.saml;
|
|
||||||
|
|
||||||
public class SamlPrincipal implements Serializable, Principal {
|
|
||||||
/**
|
|
||||||
* Get full saml assertion
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public AssertionType getAssertion() {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get SAML subject sent in assertion
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getSamlSubject() {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Subject nameID format
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getNameIDFormat() {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getName() {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience function that gets Attribute value by attribute name
|
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public List<String> getAttributes(String name) {
|
|
||||||
...
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience function that gets Attribute value by attribute friendly name
|
|
||||||
*
|
|
||||||
* @param friendlyName
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public List<String> getFriendlyAttributes(String friendlyName) {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience function that gets first value of an attribute by attribute name
|
|
||||||
*
|
|
||||||
* @param name
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getAttribute(String name) {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Convenience function that gets first value of an attribute by attribute name
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param friendlyName
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public String getFriendlyAttribute(String friendlyName) {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get set of all assertion attribute names
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Set<String> getAttributeNames() {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get set of all assertion friendly attribute names
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public Set<String> getFriendlyNames() {
|
|
||||||
...
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,25 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="debugging">
|
|
||||||
<title>Troubleshooting</title>
|
|
||||||
<para>
|
|
||||||
The best way to troubleshoot some problems is to turn on debugging for saml in both the client adapter and the keycloak server.
|
|
||||||
To do this turn on debugging int the <literal>org.keycloak.saml</literal> package to <literal>debug</literal> in your log4j or other
|
|
||||||
logging framework. Turning this on allows you to see the SAML requests and response documents being sent to and from the server.
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,24 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="idp-reg">
|
|
||||||
<title>Registering with an IDP</title>
|
|
||||||
<para>
|
|
||||||
For each servlet based adapter, the endpoint you register for the assert consumer service url and and single logout service
|
|
||||||
must be the base url of your servlet application with <literal>/saml</literal> appended to it i.e. https://example.com/contextPath/saml
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,293 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="jboss-adapter">
|
|
||||||
<title>JBoss/Wildfly Adapter</title>
|
|
||||||
<para>
|
|
||||||
To be able to secure WAR apps deployed on JBoss EAP 6.x or Wildfly, you must install and
|
|
||||||
configure the Keycloak SAML Adapter Subsystem. You then provide a keycloak
|
|
||||||
config, <literal>/WEB-INF/keycloak-saml.xml</literal> file in your WAR and change the auth-method to KEYCLOAK-SAML within web.xml.
|
|
||||||
Both methods are described in this section.
|
|
||||||
</para>
|
|
||||||
<section id="jboss-adapter-installation">
|
|
||||||
<title>Adapter Installation</title>
|
|
||||||
<para>
|
|
||||||
SAML 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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Install on Wildfly 9 or 10:
|
|
||||||
<programlisting>
|
|
||||||
$ cd $WILDFLY_HOME
|
|
||||||
$ unzip keycloak-saml-wildfly-adapter-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Install on JBoss EAP 6.x:
|
|
||||||
<programlisting>
|
|
||||||
$ cd $JBOSS_HOME
|
|
||||||
$ unzip keycloak-saml-eap6-adapter-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
This zip file creates new JBoss Modules specific to the Wildfly Keycloak SAML Adapter within your Wildfly distro.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
After adding the Keycloak modules, you must then enable the Keycloak SAML Subsystem within your app server's server configuration:
|
|
||||||
<literal>domain.xml</literal> or <literal>standalone.xml</literal>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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:
|
|
||||||
<programlisting>
|
|
||||||
$ cd $JBOSS_HOME/bin
|
|
||||||
$ jboss-cli.sh -c --file=adapter-install-saml.cli
|
|
||||||
</programlisting>
|
|
||||||
The script will add the extension, subsystem, and optional security-domain as described below.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<server xmlns="urn:jboss:domain:1.4">
|
|
||||||
|
|
||||||
<extensions>
|
|
||||||
<extension module="org.keycloak.keycloak-saml-adapter-subsystem"/>
|
|
||||||
...
|
|
||||||
</extensions>
|
|
||||||
|
|
||||||
<profile>
|
|
||||||
<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1"/>
|
|
||||||
...
|
|
||||||
</profile>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
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:
|
|
||||||
</para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Required Per WAR Configuration</title>
|
|
||||||
<para>
|
|
||||||
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The first thing you must do is create
|
|
||||||
a <literal>keycloak-saml.xml</literal> adapter config file within the <literal>WEB-INF</literal> directory
|
|
||||||
of your WAR. The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
|
|
||||||
section.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Next you must set the <literal>auth-method</literal> to <literal>KEYCLOAK-SAML</literal> in <literal>web.xml</literal>. 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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<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-SAML</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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
<section>
|
|
||||||
<title>Securing WARs via Keycloak SAML Subsystem</title>
|
|
||||||
<para>
|
|
||||||
You do not have to crack open a WAR to secure it with Keycloak. Alternatively, you can externally secure
|
|
||||||
it via the Keycloak SAML Adapter Subsystem. While you don't have to specify KEYCLOAK-SAML as an <literal>auth-method</literal>,
|
|
||||||
you still have to define the <literal>security-constraints</literal> in <literal>web.xml</literal>. You do
|
|
||||||
not, however, have to create a <literal>WEB-INF/keycloak-saml.xml</literal> file. This metadata is instead defined
|
|
||||||
within XML in your server's <literal>domain.xml</literal> or <literal>standalone.xml</literal> subsystem
|
|
||||||
configuration section.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<extensions>
|
|
||||||
<extension module="org.keycloak.keycloak-saml-adapter-subsystem"/>
|
|
||||||
</extensions>
|
|
||||||
|
|
||||||
<profile>
|
|
||||||
<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1">
|
|
||||||
<secure-deployment name="WAR MODULE NAME.war">
|
|
||||||
<SP entityID="APPLICATION URL">
|
|
||||||
...
|
|
||||||
</SP>
|
|
||||||
</secure-deployment>
|
|
||||||
</subsystem>
|
|
||||||
</profile>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The <literal>secure-deployment</literal> <literal>name</literal> attribute identifies the WAR you want
|
|
||||||
to secure. Its value is the <literal>module-name</literal> defined in <literal>web.xml</literal> with
|
|
||||||
<literal>.war</literal> appended. The rest of the configuration uses the same XML syntax as
|
|
||||||
<literal>keycloak-saml.xml</literal> configuration defined in <link linkend='adapter-config'>general adapter configuration</link>.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
An example configuration:
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<subsystem xmlns="urn:jboss:domain:keycloak-saml:1.1">
|
|
||||||
<secure-deployment name="saml-post-encryption.war">
|
|
||||||
<SP entityID="http://localhost:8080/sales-post-enc/"
|
|
||||||
sslPolicy="EXTERNAL"
|
|
||||||
nameIDPolicyFormat="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
|
||||||
logoutPage="/logout.jsp"
|
|
||||||
forceAuthentication="false">
|
|
||||||
<Keys>
|
|
||||||
<Key signing="true" encryption="true">
|
|
||||||
<KeyStore resource="/WEB-INF/keystore.jks" password="store123">
|
|
||||||
<PrivateKey alias="http://localhost:8080/sales-post-enc/" password="test123"/>
|
|
||||||
<Certificate alias="http://localhost:8080/sales-post-enc/"/>
|
|
||||||
</KeyStore>
|
|
||||||
</Key>
|
|
||||||
</Keys>
|
|
||||||
<PrincipalNameMapping policy="FROM_NAME_ID"/>
|
|
||||||
<RoleIdentifiers>
|
|
||||||
<Attribute name="Role"/>
|
|
||||||
</RoleIdentifiers>
|
|
||||||
<IDP entityID="idp">
|
|
||||||
<SingleSignOnService signRequest="true"
|
|
||||||
validateResponseSignature="true"
|
|
||||||
requestBinding="POST"
|
|
||||||
bindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
|
|
||||||
|
|
||||||
<SingleLogoutService
|
|
||||||
validateRequestSignature="true"
|
|
||||||
validateResponseSignature="true"
|
|
||||||
signRequest="true"
|
|
||||||
signResponse="true"
|
|
||||||
requestBinding="POST"
|
|
||||||
responseBinding="POST"
|
|
||||||
postBindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"
|
|
||||||
redirectBindingUrl="http://localhost:8080/auth/realms/saml-demo/protocol/saml"/>
|
|
||||||
<Keys>
|
|
||||||
<Key signing="true" >
|
|
||||||
<KeyStore resource="/WEB-INF/keystore.jks" password="store123">
|
|
||||||
<Certificate alias="saml-demo"/>
|
|
||||||
</KeyStore>
|
|
||||||
</Key>
|
|
||||||
</Keys>
|
|
||||||
</IDP>
|
|
||||||
</SP>
|
|
||||||
</secure-deployment>
|
|
||||||
</subsystem>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,66 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="jetty8-adapter">
|
|
||||||
<title>Jetty 8.1.x SAML Adapter</title>
|
|
||||||
<para>
|
|
||||||
Keycloak has a separate SAML 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.
|
|
||||||
</para>
|
|
||||||
<section id="jetty8-adapter-installation">
|
|
||||||
<title>Adapter Installation</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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!
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
$ cd $JETTY_HOME
|
|
||||||
$ unzip keycloak-saml-jetty81-adapter-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Next, you will have to enable the keycloak option. Edit start.ini and add keycloak to the options
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
#===========================================================
|
|
||||||
# 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
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Required Per WAR Configuration</title>
|
|
||||||
<para>
|
|
||||||
Enabling Keycloak for your WARs is the same as the Jetty 9.x adapter. See <link linkend="jetty9_per_war">Required Per WAR Configuration</link>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,123 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="jetty9-adapter">
|
|
||||||
<title>Jetty 9.x SAML Adapters</title>
|
|
||||||
<para>
|
|
||||||
Keycloak has a separate SAML adapter for Jetty 9.x. You then have to provide some extra configuration in each WAR you deploy to
|
|
||||||
Jetty. Let's go over these steps.
|
|
||||||
</para>
|
|
||||||
<section id="jetty9-adapter-installation">
|
|
||||||
<title>Adapter Installation</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
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!
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
$ cd $JETTY_HOME
|
|
||||||
$ unzip keycloak-saml-jetty92-adapter-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Next, you will have to enable the keycloak module for your jetty.base.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
$ cd your-base
|
|
||||||
$ java -jar $JETTY_HOME/start.jar --add-to-startd=keycloak
|
|
||||||
</programlisting>
|
|
||||||
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section id="jetty9_per_war">
|
|
||||||
<title>Required Per WAR Configuration</title>
|
|
||||||
<para>
|
|
||||||
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The first thing you must do is create a <literal>WEB-INF/jetty-web.xml</literal> file in your WAR package. This is
|
|
||||||
a Jetty specific config file and you must define a Keycloak specific authenticator within it.
|
|
||||||
</para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<?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.saml.jetty.KeycloakSamlAuthenticator">
|
|
||||||
</New>
|
|
||||||
</Set>
|
|
||||||
</Get>
|
|
||||||
</Configure>]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
Next you must create
|
|
||||||
a <literal>keycloak-saml.xml</literal> adapter config file within the <literal>WEB-INF</literal> directory
|
|
||||||
of your WAR. The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
|
|
||||||
section.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Finally you must specify both a <literal>login-config</literal> and use standard servlet security to specify
|
|
||||||
role-base constraints on your URLs. Here's an example:
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
|
@ -1,27 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter>
|
|
||||||
<title>Logout</title>
|
|
||||||
<para>
|
|
||||||
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 any url of your web application that has
|
|
||||||
a security constraing and pass in a query parameter GLO, i.e. <literal>http://myapp?GLO=true</literal>.
|
|
||||||
This will log you out if you have an SSO session with your browser.
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,73 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="multi_tenancy">
|
|
||||||
<title>Multi Tenancy</title>
|
|
||||||
<para>
|
|
||||||
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 <literal>keycloak.json</literal> files.
|
|
||||||
For this case, there are two possible solutions:
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
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.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
A WAR file deployed once (possibly in a cluster), that decides which realm to authenticate against based on the request parameters.
|
|
||||||
This scenario is suitable when there are an undefined number of realms. One example would be a SaaS provider that have only one deployment
|
|
||||||
(perhaps in a cluster) serving several companies, differentiating between clients based on the hostname
|
|
||||||
(<literal>client1.acme.com</literal>, <literal>client2.acme.com</literal>) or path (<literal>/app/client1/</literal>,
|
|
||||||
<literal>/app/client2/</literal>) or even via a special HTTP Header.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
|
|
||||||
This chapter of the reference guide focus on this second scenario.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
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:
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
Add a context parameter to the <literal>web.xml</literal>, named <literal>keycloak.config.resolver</literal>.
|
|
||||||
The value of this property should be the fully qualified name of the class extending
|
|
||||||
<literal>org.keycloak.adapters.KeycloakConfigResolver</literal>.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
A concrete implementation of <literal>org.keycloak.adapters.KeycloakConfigResolver</literal>. Keycloak will call the
|
|
||||||
<literal>resolve(org.keycloak.adapters.spi.HttpFacade.Request)</literal> method and expects a complete
|
|
||||||
<literal>org.keycloak.adapters.KeycloakDeployment</literal> in response. Note that Keycloak will call this for every request,
|
|
||||||
so, take the usual performance precautions.
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
</itemizedlist>
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
An implementation of this feature can be found in the examples.
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,26 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter>
|
|
||||||
<title>Overview</title>
|
|
||||||
<para>
|
|
||||||
This document describes the Keycloak SAML client adapter and how it can be configured for a variety of platforms.
|
|
||||||
The Keycloak SAML client adapter is a standalone component that provides generic SAML 2.0 support for your web applications.
|
|
||||||
There are no Keycloak server extensions built into it. As long as the IDP you are talking to supports standard SAML, the
|
|
||||||
Keycloak SAML client adapter should be able to integrate with it.
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
|
@ -1,84 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter>
|
|
||||||
<title>Java Servlet Filter Adapter</title>
|
|
||||||
<para>
|
|
||||||
If you want to use SAML 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.
|
|
||||||
</para>
|
|
||||||
<warning>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
</warning>
|
|
||||||
<warning>
|
|
||||||
<para>
|
|
||||||
Backchannel logout does not currently work when you have a clustered application that uses the SAML filter.
|
|
||||||
</para>
|
|
||||||
</warning>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<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.saml.servlet.SamlFilter</filter-class>
|
|
||||||
</filter>
|
|
||||||
<filter-mapping>
|
|
||||||
<filter-name>Keycloak Filter</filter-name>
|
|
||||||
<url-pattern>/*</url-pattern>
|
|
||||||
</filter-mapping>
|
|
||||||
</web-app>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You can define multiple filter mappings if you have various different secure and unsecure url patterns.
|
|
||||||
</para>
|
|
||||||
<warning>
|
|
||||||
<para>
|
|
||||||
You must have a filter mapping that covers <literal>/saml</literal>. This mapping covers all server callbacks.
|
|
||||||
</para>
|
|
||||||
</warning>
|
|
||||||
<para>
|
|
||||||
When registering SPs with an IDP, you must register <literal>http[s]://hostname/{context-root}/saml</literal> as
|
|
||||||
your Assert Consumer Service URL and Single Logout Service URL.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
To use this filter, include this maven artifact in your WAR poms
|
|
||||||
</para>
|
|
||||||
<programlisting><![CDATA[
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-servlet-filter-adapter</artifactId>
|
|
||||||
<version>&project.version;</version>
|
|
||||||
</dependency>
|
|
||||||
]]></programlisting>
|
|
||||||
</chapter>
|
|
|
@ -1,109 +0,0 @@
|
||||||
<!--
|
|
||||||
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
|
||||||
~ and other contributors as indicated by the @author tags.
|
|
||||||
~
|
|
||||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
~ you may not use this file except in compliance with the License.
|
|
||||||
~ You may obtain a copy of the License at
|
|
||||||
~
|
|
||||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
~
|
|
||||||
~ Unless required by applicable law or agreed to in writing, software
|
|
||||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
~ See the License for the specific language governing permissions and
|
|
||||||
~ limitations under the License.
|
|
||||||
-->
|
|
||||||
|
|
||||||
<chapter id="tomcat-adapter">
|
|
||||||
<title>Tomcat 6, 7 and 8 SAML adapters</title>
|
|
||||||
<para>
|
|
||||||
To be able to secure WAR apps deployed on Tomcat 6, 7 and 8 you must install the Keycloak Tomcat 6, 7 or 8 SAML 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.
|
|
||||||
</para>
|
|
||||||
<section id="tomcat-adapter-installation">
|
|
||||||
<title>Adapter Installation</title>
|
|
||||||
<para>
|
|
||||||
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.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
You must unzip the adapter distro into Tomcat's <literal>lib/</literal> directory. Including
|
|
||||||
adapter's jars within your WEB-INF/lib directory will not work! The Keycloak SAML adapter is implemented as a Valve
|
|
||||||
and valve code must reside in Tomcat's main lib/ directory.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
$ cd $TOMCAT_HOME/lib
|
|
||||||
$ unzip keycloak-saml-tomcat6-adapter-dist.zip
|
|
||||||
or
|
|
||||||
$ unzip keycloak-saml-tomcat7-adapter-dist.zip
|
|
||||||
or
|
|
||||||
$ unzip keycloak-saml-tomcat8-adapter-dist.zip
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Required Per WAR Configuration</title>
|
|
||||||
<para>
|
|
||||||
This section describes how to secure a WAR directly by adding config and editing files within your WAR package.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
The first thing you must do is create a <literal>META-INF/context.xml</literal> file in your WAR package. This is
|
|
||||||
a Tomcat specific config file and you must define a Keycloak specific Valve.
|
|
||||||
</para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<Context path="/your-context-path">
|
|
||||||
<Valve className="org.keycloak.adapters.saml.tomcat.SamlAuthenticatorValve"/>
|
|
||||||
</Context>]]>
|
|
||||||
</programlisting>
|
|
||||||
<para>
|
|
||||||
Next you must create
|
|
||||||
a <literal>keycloak-saml.xml</literal> adapter config file within the <literal>WEB-INF</literal> directory
|
|
||||||
of your WAR. The format of this config file is describe in the <link linkend='adapter-config'>general adapter configuration</link>
|
|
||||||
section.
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
Finally you must specify both a <literal>login-config</literal> and use standard servlet security to specify
|
|
||||||
role-base constraints on your URLs. Here's an example:
|
|
||||||
</para>
|
|
||||||
<para>
|
|
||||||
<programlisting>
|
|
||||||
<![CDATA[
|
|
||||||
<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>
|
|
||||||
]]>
|
|
||||||
</programlisting>
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
3
pom.xml
|
@ -1081,7 +1081,7 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-docs-dist</artifactId>
|
<artifactId>keycloak-api-docs-dist</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
<type>zip</type>
|
<type>zip</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
@ -1395,7 +1395,6 @@
|
||||||
<profile>
|
<profile>
|
||||||
<id>jboss-release</id>
|
<id>jboss-release</id>
|
||||||
<modules>
|
<modules>
|
||||||
<module>docbook</module>
|
|
||||||
<module>distribution</module>
|
<module>distribution</module>
|
||||||
</modules>
|
</modules>
|
||||||
</profile>
|
</profile>
|
||||||
|
|