Compare commits
131
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f402fb1a55 | ||
|
|
dc64260c31 | ||
|
|
d26712a1d4 | ||
|
|
db8935444f | ||
|
|
5b769ed829 | ||
|
|
7585b5ab49 | ||
|
|
95287b2faa | ||
|
|
d707133742 | ||
|
|
c0e0391a87 | ||
|
|
7139c683cc | ||
|
|
19939068d5 | ||
|
|
9ffe8287a7 | ||
|
|
be74476de1 | ||
|
|
45c5fa28fc | ||
|
|
a4bed6e433 | ||
|
|
575943fbb4 | ||
|
|
46fa593d4a | ||
|
|
9819d9997e | ||
|
|
cdb0d6b5bf | ||
|
|
ae86028e6e | ||
|
|
0cfe4c694a | ||
|
|
034735cd64 | ||
|
|
7567fea6c1 | ||
|
|
3af087e36f | ||
|
|
45e04944a4 | ||
|
|
0706e6f778 | ||
|
|
655aa6194e | ||
|
|
862baf2d5b | ||
|
|
fc148207ce | ||
|
|
095561cb29 | ||
|
|
9bd3f43ce5 | ||
|
|
4ea49a14ea | ||
|
|
12c155cd9c | ||
|
|
0249adbacc | ||
|
|
d69b01ad3c | ||
|
|
e7dbfecdb0 | ||
|
|
37b396c106 | ||
|
|
b03dddccf4 | ||
|
|
1b7e019042 | ||
|
|
33c47c8441 | ||
|
|
8e5325b5d5 | ||
|
|
e37c6f262b | ||
|
|
5bebd31b0c | ||
|
|
cc76dcf58b | ||
|
|
d0b614fdcf | ||
|
|
c325b9f04d | ||
|
|
c311f47d5d | ||
|
|
aa95ff6d84 | ||
|
|
de566ec741 | ||
|
|
9c484b9938 | ||
|
|
7ce1502bc5 | ||
|
|
78d5b09b4b | ||
|
|
fff8ae9f8a | ||
|
|
e62858cefd | ||
|
|
526e25abc7 | ||
|
|
dc94fac9f5 | ||
|
|
110783ff2f | ||
|
|
795b1d2893 | ||
|
|
b7dae5c88f | ||
|
|
37d6a79205 | ||
|
|
c4892428ae | ||
|
|
2b1ae89608 | ||
|
|
2a7fc53300 | ||
|
|
f4c06b7cd0 | ||
|
|
0f4953dcd2 | ||
|
|
c7b0c4fb05 | ||
|
|
6aa0cb5e3d | ||
|
|
181c1c8b5b | ||
|
|
74ba508e4a | ||
|
|
992455e273 | ||
|
|
6c8013182b | ||
|
|
45a1f4361e | ||
|
|
39daeca09c | ||
|
|
0c73e67372 | ||
|
|
628437c146 | ||
|
|
528196f786 | ||
|
|
ec1499cdf6 | ||
|
|
019bb558d1 | ||
|
|
6462da2c72 | ||
|
|
d1119a1c26 | ||
|
|
53e18b3ebe | ||
|
|
f97b71c207 | ||
|
|
a367473386 | ||
|
|
f157dd7915 | ||
|
|
2eb2ec50e3 | ||
|
|
9d63482759 | ||
|
|
ebf85cf04b | ||
|
|
3a9a7976fa | ||
|
|
ec9ce6ef2f | ||
|
|
30cfabb08d | ||
|
|
a280c11897 | ||
|
|
358f968429 | ||
|
|
e39ea2adaf | ||
|
|
8a1b7e39af | ||
|
|
af3efa547c | ||
|
|
fdbe5c879e | ||
|
|
3be930f6cf | ||
|
|
bcbb658ae4 | ||
|
|
512a68c5fa | ||
|
|
1eaafcd3d9 | ||
|
|
2a33b177d5 | ||
|
|
1cbf5a5d99 | ||
|
|
28a56289d9 | ||
|
|
08be04b337 | ||
|
|
519d051eb0 | ||
|
|
fe10913780 | ||
|
|
0082892f7c | ||
|
|
3a9de56f9c | ||
|
|
e174802b0d | ||
|
|
e42fe6fb23 | ||
|
|
6cf42db584 | ||
|
|
2186fe32a9 | ||
|
|
7886d2aecc | ||
|
|
2030ab159d | ||
|
|
ee62f5b1a1 | ||
|
|
0755cb6996 | ||
|
|
1650cb33c6 | ||
|
|
c34b3a8017 | ||
|
|
000a85fe99 | ||
|
|
17a8a92bb3 | ||
|
|
ce1fd8eedc | ||
|
|
919a4c661b | ||
|
|
cf11911f6b | ||
|
|
f620b04656 | ||
|
|
a3f5ace895 | ||
|
|
fbe26e28f1 | ||
|
|
9169a3df76 | ||
|
|
5ee0827a84 | ||
|
|
c4462c6de7 | ||
|
|
4c6f1b6a60 | ||
|
|
6c04e26376 |
No files matched your search
@@ -0,0 +1,8 @@
|
||||
language: java
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.m2
|
||||
sudo: false
|
||||
|
||||
after_script: 'misc/.travis/after.sh'
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+20
-14
@@ -7,8 +7,11 @@ import liquibase.exception.CustomChangeException;
|
||||
import liquibase.exception.SetupException;
|
||||
import liquibase.exception.ValidationErrors;
|
||||
import liquibase.resource.ResourceAccessor;
|
||||
import liquibase.snapshot.SnapshotGeneratorFactory;
|
||||
import liquibase.statement.SqlStatement;
|
||||
import liquibase.statement.core.UpdateStatement;
|
||||
import liquibase.structure.core.Schema;
|
||||
import liquibase.structure.core.Table;
|
||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||
|
||||
import java.sql.Connection;
|
||||
@@ -29,25 +32,28 @@ public class AddRealmCodeSecret implements CustomSqlChange {
|
||||
sb.append("Generated codeSecret for realms: ");
|
||||
|
||||
Connection connection = ((JdbcConnection) (database.getConnection())).getWrappedConnection();
|
||||
ResultSet resultSet = connection.createStatement().executeQuery("SELECT ID FROM REALM WHERE CODE_SECRET IS NULL");
|
||||
|
||||
ArrayList<SqlStatement> statements = new ArrayList<SqlStatement>();
|
||||
while (resultSet.next()) {
|
||||
String id = resultSet.getString(1);
|
||||
|
||||
UpdateStatement statement = new UpdateStatement(null, null, "REALM")
|
||||
.addNewColumnValue("CODE_SECRET", KeycloakModelUtils.generateCodeSecret())
|
||||
.setWhereClause("ID='" + id + "'");
|
||||
statements.add(statement);
|
||||
String correctedTableName = database.correctObjectName("REALM", Table.class);
|
||||
if (SnapshotGeneratorFactory.getInstance().has(new Table().setName(correctedTableName), database)) {
|
||||
ResultSet resultSet = connection.createStatement().executeQuery("SELECT ID FROM REALM WHERE CODE_SECRET IS NULL");
|
||||
while (resultSet.next()) {
|
||||
String id = resultSet.getString(1);
|
||||
|
||||
if (!resultSet.isFirst()) {
|
||||
sb.append(", ");
|
||||
UpdateStatement statement = new UpdateStatement(null, null, correctedTableName)
|
||||
.addNewColumnValue("CODE_SECRET", KeycloakModelUtils.generateCodeSecret())
|
||||
.setWhereClause("ID='" + id + "'");
|
||||
statements.add(statement);
|
||||
|
||||
if (!resultSet.isFirst()) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(id);
|
||||
}
|
||||
sb.append(id);
|
||||
}
|
||||
|
||||
if (!statements.isEmpty()) {
|
||||
confirmationMessage = sb.toString();
|
||||
if (!statements.isEmpty()) {
|
||||
confirmationMessage = sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
return statements.toArray(new SqlStatement[statements.size()]);
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
|
||||
<changeSet author="sthorger@redhat.com" id="1.1.0.Final">
|
||||
<renameColumn tableName="EVENT_ENTITY" oldColumnName="TIME" newColumnName="EVENT_TIME" columnDataType="BIGINT"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
||||
@@ -2,4 +2,5 @@
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.2.xsd">
|
||||
<include file="META-INF/jpa-changelog-1.0.0.Final.xml"/>
|
||||
<include file="META-INF/jpa-changelog-1.1.0.Beta1.xml"/>
|
||||
<include file="META-INF/jpa-changelog-1.1.0.Final.xml"/>
|
||||
</databaseChangeLog>
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+4
@@ -117,6 +117,10 @@ public class DefaultJpaConnectionProviderFactory implements JpaConnectionProvide
|
||||
logger.trace("Updating database");
|
||||
|
||||
JpaUpdaterProvider updater = session.getProvider(JpaUpdaterProvider.class);
|
||||
if (updater == null) {
|
||||
throw new RuntimeException("Can't update database: JPA updater provider not found");
|
||||
}
|
||||
|
||||
connection = getConnection();
|
||||
|
||||
if (databaseSchema.equals("update")) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ import org.keycloak.connections.mongo.api.types.MapperRegistry;
|
||||
import org.keycloak.connections.mongo.impl.EntityInfo;
|
||||
import org.keycloak.connections.mongo.impl.MongoStoreImpl;
|
||||
import org.keycloak.models.utils.reflection.Property;
|
||||
import org.keycloak.models.utils.reflection.Types;
|
||||
import org.keycloak.util.reflections.Types;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
</parent>
|
||||
<name>Connections Parent</name>
|
||||
<description/>
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -31,7 +31,7 @@ public class SkeletonKeyContextResolver implements ContextResolver<ObjectMapper>
|
||||
|
||||
@Override
|
||||
public ObjectMapper getContext(Class<?> type) {
|
||||
if (type.getPackage().getName().startsWith(getClass().getPackage().getName())) return mapper;
|
||||
if (type.getPackage() != null && type.getPackage().getName().startsWith(getClass().getPackage().getName())) return mapper;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+42
-1
@@ -4,18 +4,26 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<name>Keycloak Core</name>
|
||||
<packaging>jar</packaging>
|
||||
<description/>
|
||||
|
||||
<properties>
|
||||
<timestamp>${maven.build.timestamp}</timestamp>
|
||||
<maven.build.timestamp.format>yyyy-MM-dd HH:mm</maven.build.timestamp.format>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.*
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
net.iharder;version=${base64.version},
|
||||
*;resolution:=optional
|
||||
</keycloak.osgi.import>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
@@ -60,6 +68,39 @@
|
||||
<target>${maven.compiler.target}</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<!-- Adding OSGI metadata to the JAR without changing the packaging type. -->
|
||||
<plugin>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
<extensions>true</extensions>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>bundle-manifest</id>
|
||||
<phase>process-classes</phase>
|
||||
<goals>
|
||||
<goal>manifest</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@ public class AccessTokenResponse {
|
||||
@JsonProperty("expires_in")
|
||||
protected long expiresIn;
|
||||
|
||||
@JsonProperty("refresh_expires_in")
|
||||
protected long refreshExpiresIn;
|
||||
|
||||
@JsonProperty("refresh_token")
|
||||
protected String refreshToken;
|
||||
|
||||
@@ -46,6 +49,14 @@ public class AccessTokenResponse {
|
||||
this.expiresIn = expiresIn;
|
||||
}
|
||||
|
||||
public long getRefreshExpiresIn() {
|
||||
return refreshExpiresIn;
|
||||
}
|
||||
|
||||
public void setRefreshExpiresIn(long refreshExpiresIn) {
|
||||
this.refreshExpiresIn = refreshExpiresIn;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
@@ -8,29 +8,67 @@ import java.net.UnknownHostException;
|
||||
*/
|
||||
public class HostUtils {
|
||||
|
||||
// Best effort to find the most proper hostname of this server.
|
||||
public static String getHostName() {
|
||||
String jbossHostName = System.getProperty("jboss.host.name");
|
||||
if (jbossHostName != null) {
|
||||
return jbossHostName;
|
||||
} else {
|
||||
try {
|
||||
return InetAddress.getLocalHost().getHostName();
|
||||
} catch (UnknownHostException uhe) {
|
||||
throw new IllegalStateException(uhe);
|
||||
}
|
||||
}
|
||||
return getHostNameImpl().trim().toLowerCase();
|
||||
}
|
||||
|
||||
public static String getIpAddress() {
|
||||
try {
|
||||
String jbossHostName = System.getProperty("jboss.host.name");
|
||||
if (jbossHostName != null) {
|
||||
return InetAddress.getByName(jbossHostName).getHostAddress();
|
||||
} else {
|
||||
return java.net.InetAddress.getLocalHost().getHostAddress();
|
||||
}
|
||||
String hostname = getHostName();
|
||||
return InetAddress.getByName(hostname).getHostAddress();
|
||||
} catch (UnknownHostException uhe) {
|
||||
throw new IllegalStateException(uhe);
|
||||
}
|
||||
}
|
||||
|
||||
private static String getHostNameImpl() {
|
||||
// Return bind address if available
|
||||
String bindAddr = System.getProperty("jboss.bind.address");
|
||||
if (bindAddr != null && !bindAddr.trim().equals("0.0.0.0")) {
|
||||
return bindAddr;
|
||||
}
|
||||
|
||||
// Fallback to qualified name
|
||||
String qualifiedHostName = System.getProperty("jboss.qualified.host.name");
|
||||
if (qualifiedHostName != null) {
|
||||
return qualifiedHostName;
|
||||
}
|
||||
|
||||
// If not on jboss env, let's try other possible fallbacks
|
||||
// POSIX-like OSes including Mac should have this set
|
||||
qualifiedHostName = System.getenv("HOSTNAME");
|
||||
if (qualifiedHostName != null) {
|
||||
return qualifiedHostName;
|
||||
}
|
||||
|
||||
// Certain versions of Windows
|
||||
qualifiedHostName = System.getenv("COMPUTERNAME");
|
||||
if (qualifiedHostName != null) {
|
||||
return qualifiedHostName;
|
||||
}
|
||||
|
||||
try {
|
||||
return NetworkUtils.canonize(getLocalHost().getHostName());
|
||||
} catch (UnknownHostException uhe) {
|
||||
uhe.printStackTrace();
|
||||
return "unknown-host.unknown-domain";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Methods returns InetAddress for localhost
|
||||
*
|
||||
* @return InetAddress of the localhost
|
||||
* @throws UnknownHostException if localhost could not be resolved
|
||||
*/
|
||||
private static InetAddress getLocalHost() throws UnknownHostException {
|
||||
InetAddress addr;
|
||||
try {
|
||||
addr = InetAddress.getLocalHost();
|
||||
} catch (ArrayIndexOutOfBoundsException e) { //this is workaround for mac osx bug see AS7-3223 and JGRP-1404
|
||||
addr = InetAddress.getByName(null);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,446 @@
|
||||
package org.keycloak.util;
|
||||
|
||||
/*
|
||||
* JBoss, Home of Professional Open Source.
|
||||
* Copyright 2011, Red Hat, Inc., and individual contributors
|
||||
* as indicated by the @author tags. See the copyright.txt file in the
|
||||
* distribution for a full listing of individual contributors.
|
||||
*
|
||||
* This is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as
|
||||
* published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This software is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this software; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
||||
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
||||
*/
|
||||
|
||||
import java.net.Inet4Address;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* Utility methods related to networking.
|
||||
*
|
||||
* @author Brian Stansberry (c) 2011 Red Hat Inc.
|
||||
*/
|
||||
public class NetworkUtils {
|
||||
|
||||
private static final int MAX_GROUP_LENGTH = 4;
|
||||
private static final int IPV6_LEN = 8;
|
||||
private static final boolean can_bind_to_mcast_addr; // are we running on Linux ?
|
||||
|
||||
static {
|
||||
can_bind_to_mcast_addr = checkForLinux() || checkForSolaris() || checkForHp();
|
||||
}
|
||||
|
||||
public static String formatPossibleIpv6Address(String address) {
|
||||
if(address == null) {
|
||||
return null;
|
||||
}
|
||||
String ipv6Address;
|
||||
if (address.startsWith("[") && address.endsWith("]")) {
|
||||
ipv6Address = address.substring(0, address.lastIndexOf(']')).substring(1);
|
||||
} else {
|
||||
ipv6Address = address;
|
||||
}
|
||||
// Definitely not an IPv6, return untouched input.
|
||||
if (!mayBeIPv6Address(ipv6Address)) {
|
||||
return ipv6Address;
|
||||
}
|
||||
return '[' + canonize(ipv6Address) + ']';
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Convert IPv6 adress into RFC 5952 form.
|
||||
* E.g. 2001:db8:0:1:0:0:0:1 -> 2001:db8:0:1::1</p>
|
||||
*
|
||||
* <p>Method is null safe, and if IPv4 address or host name is passed to the
|
||||
* method it is returned wihout any processing.</p>
|
||||
*
|
||||
* <p>Method also supports IPv4 in IPv6 (e.g. 0:0:0:0:0:ffff:192.0.2.1 ->
|
||||
* ::ffff:192.0.2.1), and zone ID (e.g. fe80:0:0:0:f0f0:c0c0:1919:1234%4
|
||||
* -> fe80::f0f0:c0c0:1919:1234%4).</p>
|
||||
*
|
||||
* @param ipv6Address String representing valid IPv6 address.
|
||||
* @return String representing IPv6 in canonical form.
|
||||
* @throws IllegalArgumentException if IPv6 format is unacceptable.
|
||||
*/
|
||||
public static String canonize(String ipv6Address) throws IllegalArgumentException {
|
||||
|
||||
if (ipv6Address == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Definitely not an IPv6, return untouched input.
|
||||
if (!mayBeIPv6Address(ipv6Address)) {
|
||||
return ipv6Address;
|
||||
}
|
||||
|
||||
// Length without zone ID (%zone) or IPv4 address
|
||||
int ipv6AddressLength = ipv6Address.length();
|
||||
if (isIPv4AddressInIPv6(ipv6Address)) {
|
||||
// IPv4 in IPv6
|
||||
// e.g. 0:0:0:0:0:FFFF:127.0.0.1
|
||||
int lastColonPos = ipv6Address.lastIndexOf(":");
|
||||
int lastColonsPos = ipv6Address.lastIndexOf("::");
|
||||
if (lastColonsPos >= 0 && lastColonPos == lastColonsPos + 1) {
|
||||
// IPv6 part ends with two consecutive colons, last colon is part of IPv6 format.
|
||||
// e.g. ::127.0.0.1
|
||||
ipv6AddressLength = lastColonPos + 1;
|
||||
} else {
|
||||
// IPv6 part ends with only one colon, last colon is not part of IPv6 format.
|
||||
// e.g. ::FFFF:127.0.0.1
|
||||
ipv6AddressLength = lastColonPos;
|
||||
}
|
||||
} else if (ipv6Address.contains(":") && ipv6Address.contains("%")) {
|
||||
// Zone ID
|
||||
// e.g. fe80:0:0:0:f0f0:c0c0:1919:1234%4
|
||||
ipv6AddressLength = ipv6Address.lastIndexOf("%");
|
||||
}
|
||||
|
||||
StringBuilder result = new StringBuilder();
|
||||
char [][] groups = new char[IPV6_LEN][MAX_GROUP_LENGTH];
|
||||
int groupCounter = 0;
|
||||
int charInGroupCounter = 0;
|
||||
|
||||
// Index of the current zeroGroup, -1 means not found.
|
||||
int zeroGroupIndex = -1;
|
||||
int zeroGroupLength = 0;
|
||||
|
||||
// maximum length zero group, if there is more then one, then first one
|
||||
int maxZeroGroupIndex = -1;
|
||||
int maxZeroGroupLength = 0;
|
||||
|
||||
boolean isZero = true;
|
||||
boolean groupStart = true;
|
||||
|
||||
/*
|
||||
* Two consecutive colons, initial expansion.
|
||||
* e.g. 2001:db8:0:0:1::1 -> 2001:db8:0:0:1:0:0:1
|
||||
*/
|
||||
StringBuilder expanded = new StringBuilder(ipv6Address);
|
||||
int colonsPos = ipv6Address.indexOf("::");
|
||||
int length = ipv6AddressLength;
|
||||
int change = 0;
|
||||
|
||||
if (colonsPos >= 0 && colonsPos < ipv6AddressLength - 2) {
|
||||
int colonCounter = 0;
|
||||
for (int i = 0; i < ipv6AddressLength; i++) {
|
||||
if (ipv6Address.charAt(i) == ':') {
|
||||
colonCounter++;
|
||||
}
|
||||
}
|
||||
|
||||
if (colonsPos == 0) {
|
||||
expanded.insert(0, "0");
|
||||
change = change + 1;
|
||||
}
|
||||
|
||||
for (int i = 0; i < IPV6_LEN - colonCounter; i++) {
|
||||
expanded.insert(colonsPos + 1, "0:");
|
||||
change = change + 2;
|
||||
}
|
||||
|
||||
|
||||
if (colonsPos == ipv6AddressLength - 2) {
|
||||
expanded.setCharAt(colonsPos + change + 1, '0');
|
||||
} else {
|
||||
expanded.deleteCharAt(colonsPos + change + 1);
|
||||
change = change - 1;
|
||||
}
|
||||
length = length + change;
|
||||
}
|
||||
|
||||
|
||||
// Processing one char at the time
|
||||
for (int charCounter = 0; charCounter < length; charCounter++) {
|
||||
char c = expanded.charAt(charCounter);
|
||||
if (c >= 'A' && c <= 'F') {
|
||||
c = (char) (c + 32);
|
||||
}
|
||||
if (c != ':') {
|
||||
groups[groupCounter][charInGroupCounter] = c;
|
||||
if (!(groupStart && c == '0')) {
|
||||
++charInGroupCounter;
|
||||
groupStart = false;
|
||||
}
|
||||
if (c != '0') {
|
||||
isZero = false;
|
||||
}
|
||||
}
|
||||
if (c == ':' || charCounter == (length - 1)) {
|
||||
// We reached end of current group
|
||||
if (isZero) {
|
||||
++zeroGroupLength;
|
||||
if (zeroGroupIndex == -1) {
|
||||
zeroGroupIndex = groupCounter;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isZero || charCounter == (length - 1)) {
|
||||
// We reached end of zero group
|
||||
if (zeroGroupLength > maxZeroGroupLength) {
|
||||
maxZeroGroupLength = zeroGroupLength;
|
||||
maxZeroGroupIndex = zeroGroupIndex;
|
||||
}
|
||||
zeroGroupLength = 0;
|
||||
zeroGroupIndex = -1;
|
||||
}
|
||||
++groupCounter;
|
||||
charInGroupCounter = 0;
|
||||
isZero = true;
|
||||
groupStart = true;
|
||||
}
|
||||
}
|
||||
|
||||
int numberOfGroups = groupCounter;
|
||||
|
||||
// Output results
|
||||
for (groupCounter = 0; groupCounter < numberOfGroups; groupCounter++) {
|
||||
if (maxZeroGroupLength <= 1 || groupCounter < maxZeroGroupIndex
|
||||
|| groupCounter >= maxZeroGroupIndex + maxZeroGroupLength) {
|
||||
for (int j = 0; j < MAX_GROUP_LENGTH; j++) {
|
||||
if (groups[groupCounter][j] != 0) {
|
||||
result.append(groups[groupCounter][j]);
|
||||
}
|
||||
}
|
||||
if (groupCounter < (numberOfGroups - 1)
|
||||
&& (groupCounter != maxZeroGroupIndex - 1
|
||||
|| maxZeroGroupLength <= 1)) {
|
||||
result.append(':');
|
||||
}
|
||||
} else if (groupCounter == maxZeroGroupIndex) {
|
||||
result.append("::");
|
||||
}
|
||||
}
|
||||
|
||||
// Solve problem with three colons in IPv4 in IPv6 format
|
||||
// e.g. 0:0:0:0:0:0:127.0.0.1 -> :::127.0.0.1 -> ::127.0.0.1
|
||||
int resultLength = result.length();
|
||||
if (result.charAt(resultLength - 1) == ':' && ipv6AddressLength < ipv6Address.length()
|
||||
&& ipv6Address.charAt(ipv6AddressLength) == ':') {
|
||||
result.delete(resultLength - 1, resultLength);
|
||||
}
|
||||
|
||||
/*
|
||||
* Append IPv4 from IPv4-in-IPv6 format or Zone ID
|
||||
*/
|
||||
for (int i = ipv6AddressLength; i < ipv6Address.length(); i++) {
|
||||
result.append(ipv6Address.charAt(i));
|
||||
}
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Heuristic check if string might be an IPv6 address.
|
||||
*
|
||||
* @param input Any string or null
|
||||
* @return true, if input string contains only hex digits and at least two colons, before '.' or '%' character.
|
||||
*/
|
||||
private static boolean mayBeIPv6Address(String input) {
|
||||
if (input == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean result = false;
|
||||
int colonsCounter = 0;
|
||||
int length = input.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
char c = input.charAt(i);
|
||||
if (c == '.' || c == '%') {
|
||||
// IPv4 in IPv6 or Zone ID detected, end of checking.
|
||||
break;
|
||||
}
|
||||
if (!((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
|
||||
|| (c >= 'A' && c <= 'F') || c == ':')) {
|
||||
return false;
|
||||
} else if (c == ':') {
|
||||
colonsCounter++;
|
||||
}
|
||||
}
|
||||
if (colonsCounter >= 2) {
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Check if it is an IPv4 in IPv6 format.
|
||||
* e.g. 0:0:0:0:0:FFFF:127.0.0.1
|
||||
*
|
||||
* @param ipv6Address the address
|
||||
* @return true, if input string is an IPv4 address in IPv6 format.
|
||||
*/
|
||||
private static boolean isIPv4AddressInIPv6(String ipv6Address) {
|
||||
return (ipv6Address.contains(":") && ipv6Address.contains("."));
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats input address. For IPV4 returns simply host address, for IPV6 formats address according to <a
|
||||
* href="http://tools.ietf.org/html/rfc5952">RFC5952</a> rules. It does not embed IPV6 address in '[', ']', since those are part of IPV6 URI literal.
|
||||
*
|
||||
* @param inet
|
||||
* @return
|
||||
*/
|
||||
public static String formatAddress(InetAddress inet){
|
||||
if(inet == null){
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if(inet instanceof Inet4Address){
|
||||
return inet.getHostAddress();
|
||||
} else if (inet instanceof Inet6Address){
|
||||
byte[] byteRepresentation = inet.getAddress();
|
||||
int[] hexRepresentation = new int[IPV6_LEN];
|
||||
|
||||
for(int i=0;i < hexRepresentation.length;i++){
|
||||
hexRepresentation[i] = ( byteRepresentation[2*i] & 0xFF) << 8 | ( byteRepresentation[2*i+1] & 0xFF );
|
||||
}
|
||||
compactLongestZeroSequence(hexRepresentation);
|
||||
return formatAddress6(hexRepresentation);
|
||||
} else {
|
||||
return inet.getHostAddress();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts socket address into string literal, which has form: 'address:port'. Example:<br>
|
||||
* <ul>
|
||||
* <li>127.0.0.1:8080</li>
|
||||
* <li>dns.name.com:8080</li>
|
||||
* <li>[0fe:1::20]:8080</li>
|
||||
* <li>[::1]:8080</li>
|
||||
* </ul>
|
||||
* @param inet
|
||||
* @return
|
||||
*/
|
||||
public static String formatAddress(InetSocketAddress inet){
|
||||
if(inet == null){
|
||||
throw new NullPointerException();
|
||||
}
|
||||
StringBuilder result = new StringBuilder();
|
||||
if(inet.isUnresolved()){
|
||||
result.append(inet.getHostName());
|
||||
}else{
|
||||
result.append(formatPossibleIpv6Address(formatAddress(inet.getAddress())));
|
||||
}
|
||||
result.append(":").append(inet.getPort());
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts IPV6 int[] representation into valid IPV6 string literal. Sequence of '-1' values are converted into '::'.
|
||||
* @param hexRepresentation
|
||||
* @return
|
||||
*/
|
||||
private static String formatAddress6(int[] hexRepresentation){
|
||||
if(hexRepresentation == null){
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if(hexRepresentation.length != IPV6_LEN){
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
boolean inCompressedSection = false;
|
||||
for(int i = 0;i<hexRepresentation.length;i++){
|
||||
if(hexRepresentation[i] == -1){
|
||||
if(!inCompressedSection){
|
||||
inCompressedSection = true;
|
||||
if(i == 0){
|
||||
stringBuilder.append("::");
|
||||
} else {
|
||||
stringBuilder.append(':');
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inCompressedSection = false;
|
||||
stringBuilder.append(Integer.toHexString(hexRepresentation[i]));
|
||||
if(i+1<hexRepresentation.length){
|
||||
stringBuilder.append(":");
|
||||
}
|
||||
}
|
||||
}
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
|
||||
public static boolean isBindingToMulticastDressSupported() {
|
||||
return can_bind_to_mcast_addr;
|
||||
}
|
||||
|
||||
private static void compactLongestZeroSequence(int[] hexRepresentatoin){
|
||||
int bestRunStart = -1;
|
||||
int bestRunLen = -1;
|
||||
boolean inRun = false;
|
||||
int runStart = -1;
|
||||
for(int i=0;i<hexRepresentatoin.length;i++){
|
||||
|
||||
if(hexRepresentatoin[i] == 0){
|
||||
if(!inRun){
|
||||
runStart = i;
|
||||
inRun = true;
|
||||
}
|
||||
} else {
|
||||
if(inRun){
|
||||
inRun = false;
|
||||
int runLen = i - runStart;
|
||||
if(bestRunLen < 0){
|
||||
bestRunStart = runStart;
|
||||
bestRunLen = runLen;
|
||||
} else {
|
||||
if(runLen > bestRunLen){
|
||||
bestRunStart = runStart;
|
||||
bestRunLen = runLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(bestRunStart >=0){
|
||||
Arrays.fill(hexRepresentatoin, bestRunStart, bestRunStart + bestRunLen, -1);
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkForLinux() {
|
||||
return checkForPresence("os.name", "linux");
|
||||
}
|
||||
|
||||
private static boolean checkForHp() {
|
||||
return checkForPresence("os.name", "hp");
|
||||
}
|
||||
|
||||
private static boolean checkForSolaris() {
|
||||
return checkForPresence("os.name", "sun");
|
||||
}
|
||||
|
||||
private static boolean checkForWindows() {
|
||||
return checkForPresence("os.name", "win");
|
||||
}
|
||||
|
||||
public static boolean checkForMac() {
|
||||
return checkForPresence("os.name", "mac");
|
||||
}
|
||||
|
||||
private static boolean checkForPresence(final String key, final String value) {
|
||||
final String tmp = System.getProperty(key, value);
|
||||
try {
|
||||
return tmp != null && tmp.trim().toLowerCase(Locale.ENGLISH).startsWith(value);
|
||||
} catch (Throwable t) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// No instantiation
|
||||
private NetworkUtils() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -122,20 +122,23 @@ public class ServerCookie implements Serializable {
|
||||
private final static String OLD_COOKIE_PATTERN = "EEE, dd-MMM-yyyy HH:mm:ss z";
|
||||
|
||||
|
||||
private final static DateFormat oldCookieFormat = new SimpleDateFormat(OLD_COOKIE_PATTERN, LOCALE_US);
|
||||
private final static DateFormat OLD_COOKIE_FORMAT = new SimpleDateFormat(OLD_COOKIE_PATTERN, LOCALE_US);
|
||||
static{
|
||||
OLD_COOKIE_FORMAT.setTimeZone(GMT_ZONE);
|
||||
}
|
||||
|
||||
public static String formatOldCookie(Date d) {
|
||||
String ocf = null;
|
||||
synchronized (oldCookieFormat) {
|
||||
ocf = oldCookieFormat.format(d);
|
||||
synchronized (OLD_COOKIE_FORMAT) {
|
||||
ocf = OLD_COOKIE_FORMAT.format(d);
|
||||
}
|
||||
return ocf;
|
||||
}
|
||||
|
||||
public static void formatOldCookie(Date d, StringBuffer sb,
|
||||
FieldPosition fp) {
|
||||
synchronized (oldCookieFormat) {
|
||||
oldCookieFormat.format(d, sb, fp);
|
||||
synchronized (OLD_COOKIE_FORMAT) {
|
||||
OLD_COOKIE_FORMAT.format(d, sb, fp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Regular → Executable
+43
@@ -1,6 +1,8 @@
|
||||
package org.keycloak.util;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
@@ -23,4 +25,45 @@ public class UriUtils {
|
||||
return originPattern.matcher(url).matches();
|
||||
}
|
||||
|
||||
public static MultivaluedHashMap<String, String> decodeQueryString(String queryString) {
|
||||
MultivaluedHashMap<String, String> map = new MultivaluedHashMap<String, String>();
|
||||
if (queryString == null || queryString.equals("")) return map;
|
||||
|
||||
String[] params = queryString.split("&");
|
||||
|
||||
for (String param : params)
|
||||
{
|
||||
if (param.indexOf('=') >= 0)
|
||||
{
|
||||
String[] nv = param.split("=", 2);
|
||||
try
|
||||
{
|
||||
String name = URLDecoder.decode(nv[0], "UTF-8");
|
||||
String val = nv.length > 1 ? nv[1] : "";
|
||||
map.add(name, URLDecoder.decode(val, "UTF-8"));
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
String name = URLDecoder.decode(param, "UTF-8");
|
||||
map.add(name, "");
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
public static String stripQueryParam(String url, String name){
|
||||
return url.replaceFirst("[\\?&]"+name+"=[^&]*$|"+name+"=[^&]*&", "");
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.keycloak.models.utils.reflection;
|
||||
package org.keycloak.util.reflections;
|
||||
|
||||
import java.beans.Introspector;
|
||||
import java.io.Serializable;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.keycloak.models.utils.reflection;
|
||||
package org.keycloak.util.reflections;
|
||||
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.security.PrivilegedAction;
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package org.keycloak.models.utils.reflection;
|
||||
package org.keycloak.util.reflections;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
@@ -2,6 +2,7 @@ package org.keycloak.util;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
@@ -43,4 +44,15 @@ public class UriUtilsTest {
|
||||
assertFalse(UriUtils.isOrigin(origin));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStripQueryParam(){
|
||||
assertEquals("http://localhost",UriUtils.stripQueryParam("http://localhost?login_hint=michael","login_hint"));
|
||||
assertEquals("http://localhost",UriUtils.stripQueryParam("http://localhost?login_hint=michael@me.com","login_hint"));
|
||||
assertEquals("http://localhost?param=test",UriUtils.stripQueryParam("http://localhost?param=test&login_hint=michael","login_hint"));
|
||||
assertEquals("http://localhost?param=test",UriUtils.stripQueryParam("http://localhost?param=test&login_hint=michael@me.com","login_hint"));
|
||||
assertEquals("http://localhost?param=test",UriUtils.stripQueryParam("http://localhost?login_hint=michael¶m=test","login_hint"));
|
||||
assertEquals("http://localhost?param=test",UriUtils.stripQueryParam("http://localhost?login_hint=michael@me.com¶m=test","login_hint"));
|
||||
assertEquals("http://localhost?pre=test¶m=test",UriUtils.stripQueryParam("http://localhost?pre=test&login_hint=michael¶m=test","login_hint"));
|
||||
assertEquals("http://localhost?pre=test¶m=test",UriUtils.stripQueryParam("http://localhost?pre=test&login_hint=michael@me.com¶m=test","login_hint"));
|
||||
}
|
||||
}
|
||||
Vendored
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
Vendored
+7
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -184,6 +184,12 @@
|
||||
<dependency>
|
||||
<groupId>de.idyl</groupId>
|
||||
<artifactId>winzipaes</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk16</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
|
||||
Vendored
+5
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
@@ -24,6 +24,10 @@
|
||||
<groupId>net.iharder</groupId>
|
||||
<artifactId>base64</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk16</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core-jaxrs</artifactId>
|
||||
|
||||
@@ -42,7 +42,8 @@
|
||||
</includes>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>${project.build.directory}/unpacked/deployments/auth-server.war/WEB-INF/classes/META-INF</directory>
|
||||
<directory>${project.build.directory}/unpacked/deployments/auth-server.war/WEB-INF/classes/META-INF
|
||||
</directory>
|
||||
<outputDirectory>keycloak/standalone/configuration</outputDirectory>
|
||||
<includes>
|
||||
<include>keycloak-server.json</include>
|
||||
@@ -61,27 +62,18 @@
|
||||
<outputDirectory>keycloak/welcome-content</outputDirectory>
|
||||
<includes>
|
||||
<include>*.*</include>
|
||||
</includes>
|
||||
</includes>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
<!--
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<unpack>false</unpack>
|
||||
<useTransitiveDependencies>false</useTransitiveDependencies>
|
||||
<includes>
|
||||
<include>org.keycloak:keycloak-wildfly-adapter-dist:zip</include>
|
||||
<include>org.keycloak:keycloak-as7-adapter-dist:zip</include>
|
||||
<include>org.keycloak:keycloak-eap6-adapter-dist:zip</include>
|
||||
<include>org.keycloak:keycloak-tomcat6-adapter-dist:zip</include>
|
||||
<include>org.keycloak:keycloak-tomcat7-adapter-dist:zip</include>
|
||||
<include>org.keycloak:keycloak-tomcat8-adapter-dist:zip</include>
|
||||
<include>org.keycloak:keycloak-jetty81-adapter-dist:zip</include>
|
||||
<include>org.keycloak:keycloak-jetty91-adapter-dist:zip</include>
|
||||
<include>org.keycloak:keycloak-jetty92-adapter-dist:zip</include>
|
||||
</includes>
|
||||
<outputDirectory>adapters</outputDirectory>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
-->
|
||||
|
||||
<files>
|
||||
<file>
|
||||
<source>src/main/themes/README.txt</source>
|
||||
<outputDirectory>keycloak/standalone/configuration/themes</outputDirectory>
|
||||
</file>
|
||||
<file>
|
||||
<source>src/main/providers/README.txt</source>
|
||||
<outputDirectory>keycloak/standalone/configuration/providers</outputDirectory>
|
||||
</file>
|
||||
</files>
|
||||
</assembly>
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
Any provider implementation jars and libraries in this folder will be loaded by Keycloak. See the providers
|
||||
section in the documentation for more details.
|
||||
@@ -0,0 +1,3 @@
|
||||
Themes to configure the look and feel of login pages and account management console. It's not recommended to
|
||||
modify existing the built-in themes, instead you should create a new theme that extends a built-in theme. See the theme
|
||||
section in the documentation for more details.
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -93,6 +93,12 @@
|
||||
<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 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"/>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@
|
||||
|
||||
<module-def name="org.keycloak.keycloak-as7-adapter">
|
||||
<maven-resource group="org.keycloak" artifact="keycloak-as7-adapter"/>
|
||||
<maven-resource group="org.keycloak" artifact="keycloak-tomcat-core-adapter"/>
|
||||
</module-def>
|
||||
|
||||
<module-def name="org.keycloak.keycloak-undertow-adapter">
|
||||
@@ -108,6 +109,10 @@
|
||||
</module-def>
|
||||
<module-def name="org.picketlink.federation.bindings">
|
||||
<maven-resource group="org.picketlink" artifact="picketlink-wildfly-common"/>
|
||||
<maven-resource group="org.picketlink" artifact="picketlink-tomcat-common"/>
|
||||
<maven-resource group="org.picketlink" artifact="picketlink-tomcat5-single"/>
|
||||
<maven-resource group="org.picketlink" artifact="picketlink-jbas-common"/>
|
||||
<maven-resource group="org.picketlink" artifact="picketlink-jbas7-single"/>
|
||||
</module-def>
|
||||
<module-def name="org.picketlink.idm">
|
||||
<maven-resource group="org.picketlink" artifact="picketlink-idm-impl"/>
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -81,10 +81,31 @@
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-federation</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Wildfly federation binding -->
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-wildfly-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- AS7/EAP6 federation binding -->
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-tomcat-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-tomcat5-single</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-jbas-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-jbas7-single</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.picketlink</groupId>
|
||||
<artifactId>picketlink-idm-simple-schema</artifactId>
|
||||
|
||||
+1
@@ -35,6 +35,7 @@
|
||||
<module name="org.apache.httpcomponents" />
|
||||
<module name="javax.servlet.api"/>
|
||||
<module name="org.jboss.logging"/>
|
||||
<module name="org.jboss.xnio"/>
|
||||
<module name="io.undertow.core"/>
|
||||
<module name="io.undertow.servlet"/>
|
||||
<module name="org.keycloak.keycloak-adapter-core"/>
|
||||
|
||||
+9
-3
@@ -29,7 +29,6 @@
|
||||
<module name="javax.servlet.api" />
|
||||
<module name="org.jboss.common-core" />
|
||||
<module name="org.jboss.logging" />
|
||||
<module name="org.wildfly.extension.undertow" />
|
||||
<module name="org.jboss.security.xacml" />
|
||||
<module name="org.picketbox" />
|
||||
<module name="javax.xml.ws.api" />
|
||||
@@ -43,11 +42,18 @@
|
||||
<module name="org.jboss.ws.api" />
|
||||
<module name="org.jboss.ws.spi" />
|
||||
<module name="org.apache.cxf" />
|
||||
<module name="io.undertow.core" />
|
||||
<module name="io.undertow.servlet" />
|
||||
<module name="org.picketlink.common" />
|
||||
<module name="org.picketlink.config" />
|
||||
<module name="org.picketlink.federation" />
|
||||
|
||||
<!-- Wildfly dependencies -->
|
||||
<module name="org.wildfly.extension.undertow" optional="true" />
|
||||
<module name="io.undertow.core" optional="true" />
|
||||
<module name="io.undertow.servlet" optional="true" />
|
||||
|
||||
<!-- AS7/EAP6 dependencies -->
|
||||
<module name="org.jboss.as.web" optional="true"/>
|
||||
<module name="org.jboss.modules" optional="true"/>
|
||||
</dependencies>
|
||||
|
||||
</module>
|
||||
+1
-1
@@ -29,7 +29,7 @@
|
||||
<module name="javax.servlet.api" />
|
||||
<module name="org.jboss.common-core" />
|
||||
<module name="org.jboss.logging" />
|
||||
<module name="org.jboss.as.web-common" />
|
||||
<module name="org.jboss.as.web-common" optional="true" />
|
||||
<module name="org.jboss.security.xacml" />
|
||||
<module name="org.picketbox" />
|
||||
<module name="javax.xml.ws.api" />
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak OSGI Features</name>
|
||||
|
||||
@@ -1,15 +1,53 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0" name="keycloak-${project.version}">
|
||||
|
||||
<feature name="keycloak-core-adapter" version="${project.version}" resolver="(obr)">
|
||||
<details>The keycloak core adapter stuff</details>
|
||||
<bundle>mvn:org.keycloak/keycloak-osgi-core-adapter/${project.version}</bundle>
|
||||
<feature name="keycloak-adapter-core" version="${project.version}" resolver="(obr)">
|
||||
<details>The keycloak adapter core stuff</details>
|
||||
<bundle dependency="true">mvn:org.keycloak/keycloak-osgi-thirdparty/${project.version}</bundle>
|
||||
<bundle dependency="true">mvn:org.bouncycastle/bcprov-jdk16/${bouncycastle.version}</bundle>
|
||||
<bundle dependency="true">mvn:org.codehaus.jackson/jackson-core-asl/${jackson.version}</bundle>
|
||||
<bundle dependency="true">mvn:org.codehaus.jackson/jackson-mapper-asl/${jackson.version}</bundle>
|
||||
<bundle dependency="true">mvn:org.codehaus.jackson/jackson-xc/${jackson.version}</bundle>
|
||||
<bundle dependency="true">mvn:org.jboss.logging/jboss-logging/${jboss.logging.version}</bundle>
|
||||
<bundle>mvn:org.keycloak/keycloak-core/${project.version}</bundle>
|
||||
<bundle>mvn:org.keycloak/keycloak-adapter-core/${project.version}</bundle>
|
||||
</feature>
|
||||
|
||||
<feature name="keycloak-osgi-adapter" version="${project.version}" resolver="(obr)">
|
||||
<details>The keycloak adapter core stuff</details>
|
||||
<feature>keycloak-adapter-core</feature>
|
||||
<feature version="[2.3,4)">http-whiteboard</feature>
|
||||
<bundle>mvn:org.keycloak/keycloak-osgi-adapter/${project.version}</bundle>
|
||||
</feature>
|
||||
|
||||
<feature name="keycloak-jetty8-adapter" version="${project.version}" resolver="(obr)">
|
||||
<details>The keycloak Jetty8 adapter</details>
|
||||
<feature>keycloak-adapter-core</feature>
|
||||
<feature version="[8.1,9)">jetty</feature>
|
||||
<bundle>mvn:org.keycloak/keycloak-jetty-core/${project.version}</bundle>
|
||||
<bundle>mvn:org.keycloak/keycloak-jetty81-adapter/${project.version}</bundle>
|
||||
</feature>
|
||||
|
||||
<feature name="keycloak-jaas" version="${project.version}" resolver="(obr)">
|
||||
<details>The keycloak JAAS configuration</details>
|
||||
<feature>keycloak-core-adapter</feature>
|
||||
<feature>keycloak-adapter-core</feature>
|
||||
<bundle>mvn:org.keycloak/keycloak-osgi-jaas/${project.version}</bundle>
|
||||
</feature>
|
||||
|
||||
<feature name="keycloak" version="${project.version}" resolver="(obr)">
|
||||
<details>The keycloak adapter core stuff</details>
|
||||
<feature>keycloak-osgi-adapter</feature>
|
||||
<feature>keycloak-jetty8-adapter</feature>
|
||||
<feature>keycloak-jaas</feature>
|
||||
</feature>
|
||||
|
||||
<!-- This is just simplification to upgrade paxweb to 3.1.2 in JBoss Fuse 6.1 or Karaf 2.3.X environment -->
|
||||
<feature name="keycloak-pax-web-upgrade" version="${project.version}" resolver="(obr)">
|
||||
<details>This is just simplification to upgrade paxweb to 3.1.2 in JBoss Fuse 6.1 or Karaf 2.3.X environment</details>
|
||||
<bundle>mvn:org.ow2.asm/asm-all/5.0</bundle>
|
||||
<bundle>mvn:org.apache.xbean/xbean-bundleutils/3.18</bundle>
|
||||
<bundle>mvn:org.apache.xbean/xbean-reflect/3.18</bundle>
|
||||
<bundle>mvn:org.apache.xbean/xbean-finder/3.18</bundle>
|
||||
</feature>
|
||||
|
||||
</features>
|
||||
@@ -4,10 +4,10 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak OSGI JAAS</name>
|
||||
<name>Keycloak OSGI JAAS Realm Configuration</name>
|
||||
<description/>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-osgi-core-adapter</artifactId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
@@ -53,7 +53,7 @@
|
||||
<Embed-Dependency>*;scope=compile|runtime</Embed-Dependency>
|
||||
<Embed-Transitive>false</Embed-Transitive>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath> -->
|
||||
<Bundle-Name>${project.description}</Bundle-Name>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
|
||||
@@ -10,7 +10,10 @@
|
||||
<cm:property-placeholder persistent-id="org.keycloak" update-strategy="reload">
|
||||
<cm:default-properties>
|
||||
<cm:property name="jaasBearerKeycloakConfigFile" value="$[karaf.base]/etc/keycloak-hawtio.json"/>
|
||||
<cm:property name="jaasBearerRolePrincipalClass" value=""/>
|
||||
|
||||
<cm:property name="jaasDirectAccessKeycloakConfigFile" value="$[karaf.base]/etc/keycloak-direct-access.json"/>
|
||||
<cm:property name="jaasDirectAccessRolePrincipalClass" value="org.apache.karaf.jaas.boot.principal.RolePrincipal"/>
|
||||
</cm:default-properties>
|
||||
</cm:property-placeholder>
|
||||
|
||||
@@ -20,12 +23,14 @@
|
||||
<jaas:module className="org.keycloak.adapters.jaas.BearerTokenLoginModule"
|
||||
flags="sufficient">
|
||||
keycloak-config-file = ${jaasBearerKeycloakConfigFile}
|
||||
role-principal-class = ${jaasBearerRolePrincipalClass}
|
||||
</jaas:module>
|
||||
|
||||
<!-- Used for direct username/password authentication for non-web scenarios (like ssh) -->
|
||||
<jaas:module className="org.keycloak.adapters.jaas.DirectAccessGrantsLoginModule"
|
||||
flags="sufficient">
|
||||
keycloak-config-file = ${jaasDirectAccessKeycloakConfigFile}
|
||||
role-principal-class = ${jaasDirectAccessRolePrincipalClass}
|
||||
</jaas:module>
|
||||
|
||||
</jaas:config>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak OSGI Integration</name>
|
||||
@@ -17,7 +17,7 @@
|
||||
<modules>
|
||||
<module>features</module>
|
||||
<module>jaas</module>
|
||||
<module>core-adapter</module>
|
||||
<module>thirdparty</module>
|
||||
</modules>
|
||||
|
||||
</project>
|
||||
Vendored
Executable → Regular
+15
-40
@@ -4,20 +4,21 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak OSGI Core Adapter Integration</name>
|
||||
<description/>
|
||||
|
||||
<name>Keycloak OSGI Thirdparty</name>
|
||||
<description>Keycloak OSGI bundling for 3rd party libs without OSGI headers in manifest</description>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-osgi-core-adapter</artifactId>
|
||||
<artifactId>keycloak-osgi-thirdparty</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
|
||||
<properties>
|
||||
<keycloak.osgi.export>
|
||||
org.keycloak.adapters.jaas,
|
||||
org.keycloak.adapters
|
||||
net.iharder;version="${base64.version}",
|
||||
org.apache.http.*;version=${keycloak.apache.httpcomponents.version}
|
||||
</keycloak.osgi.export>
|
||||
<keycloak.osgi.import>
|
||||
*;resolution:=optional
|
||||
@@ -26,45 +27,19 @@
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<groupId>net.iharder</groupId>
|
||||
<artifactId>base64</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.jboss.logging</groupId>
|
||||
<artifactId>jboss-logging</artifactId>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpcore</artifactId>
|
||||
<version>${keycloak.apache.httpcomponents.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>${keycloak.apache.httpcomponents.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>net.iharder</groupId>
|
||||
<artifactId>base64</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-jdk16</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-core-asl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-mapper-asl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.codehaus.jackson</groupId>
|
||||
<artifactId>jackson-xc</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
@@ -84,14 +59,14 @@
|
||||
</executions>
|
||||
<configuration>
|
||||
<instructions>
|
||||
<Embed-Dependency>*;scope=compile|runtime;artifactId=!keycloak-adapter-core</Embed-Dependency>
|
||||
<Embed-Dependency>*;scope=compile|runtime;artifactId=!httpclient|httpcore|base64</Embed-Dependency>
|
||||
<Embed-Transitive>true</Embed-Transitive>
|
||||
<Bundle-ClassPath>.</Bundle-ClassPath>
|
||||
<Bundle-Name>${project.description}</Bundle-Name>
|
||||
<Bundle-Name>${project.name}</Bundle-Name>
|
||||
<Bundle-SymbolicName>${project.groupId}.${project.artifactId}</Bundle-SymbolicName>
|
||||
<Import-Package>${keycloak.osgi.import}</Import-Package>
|
||||
<Export-Package>${keycloak.osgi.export}</Export-Package>
|
||||
<Implementation-Title>keycloak</Implementation-Title>
|
||||
<Implementation-Title>${project.name}</Implementation-Title>
|
||||
<Implementation-Version>${project.version}</Implementation-Version>
|
||||
</instructions>
|
||||
</configuration>
|
||||
File renamed without changes.
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Distribution</name>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -68,12 +68,6 @@
|
||||
<version>${project.version}</version>
|
||||
<type>zip</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-example-themes-dist</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>zip</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
<!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">
|
||||
@@ -14,9 +15,11 @@
|
||||
<!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 InstalledApplications SYSTEM "modules/installed-applications.xml">
|
||||
<!ENTITY Logout SYSTEM "modules/logout.xml">
|
||||
<!ENTITY SAML SYSTEM "modules/saml.xml">
|
||||
<!ENTITY JAAS SYSTEM "modules/jaas.xml">
|
||||
<!ENTITY SocialConfig SYSTEM "modules/social-config.xml">
|
||||
<!ENTITY SocialFacebook SYSTEM "modules/social-facebook.xml">
|
||||
<!ENTITY SocialGitHub SYSTEM "modules/social-github.xml">
|
||||
@@ -76,6 +79,7 @@ This one is short
|
||||
&License;
|
||||
&Overview;
|
||||
&Installation;
|
||||
&Providers;
|
||||
&OpenShift;
|
||||
&AdminPermissions;
|
||||
&PerRealmAdminPermissions;
|
||||
@@ -91,10 +95,12 @@ This one is short
|
||||
&TomcatAdapter;
|
||||
&Jetty9Adapter;
|
||||
&Jetty8Adapter;
|
||||
&FuseAdapter;
|
||||
&JavascriptAdapter;
|
||||
&InstalledApplications;
|
||||
&Logout;
|
||||
&MultiTenancy;
|
||||
&JAAS;
|
||||
</chapter>
|
||||
|
||||
<chapter>
|
||||
|
||||
@@ -80,7 +80,17 @@
|
||||
<section>
|
||||
<title>Version specific migration</title>
|
||||
<section>
|
||||
<title>Migrating from 1.1.Beta1 to 1.1.Beta2</title>
|
||||
<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>
|
||||
@@ -95,7 +105,7 @@
|
||||
</itemizedlist>
|
||||
</section>
|
||||
<section>
|
||||
<title>Migrating from 1.0.x.Final to 1.1.Beta1</title>
|
||||
<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>
|
||||
|
||||
@@ -112,6 +112,15 @@
|
||||
</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>
|
||||
@@ -140,7 +149,19 @@
|
||||
<para>
|
||||
If CORS is enabled, this sets the value of the
|
||||
<literal>Access-Control-Allow-Methods</literal>
|
||||
header. This should be a JSON list of strings.
|
||||
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>
|
||||
@@ -183,7 +204,7 @@
|
||||
<listitem>
|
||||
<para>
|
||||
Specify the credentials of the application. This is an object notation where the key
|
||||
is the credential type and the value if the value of the credential type. Currently only
|
||||
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>.
|
||||
@@ -353,7 +374,7 @@
|
||||
<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>
|
||||
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>
|
||||
|
||||
@@ -79,7 +79,7 @@
|
||||
</para>
|
||||
<para>
|
||||
For example if your loadbalancer is on <emphasis>https://loadbalancer.com/myapp</emphasis> and auth-server-url is <emphasis>/auth</emphasis>,
|
||||
then relative URI of Keycloak is resolved to be <emphasis>https://loadbalancer.com/myapp</emphasis> .
|
||||
then relative URI of Keycloak is resolved to be <emphasis>https://loadbalancer.com/auth</emphasis> .
|
||||
</para>
|
||||
<para>
|
||||
For cluster setup, it may be even better to use option <emphasis>auth-server-url-for-backend-request</emphasis> . This allows to configure
|
||||
@@ -95,7 +95,7 @@
|
||||
<para>
|
||||
This would mean that browser requests (like redirecting to Keycloak login screen) will be still resolved relatively
|
||||
to current request URI like <emphasis>https://loadbalancer.com/myapp</emphasis>, but backend (out-of-bound) requests between keycloak
|
||||
and your app are send always to same cluster host with application .
|
||||
and your app are sent always to same cluster host with application .
|
||||
</para>
|
||||
<para>
|
||||
Note that additionally to network optimization,
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
<![CDATA[
|
||||
<subsystem xmlns="urn:jboss:domain:infinispan:2.0">
|
||||
<cache-container name="keycloak" jndi-name="infinispan/Keycloak" start="EAGER">
|
||||
<transport lock-timeout="60000"/>
|
||||
<invalidation-cache name="realms" mode="SYNC"/>
|
||||
<invalidation-cache name="users" mode="SYNC"/>
|
||||
<distributed-cache name="sessions" mode="SYNC" owners="1" />
|
||||
@@ -154,7 +155,7 @@
|
||||
messages to the cluster. However, as there's no sensitive data sent there's not much that can be achieved.
|
||||
For realms and users all that can be done is to send invalidation messages to make nodes load data from the
|
||||
database more frequently. For user sessions it would be possible to modify existing user sessions, but creating
|
||||
new sessions would have no affect as they would not be linked to any access tokens. There's not to much that
|
||||
new sessions would have no affect as they would not be linked to any access tokens. There's not too much that
|
||||
can be achieved by modifying user sessions. For example it would be possible to prevent sessions from expiring,
|
||||
by changing the creation time. However, it would for example have no effect adding additional permissions to the
|
||||
sessions as these are rechecked against the user and application when the token is created or refreshed.
|
||||
@@ -215,4 +216,25 @@
|
||||
</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>
|
||||
@@ -0,0 +1,51 @@
|
||||
<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 both JBoss Fuse 6.1
|
||||
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.
|
||||
</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>
|
||||
@@ -0,0 +1,42 @@
|
||||
<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,17 +1,15 @@
|
||||
<section id="javascript-adapter">
|
||||
<title>Pure Client Javascript Adapter</title>
|
||||
<title>Javascript Adapter</title>
|
||||
<para>
|
||||
The Keycloak Server comes with a Javascript library you can use to secure pure HTML/Javascript applications. This
|
||||
The Keycloak Server comes with a Javascript library you can use to secure HTML/Javascript applications. This
|
||||
library is referencable directly from the keycloak server. You can also download the adapter from Keycloak's download
|
||||
site if you want a static copy of this library. 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 end up having a non-confidential, public client. This can be mitigated
|
||||
by registering valid redirect URLs. You are still vulnerable if somebody hijacks the IP/DNS name of your pure
|
||||
HTML/Javascript application though.
|
||||
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>.
|
||||
@@ -138,6 +136,21 @@ keycloak.updateToken(30).success(function() {
|
||||
</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>
|
||||
|
||||
|
||||
@@ -145,7 +145,7 @@ $ java -jar $JETTY_HOME/start.jar --add-to-startd=keycloak
|
||||
|
||||
<login-config>
|
||||
<auth-method>BASIC</auth-method>
|
||||
<realm-name>this is ignored currently/realm-name>
|
||||
<realm-name>this is ignored currently</realm-name>
|
||||
</login-config>
|
||||
|
||||
<security-role>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
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 privleges to users within that realm. These realm admins can participate in SSO for that realm and
|
||||
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>
|
||||
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
<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 a 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>
|
||||
|
||||
<section>
|
||||
<title>Registering provider implementations</title>
|
||||
<para>
|
||||
Keycloak loads provider implementations from the file-system. By default all JARs inside
|
||||
<literal>standalone/configuration/providers</literal> are loaded. This is simple, but requires all providers
|
||||
to share the same library. All provides also inherit all classes from the Keycloak class-loader. In the future
|
||||
we'll add support to load providers from modules, which allows better control of class isolation.
|
||||
</para>
|
||||
<para>
|
||||
To register your provider simply copy the JAR including the ProviderFactory and Provider classes and the
|
||||
provider configuration file to <literal>standalone/configuration/providers</literal>.
|
||||
</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>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 Infinispan 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 file in a directory or a encrypted ZIP archive.
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Import</term>
|
||||
<listitem>
|
||||
Imports and exported Keycloak database. Keycloak provides implementations that import from JSON
|
||||
files either
|
||||
as a single file, multiple file 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>
|
||||
@@ -18,7 +18,7 @@
|
||||
<term>Include AuthnStatement</term>
|
||||
<listitem>
|
||||
<para>
|
||||
SAML login responses may specify the authenticaiton method used (password, etc.) as well as
|
||||
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>
|
||||
@@ -27,7 +27,7 @@
|
||||
<term>Multi-valued Roles</term>
|
||||
<listitem>
|
||||
<para>
|
||||
If this switch is off, any user role mapings will have a corresponding attribute created for it.
|
||||
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>
|
||||
@@ -82,7 +82,7 @@
|
||||
<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 a the Redirect binding.
|
||||
original request was the Redirect binding.
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
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 Thread Model</ulink> document put out by the IETF. Many of those vulnerabilities are discussed here.
|
||||
<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>
|
||||
|
||||
@@ -66,7 +66,7 @@ keycloak-appliance-dist-all-&project.version;/
|
||||
<literal>keycloak-war-dist-all-&project.version;.zip</literal>
|
||||
contains
|
||||
just the bits you need to install keycloak on your favorite web container. We currently only support
|
||||
installing it on top of an existing Wildfly 8, JBoss EAP 6.x or JBoss AS 7.1.1 distribution. We may in the
|
||||
installing it on top of an existing Wildfly 8 or JBoss EAP 6.x distribution. We may in the
|
||||
future provide directions on how to install it on another web container like Tomcat or Jetty. If anybody
|
||||
in the community is interested in pulling this together, please contact us. Its mostly Maven pom work.
|
||||
</para>
|
||||
@@ -701,175 +701,4 @@ keycloak-war-dist-all-&project.version;/
|
||||
</section>
|
||||
|
||||
</section>
|
||||
<section>
|
||||
<title>Configuring Servers from the Subsystem</title>
|
||||
<para>
|
||||
If you are using WildFly or EAP,he Keycloak server is deployed and configured from the Keycloak subsystem. This makes provisioning simpler in a domain environment.
|
||||
It also allows you to create more than one Keycloak server instance inside a single WildFly instance. And, you can upload providers, themes, and
|
||||
server configurations without disturbing Keycloak's auth-server.war.
|
||||
</para>
|
||||
<section>
|
||||
<title>Manually Creating A Server</title>
|
||||
<para>
|
||||
A Keycloak server can be declared by editing standalone.xml or domain.xml.
|
||||
</para>
|
||||
<para>
|
||||
<programlisting><![CDATA[
|
||||
<server xmlns="urn:jboss:domain:1.4">
|
||||
|
||||
<profile>
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak:1.0">
|
||||
<auth-server name="keycloak-1">
|
||||
<enabled>true</enabled>
|
||||
<web-context>auth</web-context>
|
||||
</auth-server>
|
||||
<auth-server name="keyclaok-2">
|
||||
<enabled>false</enabled>
|
||||
<web-context>auth2</web-context>
|
||||
</auth-server>
|
||||
</subsystem>
|
||||
</profile>
|
||||
]]>
|
||||
</programlisting>
|
||||
</para>
|
||||
<warning>
|
||||
<para>
|
||||
If you create more than one Keycloak server, you will need to use CLI to fully configure each instance. At the least,
|
||||
you will need to run the <link linkend="uploading-extra-config">update-server-config</link> operation.
|
||||
</para>
|
||||
</warning>
|
||||
</section>
|
||||
<section>
|
||||
<title>Using CLI and CLI GUI with the Keycloak Subsystem</title>
|
||||
<para>
|
||||
Servers can also be added/removed or enabled/disabled at runtime using the <ulink url="https://developer.jboss.org/wiki/CommandLineInterface">CLI</ulink> or
|
||||
<ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> tool. These are tools that ship with WildFly/EAP and also with
|
||||
the Keycloak Appliance installation. See <ulink url="https://developer.jboss.org/wiki/CommandLineInterface">CLI</ulink> or
|
||||
<ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> documentation to learn more about how to start the tools,
|
||||
issue commands, and create CLI scripts.
|
||||
</para>
|
||||
<para>
|
||||
To start CLI with the Keycloak Appliance install:
|
||||
<programlisting><![CDATA[
|
||||
cd <APPLIANCE_INSTALL_DIR>/keycloak/bin
|
||||
./jboss-cli.sh --gui
|
||||
or
|
||||
./jboss.cli.bat --gui]]>
|
||||
</programlisting>
|
||||
<note>Your server must be running to start in --gui mode.</note>
|
||||
</para>
|
||||
<section>
|
||||
<title>Basic CLI Commands</title>
|
||||
<para>
|
||||
Command to add a server in CLI:
|
||||
<programlisting><![CDATA[
|
||||
/subsystem=keycloak/auth-server=my-auth-server/:add(web-context=my-auth, enabled=true)]]>
|
||||
</programlisting>
|
||||
Because "enabled=true", a new Keycloak server will be immediately deployed. By default "enabled" is set to false.
|
||||
</para>
|
||||
<para>
|
||||
Command to remove a server in CLI:
|
||||
<programlisting><![CDATA[
|
||||
/subsystem=keycloak/auth-server=my-auth-server/:remove]]>
|
||||
</programlisting>
|
||||
The Keycloak server will be immediately deleted and undeployed.
|
||||
</para>
|
||||
<para>
|
||||
Command to enable or disable a server in CLI:
|
||||
<programlisting><![CDATA[
|
||||
/subsystem=keycloak/auth-server=foo/:write-attribute(name=enabled,value=true)]]>
|
||||
</programlisting>
|
||||
The Keycloak server will be immediately deployed or undeployed, but not deleted.
|
||||
</para>
|
||||
</section>
|
||||
<section id="uploading-extra-config">
|
||||
<title>Uploading extra configuration using CLI</title>
|
||||
<para>
|
||||
The Keycloak subsystem allows you to upload keycloak-server.json, provider jars, and theme jars to a Keycloak server instance. The
|
||||
CLI operations for this are "update-server-config" and "add-provider". You may use CLI, CLI GUI, or CLI scripts for these operations. The following
|
||||
examples are shown using <ulink url="https://developer.jboss.org/wiki/AGUIForTheCommandLineInterface">CLI GUI</ulink> for clarity.
|
||||
</para>
|
||||
<para>
|
||||
To use a new keycloak-server.json file for your server, find your server under the Keycloak subsystem. Then right-click the server,
|
||||
select "update-server-config", and upload your file.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
<imagedata fileref="images/update-server-config-select.png"/>
|
||||
</para>
|
||||
<para>
|
||||
<imagedata fileref="images/update-server-config-dialog.png"/>
|
||||
</para>
|
||||
|
||||
<warning>
|
||||
<para>
|
||||
If you use the update-server-config operation, you should delete or rename <WILDFLY_HOME>/standalone/configuration/keycloak-server.json.
|
||||
Otherwise, all Keycloak server instances will use this file instead of your uploaded file.
|
||||
</para>
|
||||
</warning>
|
||||
<para>
|
||||
To upload a new provider jar or theme jar to your server, find your server under the Keycloak subsystem. Then right-click the server,
|
||||
select "add-provider", and upload your file.
|
||||
</para>
|
||||
<para>
|
||||
<imagedata fileref="images/add-provider-select.png"/>
|
||||
</para>
|
||||
<para>
|
||||
<imagedata fileref="images/add-provider-dialog.png"/>
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
<title>Working with overlays</title>
|
||||
<para>
|
||||
When you upload a provider jar, theme jar, or keycloak-server.json file, you are creating an overlay. That is, the file is "overlayed"
|
||||
onto the Keycloak server at deploy time. There are two additional operations that help you manage these overlays. They are "list-overlays" and
|
||||
"remove-overlay". Here are CLI examples of these operations.
|
||||
</para>
|
||||
<para>
|
||||
<programlisting>
|
||||
/subsystem=keycloak/auth-server=my-auth-server/:list-overlays
|
||||
{
|
||||
"outcome" => "success",
|
||||
"result" => [
|
||||
"/WEB-INF/classes/META-INF/keycloak-server.json",
|
||||
"/WEB-INF/lib/federation-properties-example.jar"
|
||||
],
|
||||
}</programlisting>
|
||||
<programlisting>
|
||||
/subsystem=keycloak/auth-server=my-auth-server/:remove-overlay(overlay-file-path=/WEB-INF/lib/federation-properties-example.jar,redeploy=true)
|
||||
{
|
||||
"outcome" => "success",
|
||||
}</programlisting>
|
||||
</para>
|
||||
<para>
|
||||
<note>
|
||||
Notice in the "list-overlays" operation, the full path to the server config is
|
||||
/WEB-INF/classes/META-INF/keycloak-server.json. This is always the uploaded path for an "update-server-config" operation.
|
||||
If you remove this overlay, the Keycloak server will revert to its default keycloak-server.json. If you have a
|
||||
keycloak-server.json file in your <WILDFLY_HOME>/standalone/configuration directory, it will always take precedence
|
||||
over both the default and the overlay.
|
||||
</note>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
<section>
|
||||
<title>Adding a Keycloak server in Domain Mode</title>
|
||||
<para>
|
||||
In domain mode, you start the server with the "domain" command instead of the "standalone" command. In this case, the Keycloak subsystem is
|
||||
defined in domain/configuration/domain.xml instead of standalone/configuration.standalone.xml. Inside domain.xml, you will see more than one
|
||||
profile. A Keycloak subsystem can be defined in zero or more of those profiles.
|
||||
</para>
|
||||
<para>
|
||||
In the example below, a Keycloak server named "foo" is defined in the "full" profile. The "full" profile is assigned to the "main-server-group".
|
||||
Every WildFly instance that belongs to "main-server-group" will get an identically configured deployment of the "foo" Keycloak server.
|
||||
</para>
|
||||
<para>
|
||||
All operations discussed earlier are valid for a Keycloak server in a domain. You can enable/disable, upload new keyclaok-server.json, and add provider jars.
|
||||
In the following example, any changes that are made to the "foo" server will be automatically propogated to every instance in "main-server-group".
|
||||
</para>
|
||||
<para>
|
||||
<imagedata fileref="images/domain-mode.png"/>
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
</chapter>
|
||||
@@ -20,7 +20,7 @@
|
||||
Copy <literal>Client ID</literal> and <literal>Client secret</literal> from the
|
||||
<ulink url="https://github.com/settings/applications">GitHub Settings</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.
|
||||
<literal>Save</literal> in the Keycloak Admin Console to enable login with GitHub.
|
||||
</para>
|
||||
</listitem>
|
||||
</orderedlist>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<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 open the <literal>Keycloak Admin Console</literal>, select your realm
|
||||
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>
|
||||
@@ -166,7 +166,7 @@
|
||||
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:
|
||||
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"
|
||||
@@ -182,7 +182,7 @@
|
||||
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:
|
||||
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"
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
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. Thegoal of the Federation SPI is to support all of these scenarios.
|
||||
themselves. The goal of the Federation SPI is to support all of these scenarios.
|
||||
</para>
|
||||
<section>
|
||||
<title>LDAP and Active Directory Plugin</title>
|
||||
@@ -76,7 +76,7 @@
|
||||
<term>Display Name</term>
|
||||
<listitem>
|
||||
<para>
|
||||
Name used when this provider is referenced in the admin consle
|
||||
Name used when this provider is referenced in the admin console
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
@@ -118,7 +118,7 @@
|
||||
first import this LDAP user into Keycloak database and then authenticate against LDAP password.
|
||||
</para>
|
||||
<para>
|
||||
Thing is that Federation Provider import just requested users by default, so if you click to <literal>View all users</literal>
|
||||
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
|
||||
@@ -160,7 +160,7 @@
|
||||
<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 on how to do this. Some important methods of note:
|
||||
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>
|
||||
@@ -173,8 +173,8 @@
|
||||
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>.
|
||||
This is how Keycloak discovers which providers have been deployment. Place the JAR in the
|
||||
keycloak WAR deployment in the <literal>WEB-INF/lib</literal> directory.
|
||||
For more details on writing provider implementations and how to deploy to Keycloak refer to the
|
||||
<link linkend='providers'>providers</link> section.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-events-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -36,11 +36,10 @@ public interface Errors {
|
||||
|
||||
String SOCIAL_PROVIDER_NOT_FOUND = "social_provider_not_found";
|
||||
String SOCIAL_ID_IN_USE = "social_id_in_use";
|
||||
String STATE_PARAM_NOT_FOUND = "state_param_not_found";
|
||||
String SSL_REQUIRED = "ssl_required";
|
||||
|
||||
String USER_NOT_LOGGED_IN = "user_not_logged_in";
|
||||
String USER_SESSION_NOT_FOUND = "user_session_not_found";
|
||||
|
||||
|
||||
String EMAIL_SEND_FAILED = "email_send_failed";
|
||||
String INVALID_EMAIL = "invalid_email";
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-events-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-events-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-events-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -16,7 +16,7 @@ public class EventEntity {
|
||||
@Column(name="ID", length = 36)
|
||||
private String id;
|
||||
|
||||
@Column(name="TIME")
|
||||
@Column(name="EVENT_TIME")
|
||||
private long time;
|
||||
|
||||
@Column(name="TYPE")
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-events-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
</parent>
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -58,3 +58,18 @@ Multi tenancy
|
||||
-------------
|
||||
|
||||
A complete application, showing how to achieve multi tenancy of web applications by using one realm per account. For more information look at `multi-tenant/README.md`
|
||||
|
||||
Basic authentication
|
||||
--------------------
|
||||
|
||||
Example REST application configured to support both basic authentication with username/password as well as authentication with bearer token. For more information look at `basic-auth/README.md`
|
||||
|
||||
Fuse
|
||||
----
|
||||
|
||||
This is set of demo applications, showing how to secure your own web applications running inside OSGI environment in JBoss Fuse or Apache Karaf. Fore more information look at `fuse/README.md`
|
||||
|
||||
SAML
|
||||
----
|
||||
|
||||
This is set of demo applications, showing how to secure your own SAML web applications. Fore more information look at `saml/README.md`
|
||||
@@ -5,7 +5,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -18,9 +18,11 @@
|
||||
document.getElementById('not-authenticated').style.display = 'none';
|
||||
|
||||
document.getElementById('subject').innerText = keycloak.subject;
|
||||
document.getElementById('username').innerText = keycloak.idToken.preferred_username;
|
||||
document.getElementById('username').innerText = keycloak.idTokenParsed.preferred_username;
|
||||
document.getElementById('tokenExpires').innerText = new Date(keycloak.tokenParsed.exp * 1000).toLocaleString();
|
||||
document.getElementById('tokenRefreshExpires').innerText = new Date(keycloak.refreshTokenParsed.exp * 1000).toLocaleString();
|
||||
document.getElementById('token').innerText = JSON.stringify(keycloak.tokenParsed, null, ' ');
|
||||
document.getElementById('idToken').innerText = JSON.stringify(keycloak.idTokenParsed, null, ' ');
|
||||
} else {
|
||||
document.getElementById('authenticated').style.display = 'none';
|
||||
document.getElementById('not-authenticated').style.display = 'block';
|
||||
@@ -31,6 +33,15 @@
|
||||
keycloak.init({ onLoad: 'check-sso' }).success(updateState);
|
||||
}, false);
|
||||
</script>
|
||||
<style>
|
||||
td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
tr.odd td {
|
||||
background-color: #eee;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="authenticated" style="display: none;">
|
||||
@@ -46,7 +57,7 @@
|
||||
<td>Subject</td>
|
||||
<td id="subject"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd">
|
||||
<td>Username</td>
|
||||
<td id="username"></td>
|
||||
</tr>
|
||||
@@ -54,10 +65,18 @@
|
||||
<td>Token expires</td>
|
||||
<td id="tokenExpires"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr class="odd">
|
||||
<td>Refresh token expires</td>
|
||||
<td id="tokenRefreshExpires"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Token</td>
|
||||
<td><pre id="token"></pre></td>
|
||||
</tr>
|
||||
<tr class="odd">
|
||||
<td>ID Token</td>
|
||||
<td><pre id="idToken"></pre></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -81,6 +81,16 @@
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<div>
|
||||
<h2><span>Server version</span></h2>
|
||||
<button type="submit" data-ng-click="loadVersion()">Load version</button>
|
||||
|
||||
<div data-ng-show="version">
|
||||
Keycloak version: {{version.version}} <br/>
|
||||
Keycloak build time: {{version['build-time'] | date:'yyyy-MM-dd HH:mm:ss'}} <br/>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -32,6 +32,9 @@ angular.element(document).ready(function ($http) {
|
||||
module.controller('GlobalCtrl', function($scope, $http) {
|
||||
$scope.products = [];
|
||||
$scope.roles = [];
|
||||
$scope.serverInfo = [];
|
||||
$scope.realm = [];
|
||||
$scope.version = [];
|
||||
$scope.reloadData = function() {
|
||||
$http.get("http://localhost-db:8080/cors-database/products").success(function(data) {
|
||||
$scope.products = angular.fromJson(data);
|
||||
@@ -72,6 +75,12 @@ module.controller('GlobalCtrl', function($scope, $http) {
|
||||
});
|
||||
};
|
||||
|
||||
$scope.loadVersion = function() {
|
||||
$http.get("http://localhost-auth:8080/auth/version").success(function(data) {
|
||||
$scope.version = angular.fromJson(data);
|
||||
});
|
||||
};
|
||||
|
||||
$scope.logout = logout;
|
||||
});
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<name>Keycloak Examples - CORS</name>
|
||||
|
||||
@@ -30,13 +30,11 @@ Step 1: Make sure you've set up the Keycloak Server
|
||||
The Keycloak Appliance Distribution comes with a preconfigured Keycloak server (based on Wildfly). You can use it out of
|
||||
the box to run these demos. So, if you're using this, you can head to Step 2.
|
||||
|
||||
Alternatively, you can install the Keycloak Server onto any JBoss AS 7.1.1, EAP 6.x, or Wildfly 8.x server, but there is
|
||||
a few steps you must follow.
|
||||
Alternatively, you can install the Keycloak Server onto any EAP 6.x, or Wildfly 8.x server, but there is
|
||||
a few steps you must follow. You need to obtain latest keycloak-war-dist-all.zip. This distro is used to install Keycloak onto an existing JBoss installation.
|
||||
This installs the server using a WAR file.
|
||||
|
||||
Obtain latest keycloak-war-dist-all.zip. This distro is used to install Keycloak onto an existing JBoss installation.
|
||||
This installs the server.
|
||||
|
||||
$ cd ${wildfly.jboss.home}/standalone
|
||||
$ cd ${jboss.as7.home}/standalone
|
||||
$ cp -r ${keycloak-war-dist-all}/deployments .
|
||||
|
||||
To be able to run the demos you also need to install the Keycloak client adapter. For Wildfly:
|
||||
@@ -54,6 +52,10 @@ For JBoss AS 7.1.1:
|
||||
$ cd ${as7.home}
|
||||
$ unzip ${keycloak-war-dist-all}/adapters/keycloak-as7-adapter-dist.zip
|
||||
|
||||
WARNING: Note that we don't officially support Keycloak auth-server running on JBoss AS 7.1.1. You can still test examples running on AS 7.1.1,
|
||||
but then you may need to do few additional changes in examples to point them into external Keycloak server running on WildFly or EAP 6.x.
|
||||
This is especially changing "auth-server-url" in keycloak.json files to be non-relative as examples and auth-server will run on different server!
|
||||
|
||||
Unzipping the adapter ZIP only installs the JAR files. You must also add the Keycloak Subsystem to the server's
|
||||
configuration (standalone/configuration/standalone.xml).
|
||||
|
||||
@@ -66,7 +68,12 @@ For WildFly and JBoss EAP 6.x
|
||||
</extensions>
|
||||
|
||||
<profile>
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak:1.0"/>
|
||||
<subsystem xmlns="urn:jboss:domain:keycloak:1.0">
|
||||
<auth-server name="main-auth-server">
|
||||
<enabled>true</enabled>
|
||||
<web-context>auth</web-context>
|
||||
</auth-server>
|
||||
</subsystem>
|
||||
...
|
||||
</profile>
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.1.0.Beta2</version>
|
||||
<version>1.1.1.Final</version>
|
||||
<relativePath>../../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
Loaded 100 of 474 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user