refactor core/adapter
This commit is contained in:
parent
698b5a1a16
commit
d28b1ff98b
29 changed files with 485 additions and 308 deletions
|
@ -2,7 +2,6 @@ package org.keycloak;
|
|||
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfig;
|
||||
|
||||
import javax.ws.rs.core.Form;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
@ -23,9 +22,6 @@ public class RealmConfiguration {
|
|||
public RealmConfiguration() {
|
||||
}
|
||||
|
||||
public RealmConfiguration(ManagedResourceConfig config) {
|
||||
}
|
||||
|
||||
public ResourceMetadata getMetadata() {
|
||||
return metadata;
|
||||
}
|
||||
|
|
|
@ -1,217 +0,0 @@
|
|||
package org.keycloak.adapters.config;
|
||||
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.EnvUtil;
|
||||
import org.keycloak.PemUtils;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.ResourceMetadata;
|
||||
import org.keycloak.representations.idm.PublishedRealmRepresentation;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PublicKey;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class ManagedResourceConfigLoader {
|
||||
protected ManagedResourceConfig remoteSkeletonKeyConfig;
|
||||
protected ResourceMetadata resourceMetadata;
|
||||
protected KeyStore clientCertKeystore;
|
||||
protected KeyStore truststore;
|
||||
protected ResteasyClient client;
|
||||
protected RealmConfiguration realmConfiguration;
|
||||
|
||||
public ManagedResourceConfigLoader() {
|
||||
}
|
||||
|
||||
public ManagedResourceConfigLoader(InputStream is) {
|
||||
loadConfig(is);
|
||||
}
|
||||
|
||||
|
||||
public static KeyStore loadKeyStore(String filename, String password) throws Exception {
|
||||
KeyStore trustStore = KeyStore.getInstance(KeyStore
|
||||
.getDefaultType());
|
||||
File truststoreFile = new File(filename);
|
||||
FileInputStream trustStream = new FileInputStream(truststoreFile);
|
||||
trustStore.load(trustStream, password.toCharArray());
|
||||
trustStream.close();
|
||||
return trustStore;
|
||||
}
|
||||
|
||||
public void init(boolean setupClient) {
|
||||
String truststorePath = remoteSkeletonKeyConfig.getTruststore();
|
||||
if (truststorePath != null) {
|
||||
truststorePath = EnvUtil.replace(truststorePath);
|
||||
String truststorePassword = remoteSkeletonKeyConfig.getTruststorePassword();
|
||||
truststorePath = null;
|
||||
try {
|
||||
this.truststore = loadKeyStore(truststorePath, truststorePassword);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to load truststore", e);
|
||||
}
|
||||
}
|
||||
String clientKeystore = remoteSkeletonKeyConfig.getClientKeystore();
|
||||
String clientKeyPassword = null;
|
||||
if (clientKeystore != null) {
|
||||
clientKeystore = EnvUtil.replace(clientKeystore);
|
||||
String clientKeystorePassword = remoteSkeletonKeyConfig.getClientKeystorePassword();
|
||||
clientCertKeystore = null;
|
||||
try {
|
||||
clientCertKeystore = loadKeyStore(clientKeystore, clientKeystorePassword);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to load keystore", e);
|
||||
}
|
||||
}
|
||||
|
||||
initClient();
|
||||
|
||||
|
||||
if (remoteSkeletonKeyConfig.getRealmUrl() != null) {
|
||||
PublishedRealmRepresentation rep = null;
|
||||
try {
|
||||
rep = client.target(remoteSkeletonKeyConfig.getRealmUrl()).request().get(PublishedRealmRepresentation.class);
|
||||
} finally {
|
||||
if (!setupClient) {
|
||||
client.close();
|
||||
}
|
||||
}
|
||||
remoteSkeletonKeyConfig.setRealm(rep.getRealm());
|
||||
remoteSkeletonKeyConfig.setAuthUrl(rep.getAuthorizationUrl());
|
||||
remoteSkeletonKeyConfig.setCodeUrl(rep.getCodeUrl());
|
||||
remoteSkeletonKeyConfig.setRealmKey(rep.getPublicKeyPem());
|
||||
remoteSkeletonKeyConfig.setAdminRole(rep.getAdminRole());
|
||||
}
|
||||
if (remoteSkeletonKeyConfig.getAdminRole() == null) {
|
||||
remoteSkeletonKeyConfig.setAdminRole("$REALM-ADMIN$");
|
||||
}
|
||||
|
||||
String realm = remoteSkeletonKeyConfig.getRealm();
|
||||
if (realm == null) throw new RuntimeException("Must set 'realm' in config");
|
||||
String resource = remoteSkeletonKeyConfig.getResource();
|
||||
if (resource == null) throw new RuntimeException("Must set 'resource' in config");
|
||||
|
||||
String realmKeyPem = remoteSkeletonKeyConfig.getRealmKey();
|
||||
if (realmKeyPem == null) {
|
||||
throw new IllegalArgumentException("You must set the realm-public-key");
|
||||
}
|
||||
|
||||
PublicKey realmKey = null;
|
||||
try {
|
||||
realmKey = PemUtils.decodePublicKey(realmKeyPem);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
resourceMetadata = new ResourceMetadata();
|
||||
resourceMetadata.setRealm(realm);
|
||||
resourceMetadata.setResourceName(resource);
|
||||
resourceMetadata.setRealmKey(realmKey);
|
||||
resourceMetadata.setClientKeystore(clientCertKeystore);
|
||||
clientKeyPassword = remoteSkeletonKeyConfig.getClientKeyPassword();
|
||||
resourceMetadata.setClientKeyPassword(clientKeyPassword);
|
||||
resourceMetadata.setTruststore(this.truststore);
|
||||
|
||||
if (!setupClient || remoteSkeletonKeyConfig.isBearerOnly()) return;
|
||||
|
||||
realmConfiguration = new RealmConfiguration();
|
||||
String authUrl = remoteSkeletonKeyConfig.getAuthUrl();
|
||||
if (authUrl == null) {
|
||||
throw new RuntimeException("You must specify auth-url");
|
||||
}
|
||||
String tokenUrl = remoteSkeletonKeyConfig.getCodeUrl();
|
||||
if (tokenUrl == null) {
|
||||
throw new RuntimeException("You mut specify code-url");
|
||||
}
|
||||
realmConfiguration.setMetadata(resourceMetadata);
|
||||
realmConfiguration.setSslRequired(!remoteSkeletonKeyConfig.isSslNotRequired());
|
||||
|
||||
for (Map.Entry<String, String> entry : getRemoteSkeletonKeyConfig().getCredentials().entrySet()) {
|
||||
realmConfiguration.getResourceCredentials().param(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
ResteasyClient client = getClient();
|
||||
|
||||
realmConfiguration.setClient(client);
|
||||
realmConfiguration.setAuthUrl(UriBuilder.fromUri(authUrl).queryParam("client_id", resourceMetadata.getResourceName()));
|
||||
realmConfiguration.setCodeUrl(client.target(tokenUrl));
|
||||
|
||||
|
||||
}
|
||||
|
||||
protected void initClient() {
|
||||
int size = 10;
|
||||
if (remoteSkeletonKeyConfig.getConnectionPoolSize() > 0)
|
||||
size = remoteSkeletonKeyConfig.getConnectionPoolSize();
|
||||
ResteasyClientBuilder.HostnameVerificationPolicy policy = ResteasyClientBuilder.HostnameVerificationPolicy.WILDCARD;
|
||||
if (remoteSkeletonKeyConfig.isAllowAnyHostname())
|
||||
policy = ResteasyClientBuilder.HostnameVerificationPolicy.ANY;
|
||||
ResteasyProviderFactory providerFactory = new ResteasyProviderFactory();
|
||||
ClassLoader old = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(ManagedResourceConfigLoader.class.getClassLoader());
|
||||
try {
|
||||
ResteasyProviderFactory.getInstance(); // initialize builtins
|
||||
RegisterBuiltin.register(providerFactory);
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(old);
|
||||
}
|
||||
ResteasyClientBuilder builder = new ResteasyClientBuilder()
|
||||
.providerFactory(providerFactory)
|
||||
.connectionPoolSize(size)
|
||||
.hostnameVerification(policy)
|
||||
.keyStore(clientCertKeystore, remoteSkeletonKeyConfig.getClientKeyPassword());
|
||||
if (remoteSkeletonKeyConfig.isDisableTrustManager()) {
|
||||
builder.disableTrustManager();
|
||||
} else {
|
||||
builder.trustStore(truststore);
|
||||
}
|
||||
client = builder.build();
|
||||
}
|
||||
|
||||
public ManagedResourceConfig getRemoteSkeletonKeyConfig() {
|
||||
return remoteSkeletonKeyConfig;
|
||||
}
|
||||
|
||||
public ResourceMetadata getResourceMetadata() {
|
||||
return resourceMetadata;
|
||||
}
|
||||
|
||||
public ResteasyClient getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public KeyStore getClientCertKeystore() {
|
||||
return clientCertKeystore;
|
||||
}
|
||||
|
||||
public KeyStore getTruststore() {
|
||||
return truststore;
|
||||
}
|
||||
|
||||
public RealmConfiguration getRealmConfiguration() {
|
||||
return realmConfiguration;
|
||||
}
|
||||
|
||||
protected void loadConfig(InputStream is) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
|
||||
remoteSkeletonKeyConfig = null;
|
||||
try {
|
||||
remoteSkeletonKeyConfig = mapper.readValue(is, ManagedResourceConfig.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,6 +38,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-as7-adapter</artifactId>
|
||||
|
|
|
@ -34,6 +34,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-as7-adapter</artifactId>
|
||||
|
|
|
@ -38,6 +38,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-as7-adapter</artifactId>
|
||||
|
|
|
@ -38,6 +38,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-undertow-adapter</artifactId>
|
||||
|
|
|
@ -34,6 +34,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-undertow-adapter</artifactId>
|
||||
|
|
|
@ -38,6 +38,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-undertow-adapter</artifactId>
|
||||
|
|
5
examples/wildfly-demo/third-party/pom.xml
vendored
5
examples/wildfly-demo/third-party/pom.xml
vendored
|
@ -31,6 +31,11 @@
|
|||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
53
integration/adapter-core/pom.xml
Executable file
53
integration/adapter-core/pom.xml
Executable file
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0"?>
|
||||
<project>
|
||||
<parent>
|
||||
<artifactId>keycloak-parent</artifactId>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<version>1.0-alpha-1-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<name>Keycloak AS7 Integration</name>
|
||||
<description/>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</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>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -11,7 +11,8 @@ import java.util.Map;
|
|||
* @version $Revision: 1 $
|
||||
*/
|
||||
@JsonPropertyOrder({"realm-url", "realm", "resource", "realm-public-key", "admin-role", "auth-url", "code-url", "allow-any-hostname", "disable-trust-manager", "truststore", "truststore-password", "client-id", "client-credentials"})
|
||||
public class ManagedResourceConfig {
|
||||
public class AdapterConfig
|
||||
{
|
||||
@JsonProperty("realm-url")
|
||||
protected String realmUrl;
|
||||
@JsonProperty("realm")
|
||||
|
@ -20,9 +21,7 @@ public class ManagedResourceConfig {
|
|||
protected String resource;
|
||||
@JsonProperty("realm-public-key")
|
||||
protected String realmKey;
|
||||
@JsonProperty("admin-role")
|
||||
protected String adminRole;
|
||||
@JsonProperty("auth-url")
|
||||
@JsonProperty("auth-url")
|
||||
protected String authUrl;
|
||||
@JsonProperty("code-url")
|
||||
protected String codeUrl;
|
||||
|
@ -194,15 +193,7 @@ public class ManagedResourceConfig {
|
|||
this.connectionPoolSize = connectionPoolSize;
|
||||
}
|
||||
|
||||
public String getAdminRole() {
|
||||
return adminRole;
|
||||
}
|
||||
|
||||
public void setAdminRole(String adminRole) {
|
||||
this.adminRole = adminRole;
|
||||
}
|
||||
|
||||
public boolean isCors() {
|
||||
public boolean isCors() {
|
||||
return cors;
|
||||
}
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
package org.keycloak.adapters.config;
|
||||
|
||||
import org.codehaus.jackson.map.ObjectMapper;
|
||||
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
||||
import org.keycloak.EnvUtil;
|
||||
import org.keycloak.PemUtils;
|
||||
import org.keycloak.ResourceMetadata;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.KeyStore;
|
||||
import java.security.PublicKey;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class AdapterConfigLoader {
|
||||
protected AdapterConfig adapterConfig;
|
||||
protected ResourceMetadata resourceMetadata;
|
||||
protected KeyStore clientCertKeystore;
|
||||
protected KeyStore truststore;
|
||||
|
||||
public static KeyStore loadKeyStore(String filename, String password) throws Exception {
|
||||
KeyStore trustStore = KeyStore.getInstance(KeyStore
|
||||
.getDefaultType());
|
||||
File truststoreFile = new File(filename);
|
||||
FileInputStream trustStream = new FileInputStream(truststoreFile);
|
||||
trustStore.load(trustStream, password.toCharArray());
|
||||
trustStream.close();
|
||||
return trustStore;
|
||||
}
|
||||
|
||||
public void init() {
|
||||
String truststorePath = adapterConfig.getTruststore();
|
||||
if (truststorePath != null) {
|
||||
truststorePath = EnvUtil.replace(truststorePath);
|
||||
String truststorePassword = adapterConfig.getTruststorePassword();
|
||||
truststorePath = null;
|
||||
try {
|
||||
this.truststore = loadKeyStore(truststorePath, truststorePassword);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to load truststore", e);
|
||||
}
|
||||
}
|
||||
String clientKeystore = adapterConfig.getClientKeystore();
|
||||
String clientKeyPassword = null;
|
||||
if (clientKeystore != null) {
|
||||
clientKeystore = EnvUtil.replace(clientKeystore);
|
||||
String clientKeystorePassword = adapterConfig.getClientKeystorePassword();
|
||||
clientCertKeystore = null;
|
||||
try {
|
||||
clientCertKeystore = loadKeyStore(clientKeystore, clientKeystorePassword);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to load keystore", e);
|
||||
}
|
||||
}
|
||||
|
||||
String realm = adapterConfig.getRealm();
|
||||
if (realm == null) throw new RuntimeException("Must set 'realm' in config");
|
||||
String resource = adapterConfig.getResource();
|
||||
if (resource == null) throw new RuntimeException("Must set 'resource' in config");
|
||||
|
||||
String realmKeyPem = adapterConfig.getRealmKey();
|
||||
if (realmKeyPem == null) {
|
||||
throw new IllegalArgumentException("You must set the realm-public-key");
|
||||
}
|
||||
|
||||
PublicKey realmKey = null;
|
||||
try {
|
||||
realmKey = PemUtils.decodePublicKey(realmKeyPem);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
resourceMetadata = new ResourceMetadata();
|
||||
resourceMetadata.setRealm(realm);
|
||||
resourceMetadata.setResourceName(resource);
|
||||
resourceMetadata.setRealmKey(realmKey);
|
||||
resourceMetadata.setClientKeystore(clientCertKeystore);
|
||||
clientKeyPassword = adapterConfig.getClientKeyPassword();
|
||||
resourceMetadata.setClientKeyPassword(clientKeyPassword);
|
||||
resourceMetadata.setTruststore(this.truststore);
|
||||
|
||||
}
|
||||
|
||||
public AdapterConfig getAdapterConfig() {
|
||||
return adapterConfig;
|
||||
}
|
||||
|
||||
public ResourceMetadata getResourceMetadata() {
|
||||
return resourceMetadata;
|
||||
}
|
||||
|
||||
public KeyStore getClientCertKeystore() {
|
||||
return clientCertKeystore;
|
||||
}
|
||||
|
||||
public KeyStore getTruststore() {
|
||||
return truststore;
|
||||
}
|
||||
|
||||
protected void loadConfig(InputStream is) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
|
||||
adapterConfig = null;
|
||||
try {
|
||||
adapterConfig = mapper.readValue(is, AdapterConfig.class);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,12 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jose-jwt</artifactId>
|
||||
|
|
|
@ -8,7 +8,7 @@ import org.apache.catalina.connector.Response;
|
|||
import org.apache.catalina.valves.ValveBase;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.SkeletonKeySession;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfig;
|
||||
import org.keycloak.adapters.config.AdapterConfig;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
@ -29,9 +29,9 @@ import java.util.Set;
|
|||
*/
|
||||
public class AuthenticatedActionsValve extends ValveBase {
|
||||
private static final Logger log = Logger.getLogger(AuthenticatedActionsValve.class);
|
||||
protected ManagedResourceConfig config;
|
||||
protected AdapterConfig config;
|
||||
|
||||
public AuthenticatedActionsValve(ManagedResourceConfig config, Valve next, Container container, ObjectName controller) {
|
||||
public AuthenticatedActionsValve(AdapterConfig config, Valve next, Container container, ObjectName controller) {
|
||||
this.config = config;
|
||||
if (next == null) throw new RuntimeException("WTF is next null?!");
|
||||
setNext(next);
|
||||
|
|
|
@ -12,9 +12,9 @@ import org.apache.catalina.deploy.LoginConfig;
|
|||
import org.jboss.logging.Logger;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.ResourceMetadata;
|
||||
import org.keycloak.adapters.as7.config.CatalinaManagedResourceConfigLoader;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfig;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfigLoader;
|
||||
import org.keycloak.adapters.as7.config.CatalinaAdapterConfigLoader;
|
||||
import org.keycloak.adapters.config.AdapterConfig;
|
||||
import org.keycloak.adapters.config.AdapterConfigLoader;
|
||||
|
||||
import javax.security.auth.login.LoginException;
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -30,7 +30,7 @@ import java.io.IOException;
|
|||
*/
|
||||
public class BearerTokenAuthenticatorValve extends AuthenticatorBase implements LifecycleListener {
|
||||
private static final Logger log = Logger.getLogger(BearerTokenAuthenticatorValve.class);
|
||||
protected ManagedResourceConfig remoteSkeletonKeyConfig;
|
||||
protected AdapterConfig adapterConfig;
|
||||
protected ResourceMetadata resourceMetadata;
|
||||
|
||||
@Override
|
||||
|
@ -46,11 +46,11 @@ public class BearerTokenAuthenticatorValve extends AuthenticatorBase implements
|
|||
}
|
||||
|
||||
protected void init() {
|
||||
ManagedResourceConfigLoader managedResourceConfigLoader = new CatalinaManagedResourceConfigLoader(context);
|
||||
remoteSkeletonKeyConfig = managedResourceConfigLoader.getRemoteSkeletonKeyConfig();
|
||||
managedResourceConfigLoader.init(false);
|
||||
resourceMetadata = managedResourceConfigLoader.getResourceMetadata();
|
||||
AuthenticatedActionsValve actions = new AuthenticatedActionsValve(remoteSkeletonKeyConfig, getNext(), getContainer(), getController());
|
||||
AdapterConfigLoader adapterConfigLoader = new CatalinaAdapterConfigLoader(context);
|
||||
adapterConfig = adapterConfigLoader.getAdapterConfig();
|
||||
adapterConfigLoader.init();
|
||||
resourceMetadata = adapterConfigLoader.getResourceMetadata();
|
||||
AuthenticatedActionsValve actions = new AuthenticatedActionsValve(adapterConfig, getNext(), getContainer(), getController());
|
||||
setNext(actions);
|
||||
}
|
||||
|
||||
|
@ -58,7 +58,7 @@ public class BearerTokenAuthenticatorValve extends AuthenticatorBase implements
|
|||
public void invoke(Request request, Response response) throws IOException, ServletException {
|
||||
try {
|
||||
log.debugv("{0} {1}", request.getMethod(), request.getRequestURI());
|
||||
if (remoteSkeletonKeyConfig.isCors() && new CorsPreflightChecker(remoteSkeletonKeyConfig).checkCorsPreflight(request, response)) {
|
||||
if (adapterConfig.isCors() && new CorsPreflightChecker(adapterConfig).checkCorsPreflight(request, response)) {
|
||||
return;
|
||||
}
|
||||
super.invoke(request, response);
|
||||
|
@ -70,7 +70,7 @@ public class BearerTokenAuthenticatorValve extends AuthenticatorBase implements
|
|||
@Override
|
||||
protected boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
|
||||
try {
|
||||
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, true, remoteSkeletonKeyConfig.isUseResourceRoleMappings());
|
||||
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, true, adapterConfig.isUseResourceRoleMappings());
|
||||
if (bearer.login(request, response)) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ package org.keycloak.adapters.as7;
|
|||
import org.apache.catalina.connector.Request;
|
||||
import org.apache.catalina.connector.Response;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfig;
|
||||
import org.keycloak.adapters.config.AdapterConfig;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -11,9 +11,9 @@ import org.keycloak.adapters.config.ManagedResourceConfig;
|
|||
*/
|
||||
public class CorsPreflightChecker {
|
||||
private static final Logger log = Logger.getLogger(CorsPreflightChecker.class);
|
||||
protected ManagedResourceConfig config;
|
||||
protected AdapterConfig config;
|
||||
|
||||
public CorsPreflightChecker(ManagedResourceConfig config) {
|
||||
public CorsPreflightChecker(AdapterConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,9 +21,9 @@ import org.keycloak.RealmConfiguration;
|
|||
import org.keycloak.ResourceMetadata;
|
||||
import org.keycloak.SkeletonKeyPrincipal;
|
||||
import org.keycloak.SkeletonKeySession;
|
||||
import org.keycloak.adapters.as7.config.CatalinaManagedResourceConfigLoader;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfig;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfigLoader;
|
||||
import org.keycloak.adapters.as7.config.CatalinaAdapterConfigLoader;
|
||||
import org.keycloak.adapters.as7.config.RealmConfigurationLoader;
|
||||
import org.keycloak.adapters.config.AdapterConfig;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
import org.keycloak.representations.idm.admin.LogoutAction;
|
||||
|
||||
|
@ -47,7 +47,7 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
|
|||
protected RealmConfiguration realmConfiguration;
|
||||
private static final Logger log = Logger.getLogger(OAuthManagedResourceValve.class);
|
||||
protected UserSessionManagement userSessionManagement = new UserSessionManagement();
|
||||
protected ManagedResourceConfig remoteSkeletonKeyConfig;
|
||||
protected AdapterConfig adapterConfig;
|
||||
protected ResourceMetadata resourceMetadata;
|
||||
|
||||
|
||||
|
@ -64,20 +64,20 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
|
|||
}
|
||||
|
||||
protected void init() {
|
||||
ManagedResourceConfigLoader managedResourceConfigLoader = new CatalinaManagedResourceConfigLoader(context);
|
||||
managedResourceConfigLoader.init(true);
|
||||
resourceMetadata = managedResourceConfigLoader.getResourceMetadata();
|
||||
remoteSkeletonKeyConfig = managedResourceConfigLoader.getRemoteSkeletonKeyConfig();
|
||||
RealmConfigurationLoader configLoader = new CatalinaAdapterConfigLoader(context);
|
||||
configLoader.init(true);
|
||||
resourceMetadata = configLoader.getResourceMetadata();
|
||||
adapterConfig = configLoader.getAdapterConfig();
|
||||
|
||||
realmConfiguration = managedResourceConfigLoader.getRealmConfiguration();
|
||||
AuthenticatedActionsValve actions = new AuthenticatedActionsValve(remoteSkeletonKeyConfig, getNext(), getContainer(), getController());
|
||||
realmConfiguration = configLoader.getRealmConfiguration();
|
||||
AuthenticatedActionsValve actions = new AuthenticatedActionsValve(adapterConfig, getNext(), getContainer(), getController());
|
||||
setNext(actions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(Request request, Response response) throws IOException, ServletException {
|
||||
try {
|
||||
if (remoteSkeletonKeyConfig.isCors() && new CorsPreflightChecker(remoteSkeletonKeyConfig).checkCorsPreflight(request, response)) {
|
||||
if (adapterConfig.isCors() && new CorsPreflightChecker(adapterConfig).checkCorsPreflight(request, response)) {
|
||||
return;
|
||||
}
|
||||
String requestURI = request.getDecodedRequestURI();
|
||||
|
@ -181,7 +181,7 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
|
|||
}
|
||||
|
||||
protected boolean bearer(boolean challenge, Request request, HttpServletResponse response) throws LoginException, IOException {
|
||||
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(realmConfiguration.getMetadata(), challenge, remoteSkeletonKeyConfig.isUseResourceRoleMappings());
|
||||
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(realmConfiguration.getMetadata(), challenge, adapterConfig.isUseResourceRoleMappings());
|
||||
if (bearer.login(request, response)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -228,7 +228,7 @@ public class OAuthManagedResourceValve extends FormAuthenticator implements Life
|
|||
|
||||
SkeletonKeyToken token = oauth.getToken();
|
||||
Set<String> roles = new HashSet<String>();
|
||||
if (remoteSkeletonKeyConfig.isUseResourceRoleMappings()) {
|
||||
if (adapterConfig.isUseResourceRoleMappings()) {
|
||||
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
|
||||
if (access != null) roles.addAll(access.getRoles());
|
||||
} else {
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
package org.keycloak.adapters.as7.config;
|
||||
|
||||
import org.apache.catalina.Context;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfigLoader;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.InputStream;
|
||||
|
||||
public class CatalinaManagedResourceConfigLoader extends ManagedResourceConfigLoader {
|
||||
public class CatalinaAdapterConfigLoader extends RealmConfigurationLoader
|
||||
{
|
||||
|
||||
public CatalinaManagedResourceConfigLoader(Context context) {
|
||||
public CatalinaAdapterConfigLoader(Context context) {
|
||||
InputStream is = null;
|
||||
String path = context.getServletContext().getInitParameter("keycloak.config.file");
|
||||
if (path == null) {
|
|
@ -0,0 +1,97 @@
|
|||
package org.keycloak.adapters.as7.config;
|
||||
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.adapters.config.AdapterConfigLoader;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RealmConfigurationLoader extends AdapterConfigLoader {
|
||||
protected ResteasyClient client;
|
||||
protected RealmConfiguration realmConfiguration;
|
||||
|
||||
public RealmConfigurationLoader() {
|
||||
}
|
||||
|
||||
public RealmConfigurationLoader(InputStream is) {
|
||||
loadConfig(is);
|
||||
}
|
||||
|
||||
public void init(boolean setupClient) {
|
||||
init();
|
||||
initRealmConfiguration(setupClient);
|
||||
}
|
||||
|
||||
protected void initRealmConfiguration(boolean setupClient) {
|
||||
if (!setupClient || adapterConfig.isBearerOnly()) return;
|
||||
initClient();
|
||||
realmConfiguration = new RealmConfiguration();
|
||||
String authUrl = adapterConfig.getAuthUrl();
|
||||
if (authUrl == null) {
|
||||
throw new RuntimeException("You must specify auth-url");
|
||||
}
|
||||
String tokenUrl = adapterConfig.getCodeUrl();
|
||||
if (tokenUrl == null) {
|
||||
throw new RuntimeException("You mut specify code-url");
|
||||
}
|
||||
realmConfiguration.setMetadata(resourceMetadata);
|
||||
realmConfiguration.setSslRequired(!adapterConfig.isSslNotRequired());
|
||||
|
||||
for (Map.Entry<String, String> entry : getAdapterConfig().getCredentials().entrySet()) {
|
||||
realmConfiguration.getResourceCredentials().param(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
ResteasyClient client = getClient();
|
||||
|
||||
realmConfiguration.setClient(client);
|
||||
realmConfiguration.setAuthUrl(UriBuilder.fromUri(authUrl).queryParam("client_id", resourceMetadata.getResourceName()));
|
||||
realmConfiguration.setCodeUrl(client.target(tokenUrl));
|
||||
}
|
||||
|
||||
protected void initClient() {
|
||||
int size = 10;
|
||||
if (adapterConfig.getConnectionPoolSize() > 0)
|
||||
size = adapterConfig.getConnectionPoolSize();
|
||||
ResteasyClientBuilder.HostnameVerificationPolicy policy = ResteasyClientBuilder.HostnameVerificationPolicy.WILDCARD;
|
||||
if (adapterConfig.isAllowAnyHostname())
|
||||
policy = ResteasyClientBuilder.HostnameVerificationPolicy.ANY;
|
||||
ResteasyProviderFactory providerFactory = new ResteasyProviderFactory();
|
||||
ClassLoader old = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(RealmConfigurationLoader.class.getClassLoader());
|
||||
try {
|
||||
ResteasyProviderFactory.getInstance(); // initialize builtins
|
||||
RegisterBuiltin.register(providerFactory);
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(old);
|
||||
}
|
||||
ResteasyClientBuilder builder = new ResteasyClientBuilder()
|
||||
.providerFactory(providerFactory)
|
||||
.connectionPoolSize(size)
|
||||
.hostnameVerification(policy)
|
||||
.keyStore(clientCertKeystore, adapterConfig.getClientKeyPassword());
|
||||
if (adapterConfig.isDisableTrustManager()) {
|
||||
builder.disableTrustManager();
|
||||
} else {
|
||||
builder.trustStore(truststore);
|
||||
}
|
||||
client = builder.build();
|
||||
}
|
||||
|
||||
public ResteasyClient getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public RealmConfiguration getRealmConfiguration() {
|
||||
return realmConfiguration;
|
||||
}
|
||||
|
||||
}
|
|
@ -15,6 +15,7 @@
|
|||
<packaging>pom</packaging>
|
||||
|
||||
<modules>
|
||||
<module>adapter-core</module>
|
||||
<module>as7-eap6/adapter</module>
|
||||
<module>undertow</module>
|
||||
<!-- <module>as7-eap6/jboss-modules</module> -->
|
||||
|
|
|
@ -25,6 +25,12 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.keycloak</groupId>
|
||||
<artifactId>keycloak-adapter-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.resteasy</groupId>
|
||||
<artifactId>jose-jwt</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@ import io.undertow.server.HttpServerExchange;
|
|||
import io.undertow.util.Headers;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.SkeletonKeySession;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfig;
|
||||
import org.keycloak.adapters.config.AdapterConfig;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -25,11 +25,11 @@ import java.util.Set;
|
|||
*/
|
||||
public class AuthenticatedActionsHandler implements HttpHandler {
|
||||
private static final Logger log = Logger.getLogger(AuthenticatedActionsHandler.class);
|
||||
protected ManagedResourceConfig config;
|
||||
protected AdapterConfig adapterConfig;
|
||||
protected HttpHandler next;
|
||||
|
||||
protected AuthenticatedActionsHandler(ManagedResourceConfig config, HttpHandler next) {
|
||||
this.config = config;
|
||||
protected AuthenticatedActionsHandler(AdapterConfig config, HttpHandler next) {
|
||||
this.adapterConfig = config;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
|
@ -68,12 +68,12 @@ public class AuthenticatedActionsHandler implements HttpHandler {
|
|||
exchange.endExchange();
|
||||
return true;
|
||||
}
|
||||
if (!config.isExposeToken()) {
|
||||
if (!adapterConfig.isExposeToken()) {
|
||||
exchange.setResponseCode(200);
|
||||
exchange.endExchange();
|
||||
return true;
|
||||
}
|
||||
if (!config.isCors() && exchange.getRequestHeaders().getFirst(Headers.ORIGIN) != null) {
|
||||
if (!adapterConfig.isCors() && exchange.getRequestHeaders().getFirst(Headers.ORIGIN) != null) {
|
||||
exchange.setResponseCode(200);
|
||||
exchange.endExchange();
|
||||
return true;
|
||||
|
@ -82,7 +82,7 @@ public class AuthenticatedActionsHandler implements HttpHandler {
|
|||
}
|
||||
|
||||
protected boolean corsRequest(HttpServerExchange exchange, SkeletonKeySession session) throws IOException {
|
||||
if (!config.isCors()) return false;
|
||||
if (!adapterConfig.isCors()) return false;
|
||||
log.debugv("CORS enabled + request.getRequestURI()");
|
||||
String origin = exchange.getRequestHeaders().getFirst("Origin");
|
||||
log.debugv("Origin: {0} uri: {1}", origin, exchange.getRequestURI());
|
||||
|
|
|
@ -10,16 +10,13 @@ import org.keycloak.RealmConfiguration;
|
|||
import org.keycloak.ResourceMetadata;
|
||||
import org.keycloak.SkeletonKeyPrincipal;
|
||||
import org.keycloak.SkeletonKeySession;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfig;
|
||||
import org.keycloak.adapters.config.AdapterConfig;
|
||||
import org.keycloak.representations.SkeletonKeyToken;
|
||||
|
||||
import java.security.Principal;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import static io.undertow.util.Headers.WWW_AUTHENTICATE;
|
||||
import static io.undertow.util.StatusCodes.UNAUTHORIZED;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
|
@ -31,20 +28,20 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism
|
|||
public static final AttachmentKey<SkeletonKeySession> SKELETON_KEY_SESSION_ATTACHMENT_KEY = AttachmentKey.create(SkeletonKeySession.class);
|
||||
|
||||
protected ResourceMetadata resourceMetadata;
|
||||
protected ManagedResourceConfig config;
|
||||
protected AdapterConfig adapterConfig;
|
||||
protected RealmConfiguration realmConfig;
|
||||
protected int sslRedirectPort;
|
||||
|
||||
public KeycloakAuthenticationMechanism(ResourceMetadata resourceMetadata, ManagedResourceConfig config, RealmConfiguration realmConfig, int sslRedirectPort) {
|
||||
public KeycloakAuthenticationMechanism(ResourceMetadata resourceMetadata, AdapterConfig config, RealmConfiguration realmConfig, int sslRedirectPort) {
|
||||
this.resourceMetadata = resourceMetadata;
|
||||
this.config = config;
|
||||
this.adapterConfig = config;
|
||||
this.realmConfig = realmConfig;
|
||||
this.sslRedirectPort = sslRedirectPort;
|
||||
}
|
||||
|
||||
public KeycloakAuthenticationMechanism(ResourceMetadata resourceMetadata, ManagedResourceConfig config, RealmConfiguration realmConfig) {
|
||||
public KeycloakAuthenticationMechanism(ResourceMetadata resourceMetadata, AdapterConfig config, RealmConfiguration realmConfig) {
|
||||
this.resourceMetadata = resourceMetadata;
|
||||
this.config = config;
|
||||
this.adapterConfig = config;
|
||||
this.realmConfig = realmConfig;
|
||||
}
|
||||
|
||||
|
@ -64,7 +61,7 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism
|
|||
completeAuthentication(exchange, securityContext, token, surrogate);
|
||||
return AuthenticationMechanismOutcome.AUTHENTICATED;
|
||||
}
|
||||
else if (config.isBearerOnly()) {
|
||||
else if (adapterConfig.isBearerOnly()) {
|
||||
exchange.putAttachment(KEYCLOAK_CHALLENGE_ATTACHMENT_KEY, bearer.getChallenge());
|
||||
return AuthenticationMechanismOutcome.NOT_ATTEMPTED;
|
||||
}
|
||||
|
@ -92,13 +89,13 @@ public class KeycloakAuthenticationMechanism implements AuthenticationMechanism
|
|||
}
|
||||
|
||||
protected BearerTokenAuthenticator createBearerTokenAuthenticator() {
|
||||
return new BearerTokenAuthenticator(resourceMetadata, config.isUseResourceRoleMappings());
|
||||
return new BearerTokenAuthenticator(resourceMetadata, adapterConfig.isUseResourceRoleMappings());
|
||||
}
|
||||
|
||||
protected void completeAuthentication(HttpServerExchange exchange, SecurityContext securityContext, SkeletonKeyToken token, String surrogate) {
|
||||
final SkeletonKeyPrincipal skeletonKeyPrincipal = new SkeletonKeyPrincipal(token.getPrincipal(), surrogate);
|
||||
Set<String> roles = null;
|
||||
if (config.isUseResourceRoleMappings()) {
|
||||
if (adapterConfig.isUseResourceRoleMappings()) {
|
||||
SkeletonKeyToken.Access access = token.getResourceAccess(resourceMetadata.getResourceName());
|
||||
if (access != null) roles = access.getRoles();
|
||||
} else {
|
||||
|
|
|
@ -7,8 +7,7 @@ import io.undertow.servlet.ServletExtension;
|
|||
import io.undertow.servlet.api.DeploymentInfo;
|
||||
import io.undertow.servlet.api.ServletSessionConfig;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfig;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfigLoader;
|
||||
import org.keycloak.adapters.config.AdapterConfig;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import java.io.InputStream;
|
||||
|
@ -30,9 +29,9 @@ public class KeycloakServletExtension implements ServletExtension {
|
|||
deploymentInfo.setIgnoreStandardAuthenticationMechanism(true);
|
||||
InputStream is = servletContext.getResourceAsStream("/WEB-INF/keycloak.json");
|
||||
if (is == null) throw new RuntimeException("Unable to find /WEB-INF/keycloak.json configuration file");
|
||||
ManagedResourceConfigLoader loader = new ManagedResourceConfigLoader(is);
|
||||
RealmConfigurationLoader loader = new RealmConfigurationLoader(is);
|
||||
loader.init(true);
|
||||
ManagedResourceConfig keycloakConfig = loader.getRemoteSkeletonKeyConfig();
|
||||
AdapterConfig keycloakConfig = loader.getAdapterConfig();
|
||||
PreflightCorsHandler.Wrapper preflight = new PreflightCorsHandler.Wrapper(keycloakConfig);
|
||||
ServletKeycloakAuthenticationMechanism auth = new ServletKeycloakAuthenticationMechanism(loader.getResourceMetadata(),
|
||||
keycloakConfig,
|
||||
|
|
|
@ -5,7 +5,7 @@ import io.undertow.server.HttpHandler;
|
|||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.util.HttpString;
|
||||
import org.jboss.logging.Logger;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfig;
|
||||
import org.keycloak.adapters.config.AdapterConfig;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
|
@ -13,7 +13,7 @@ import org.keycloak.adapters.config.ManagedResourceConfig;
|
|||
*/
|
||||
public class PreflightCorsHandler implements HttpHandler {
|
||||
private static final Logger log = Logger.getLogger(PreflightCorsHandler.class);
|
||||
protected ManagedResourceConfig config;
|
||||
protected AdapterConfig adapterConfig;
|
||||
protected HttpHandler next;
|
||||
|
||||
public static final HttpString ACCESS_CONTROL_ALLOW_ORIGIN = new HttpString("Access-Control-Allow-Origin");
|
||||
|
@ -23,9 +23,9 @@ public class PreflightCorsHandler implements HttpHandler {
|
|||
public static final HttpString ACCESS_CONTROL_MAX_AGE = new HttpString("Access-Control-Max-Age");
|
||||
|
||||
public static class Wrapper implements HandlerWrapper {
|
||||
protected ManagedResourceConfig config;
|
||||
protected AdapterConfig config;
|
||||
|
||||
public Wrapper(ManagedResourceConfig config) {
|
||||
public Wrapper(AdapterConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
|
@ -35,8 +35,8 @@ public class PreflightCorsHandler implements HttpHandler {
|
|||
}
|
||||
}
|
||||
|
||||
protected PreflightCorsHandler(ManagedResourceConfig config, HttpHandler next) {
|
||||
this.config = config;
|
||||
protected PreflightCorsHandler(AdapterConfig config, HttpHandler next) {
|
||||
this.adapterConfig = config;
|
||||
this.next = next;
|
||||
}
|
||||
|
||||
|
@ -60,20 +60,20 @@ public class PreflightCorsHandler implements HttpHandler {
|
|||
exchange.getResponseHeaders().put(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
|
||||
String requestMethods = exchange.getRequestHeaders().getFirst("Access-Control-Request-Method");
|
||||
if (requestMethods != null) {
|
||||
if (config.getCorsAllowedMethods() != null) {
|
||||
requestMethods = config.getCorsAllowedMethods();
|
||||
if (adapterConfig.getCorsAllowedMethods() != null) {
|
||||
requestMethods = adapterConfig.getCorsAllowedMethods();
|
||||
}
|
||||
exchange.getResponseHeaders().put(ACCESS_CONTROL_ALLOW_METHODS, requestMethods);
|
||||
}
|
||||
String allowHeaders = exchange.getRequestHeaders().getFirst("Access-Control-Request-Headers");
|
||||
if (allowHeaders != null) {
|
||||
if (config.getCorsAllowedHeaders() != null) {
|
||||
allowHeaders = config.getCorsAllowedHeaders();
|
||||
if (adapterConfig.getCorsAllowedHeaders() != null) {
|
||||
allowHeaders = adapterConfig.getCorsAllowedHeaders();
|
||||
}
|
||||
exchange.getResponseHeaders().put(ACCESS_CONTROL_ALLOW_HEADERS, allowHeaders);
|
||||
}
|
||||
if (config.getCorsMaxAge() > -1) {
|
||||
exchange.getResponseHeaders().put(ACCESS_CONTROL_MAX_AGE, Integer.toString(config.getCorsMaxAge()));
|
||||
if (adapterConfig.getCorsMaxAge() > -1) {
|
||||
exchange.getResponseHeaders().put(ACCESS_CONTROL_MAX_AGE, Integer.toString(adapterConfig.getCorsMaxAge()));
|
||||
}
|
||||
exchange.endExchange();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
package org.keycloak.adapters.undertow;
|
||||
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
||||
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
|
||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
||||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.adapters.config.AdapterConfigLoader;
|
||||
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
import java.io.InputStream;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||
* @version $Revision: 1 $
|
||||
*/
|
||||
public class RealmConfigurationLoader extends AdapterConfigLoader {
|
||||
protected ResteasyClient client;
|
||||
protected RealmConfiguration realmConfiguration;
|
||||
|
||||
public RealmConfigurationLoader() {
|
||||
}
|
||||
|
||||
public RealmConfigurationLoader(InputStream is) {
|
||||
loadConfig(is);
|
||||
}
|
||||
|
||||
public void init(boolean setupClient) {
|
||||
init();
|
||||
initRealmConfiguration(setupClient);
|
||||
}
|
||||
|
||||
protected void initRealmConfiguration(boolean setupClient) {
|
||||
if (!setupClient || adapterConfig.isBearerOnly()) return;
|
||||
initClient();
|
||||
realmConfiguration = new RealmConfiguration();
|
||||
String authUrl = adapterConfig.getAuthUrl();
|
||||
if (authUrl == null) {
|
||||
throw new RuntimeException("You must specify auth-url");
|
||||
}
|
||||
String tokenUrl = adapterConfig.getCodeUrl();
|
||||
if (tokenUrl == null) {
|
||||
throw new RuntimeException("You mut specify code-url");
|
||||
}
|
||||
realmConfiguration.setMetadata(resourceMetadata);
|
||||
realmConfiguration.setSslRequired(!adapterConfig.isSslNotRequired());
|
||||
|
||||
for (Map.Entry<String, String> entry : getAdapterConfig().getCredentials().entrySet()) {
|
||||
realmConfiguration.getResourceCredentials().param(entry.getKey(), entry.getValue());
|
||||
}
|
||||
|
||||
ResteasyClient client = getClient();
|
||||
|
||||
realmConfiguration.setClient(client);
|
||||
realmConfiguration.setAuthUrl(UriBuilder.fromUri(authUrl).queryParam("client_id", resourceMetadata.getResourceName()));
|
||||
realmConfiguration.setCodeUrl(client.target(tokenUrl));
|
||||
}
|
||||
|
||||
protected void initClient() {
|
||||
int size = 10;
|
||||
if (adapterConfig.getConnectionPoolSize() > 0)
|
||||
size = adapterConfig.getConnectionPoolSize();
|
||||
ResteasyClientBuilder.HostnameVerificationPolicy policy = ResteasyClientBuilder.HostnameVerificationPolicy.WILDCARD;
|
||||
if (adapterConfig.isAllowAnyHostname())
|
||||
policy = ResteasyClientBuilder.HostnameVerificationPolicy.ANY;
|
||||
ResteasyProviderFactory providerFactory = new ResteasyProviderFactory();
|
||||
ClassLoader old = Thread.currentThread().getContextClassLoader();
|
||||
Thread.currentThread().setContextClassLoader(RealmConfigurationLoader.class.getClassLoader());
|
||||
try {
|
||||
ResteasyProviderFactory.getInstance(); // initialize builtins
|
||||
RegisterBuiltin.register(providerFactory);
|
||||
} finally {
|
||||
Thread.currentThread().setContextClassLoader(old);
|
||||
}
|
||||
ResteasyClientBuilder builder = new ResteasyClientBuilder()
|
||||
.providerFactory(providerFactory)
|
||||
.connectionPoolSize(size)
|
||||
.hostnameVerification(policy)
|
||||
.keyStore(clientCertKeystore, adapterConfig.getClientKeyPassword());
|
||||
if (adapterConfig.isDisableTrustManager()) {
|
||||
builder.disableTrustManager();
|
||||
} else {
|
||||
builder.trustStore(truststore);
|
||||
}
|
||||
client = builder.build();
|
||||
}
|
||||
|
||||
public ResteasyClient getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
public RealmConfiguration getRealmConfiguration() {
|
||||
return realmConfiguration;
|
||||
}
|
||||
|
||||
}
|
|
@ -5,7 +5,7 @@ import io.undertow.server.HttpHandler;
|
|||
import io.undertow.server.HttpServerExchange;
|
||||
import io.undertow.servlet.handlers.ServletRequestContext;
|
||||
import org.keycloak.SkeletonKeySession;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfig;
|
||||
import org.keycloak.adapters.config.AdapterConfig;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
@ -16,14 +16,14 @@ import javax.servlet.http.HttpSession;
|
|||
*/
|
||||
public class ServletAuthenticatedActionsHandler extends AuthenticatedActionsHandler {
|
||||
|
||||
protected ServletAuthenticatedActionsHandler(ManagedResourceConfig config, HttpHandler next) {
|
||||
protected ServletAuthenticatedActionsHandler(AdapterConfig config, HttpHandler next) {
|
||||
super(config, next);
|
||||
}
|
||||
|
||||
public static class Wrapper implements HandlerWrapper {
|
||||
protected ManagedResourceConfig config;
|
||||
protected AdapterConfig config;
|
||||
|
||||
public Wrapper(ManagedResourceConfig config) {
|
||||
public Wrapper(AdapterConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ import io.undertow.servlet.handlers.ServletRequestContext;
|
|||
import org.keycloak.RealmConfiguration;
|
||||
import org.keycloak.ResourceMetadata;
|
||||
import org.keycloak.SkeletonKeySession;
|
||||
import org.keycloak.adapters.config.ManagedResourceConfig;
|
||||
import org.keycloak.adapters.config.AdapterConfig;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
@ -18,7 +18,7 @@ import javax.servlet.http.HttpSession;
|
|||
public class ServletKeycloakAuthenticationMechanism extends KeycloakAuthenticationMechanism {
|
||||
protected ConfidentialPortManager portManager;
|
||||
|
||||
public ServletKeycloakAuthenticationMechanism(ResourceMetadata resourceMetadata, ManagedResourceConfig config, RealmConfiguration realmConfig, ConfidentialPortManager portManager) {
|
||||
public ServletKeycloakAuthenticationMechanism(ResourceMetadata resourceMetadata, AdapterConfig config, RealmConfiguration realmConfig, ConfidentialPortManager portManager) {
|
||||
super(resourceMetadata, config, realmConfig);
|
||||
this.portManager = portManager;
|
||||
}
|
||||
|
|
|
@ -134,6 +134,7 @@ public class AccountTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
public void changePassword() {
|
||||
changePasswordPage.open();
|
||||
loginPage.login("test-user@localhost", "password");
|
||||
|
|
Loading…
Reference in a new issue