Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
d9633dc20c
36 changed files with 1122 additions and 507 deletions
|
@ -87,6 +87,10 @@
|
||||||
}
|
}
|
||||||
kc.flow = initOptions.flow;
|
kc.flow = initOptions.flow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (initOptions.timeSkew != null) {
|
||||||
|
kc.timeSkew = initOptions.timeSkew;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!kc.responseMode) {
|
if (!kc.responseMode) {
|
||||||
|
@ -162,12 +166,8 @@
|
||||||
kc.onAuthSuccess && kc.onAuthSuccess();
|
kc.onAuthSuccess && kc.onAuthSuccess();
|
||||||
initPromise.setSuccess();
|
initPromise.setSuccess();
|
||||||
}).error(function () {
|
}).error(function () {
|
||||||
kc.onAuthError && kc.onAuthError();
|
setToken(null, null, null);
|
||||||
if (initOptions.onLoad) {
|
initPromise.setSuccess();
|
||||||
onLoad();
|
|
||||||
} else {
|
|
||||||
initPromise.setError();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -369,6 +369,11 @@
|
||||||
throw 'Not authenticated';
|
throw 'Not authenticated';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (kc.timeSkew == null) {
|
||||||
|
console.info('[KEYCLOAK] Unable to determine if token is expired as timeskew is not set');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
var expiresIn = kc.tokenParsed['exp'] - Math.ceil(new Date().getTime() / 1000) + kc.timeSkew;
|
var expiresIn = kc.tokenParsed['exp'] - Math.ceil(new Date().getTime() / 1000) + kc.timeSkew;
|
||||||
if (minValidity) {
|
if (minValidity) {
|
||||||
expiresIn -= minValidity;
|
expiresIn -= minValidity;
|
||||||
|
@ -653,12 +658,7 @@
|
||||||
if (token) {
|
if (token) {
|
||||||
kc.token = token;
|
kc.token = token;
|
||||||
kc.tokenParsed = decodeToken(token);
|
kc.tokenParsed = decodeToken(token);
|
||||||
|
kc.sessionId = kc.tokenParsed.session_state;
|
||||||
var sessionId = kc.realm + '/' + kc.tokenParsed.sub;
|
|
||||||
if (kc.tokenParsed.session_state) {
|
|
||||||
sessionId = sessionId + '/' + kc.tokenParsed.session_state;
|
|
||||||
}
|
|
||||||
kc.sessionId = sessionId;
|
|
||||||
kc.authenticated = true;
|
kc.authenticated = true;
|
||||||
kc.subject = kc.tokenParsed.sub;
|
kc.subject = kc.tokenParsed.sub;
|
||||||
kc.realmAccess = kc.tokenParsed.realm_access;
|
kc.realmAccess = kc.tokenParsed.realm_access;
|
||||||
|
@ -666,6 +666,9 @@
|
||||||
|
|
||||||
if (timeLocal) {
|
if (timeLocal) {
|
||||||
kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
|
kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kc.timeSkew != null) {
|
||||||
console.info('[KEYCLOAK] Estimated time difference between browser and server is ' + kc.timeSkew + ' seconds');
|
console.info('[KEYCLOAK] Estimated time difference between browser and server is ' + kc.timeSkew + ' seconds');
|
||||||
|
|
||||||
if (kc.onTokenExpired) {
|
if (kc.onTokenExpired) {
|
||||||
|
@ -677,11 +680,7 @@
|
||||||
kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
|
kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
kc.updateToken(-1);
|
|
||||||
}
|
}
|
||||||
} else if (refreshToken) {
|
|
||||||
kc.updateToken(-1);
|
|
||||||
} else {
|
} else {
|
||||||
delete kc.token;
|
delete kc.token;
|
||||||
delete kc.tokenParsed;
|
delete kc.tokenParsed;
|
||||||
|
|
|
@ -53,7 +53,8 @@
|
||||||
req.send();
|
req.send();
|
||||||
} else {
|
} else {
|
||||||
if (clientId === init.clientId && origin === init.origin) {
|
if (clientId === init.clientId && origin === init.origin) {
|
||||||
if (sessionState === cookie) {
|
var c = cookie.split('/');
|
||||||
|
if (sessionState === c[2]) {
|
||||||
callback('unchanged');
|
callback('unchanged');
|
||||||
} else {
|
} else {
|
||||||
callback('changed');
|
callback('changed');
|
||||||
|
@ -81,7 +82,7 @@
|
||||||
var origin = event.origin;
|
var origin = event.origin;
|
||||||
var data = event.data.split(' ');
|
var data = event.data.split(' ');
|
||||||
if (data.length != 2) {
|
if (data.length != 2) {
|
||||||
event.source.postMessage('error', origin);
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var clientId = data[0];
|
var clientId = data[0];
|
||||||
|
|
33
distribution/downloads/assembly.xml
Normal file
33
distribution/downloads/assembly.xml
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
<!--
|
||||||
|
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
~ and other contributors as indicated by the @author tags.
|
||||||
|
~
|
||||||
|
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ you may not use this file except in compliance with the License.
|
||||||
|
~ You may obtain a copy of the License at
|
||||||
|
~
|
||||||
|
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~
|
||||||
|
~ Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ See the License for the specific language governing permissions and
|
||||||
|
~ limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<assembly>
|
||||||
|
<id>server-dist</id>
|
||||||
|
|
||||||
|
<formats>
|
||||||
|
<format>dir</format>
|
||||||
|
</formats>
|
||||||
|
|
||||||
|
<fileSets>
|
||||||
|
<fileSet>
|
||||||
|
<directory>${localRepository}/org/keycloak</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*.zip</include>
|
||||||
|
</includes>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
</assembly>
|
|
@ -25,16 +25,25 @@
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>keycloak-dist-downloads</artifactId>
|
<artifactId>keycloak-dist-downloads</artifactId>
|
||||||
<packaging>pom</packaging>
|
<packaging>jar</packaging>
|
||||||
<name>Keycloak Release Downloads</name>
|
<name>Keycloak Release Downloads</name>
|
||||||
<description/>
|
<description/>
|
||||||
|
|
||||||
<dependencies>
|
<properties>
|
||||||
|
<maven.compiler.target>1.8</maven.compiler.target>
|
||||||
</dependencies>
|
<maven.compiler.source>1.8</maven.compiler.source>
|
||||||
|
</properties>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<source>${maven.compiler.source}</source>
|
||||||
|
<target>${maven.compiler.target}</target>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
<artifactId>maven-deploy-plugin</artifactId>
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
@ -43,342 +52,22 @@
|
||||||
</configuration>
|
</configuration>
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
<groupId>org.codehaus.mojo</groupId>
|
||||||
<artifactId>maven-dependency-plugin</artifactId>
|
<artifactId>exec-maven-plugin</artifactId>
|
||||||
<executions>
|
<executions>
|
||||||
<execution>
|
<execution>
|
||||||
<id>server-downloads</id>
|
<id>server-downloads</id>
|
||||||
<phase>install</phase>
|
<phase>package</phase>
|
||||||
<goals>
|
<goals>
|
||||||
<goal>copy</goal>
|
<goal>java</goal>
|
||||||
</goals>
|
</goals>
|
||||||
<configuration>
|
<configuration>
|
||||||
<artifactItems>
|
<mainClass>CopyDependencies</mainClass>
|
||||||
<artifactItem>
|
<arguments>
|
||||||
<groupId>org.keycloak</groupId>
|
<argument>${settings.localRepository}</argument>
|
||||||
<artifactId>keycloak-server-dist</artifactId>
|
<argument>${project.build.directory}</argument>
|
||||||
<type>zip</type>
|
<argument>${project.version}</argument>
|
||||||
<destFileName>keycloak-${project.version}.zip</destFileName>
|
</arguments>
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-server-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
<destFileName>keycloak-${project.version}.tar.gz</destFileName>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-demo-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
<destFileName>keycloak-demo-${project.version}.zip</destFileName>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-demo-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
<destFileName>keycloak-demo-${project.version}.tar.gz</destFileName>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-server-overlay</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
<destFileName>keycloak-overlay-${project.version}.zip</destFileName>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-server-overlay</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
<destFileName>keycloak-overlay-${project.version}.tar.gz</destFileName>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-proxy-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
<destFileName>keycloak-proxy-${project.version}.zip</destFileName>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-api-docs-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
<destFileName>keycloak-api-docs-${project.version}.zip</destFileName>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-examples-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
<destFileName>keycloak-examples-${project.version}.zip</destFileName>
|
|
||||||
</artifactItem>
|
|
||||||
</artifactItems>
|
|
||||||
<outputDirectory>target/${project.version}</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
|
|
||||||
<execution>
|
|
||||||
<id>adapter-downloads</id>
|
|
||||||
<phase>install</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<artifactItems>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-as7-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-as7-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-eap6-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-eap6-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty81-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty81-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty91-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty91-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty92-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty92-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty93-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-jetty93-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-js-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-js-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-tomcat6-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-tomcat6-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-tomcat7-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-tomcat7-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-tomcat8-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-tomcat8-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-wf8-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-wf8-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-wildfly-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-wildfly-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-fuse-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-fuse-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
</artifactItems>
|
|
||||||
<outputDirectory>target/${project.version}/adapters/keycloak-oidc</outputDirectory>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
<execution>
|
|
||||||
<id>saml-adapter-downloads</id>
|
|
||||||
<phase>install</phase>
|
|
||||||
<goals>
|
|
||||||
<goal>copy</goal>
|
|
||||||
</goals>
|
|
||||||
<configuration>
|
|
||||||
<artifactItems>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-as7-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-as7-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-eap6-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-eap6-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-jetty81-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-jetty81-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-jetty92-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-jetty92-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-jetty93-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-jetty93-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-tomcat6-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-tomcat6-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-tomcat7-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-tomcat7-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-tomcat8-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-tomcat8-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-wildfly-adapter-dist</artifactId>
|
|
||||||
<type>zip</type>
|
|
||||||
</artifactItem>
|
|
||||||
<artifactItem>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-saml-wildfly-adapter-dist</artifactId>
|
|
||||||
<type>tar.gz</type>
|
|
||||||
</artifactItem>
|
|
||||||
</artifactItems>
|
|
||||||
<outputDirectory>target/${project.version}/adapters/saml</outputDirectory>
|
|
||||||
</configuration>
|
</configuration>
|
||||||
</execution>
|
</execution>
|
||||||
</executions>
|
</executions>
|
||||||
|
|
49
distribution/downloads/src/main/java/CopyDependencies.java
Normal file
49
distribution/downloads/src/main/java/CopyDependencies.java
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by st on 06.02.17.
|
||||||
|
*/
|
||||||
|
public class CopyDependencies {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
String version = args[2];
|
||||||
|
|
||||||
|
Path repository = new File(args[0]).toPath().resolve("org").resolve("keycloak");
|
||||||
|
Path targetRoot = new File(args[1]).toPath().resolve(version);
|
||||||
|
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(CopyDependencies.class.getResourceAsStream("files")));
|
||||||
|
|
||||||
|
Path target = targetRoot;
|
||||||
|
for (String l = br.readLine(); l != null; l = br.readLine()) {
|
||||||
|
|
||||||
|
if (l.startsWith("./")) {
|
||||||
|
target = targetRoot.resolve(l.replace("./", "").replace('/', File.separatorChar));
|
||||||
|
if (!target.toFile().isDirectory()) {
|
||||||
|
target.toFile().mkdirs();
|
||||||
|
}
|
||||||
|
} else if (l.trim().length() > 0) {
|
||||||
|
String[] t = l.trim().split(":");
|
||||||
|
|
||||||
|
String artifactName = t[0];
|
||||||
|
String destName = t.length == 1 ? artifactName : t[1];
|
||||||
|
|
||||||
|
File artifactDir = repository.resolve(artifactName).resolve(version).toFile();
|
||||||
|
|
||||||
|
for (File f : artifactDir.listFiles((file, name) -> name.contains(".tar.gz") || name.contains(".zip"))) {
|
||||||
|
Files.copy(f.toPath(), target.resolve(f.getName().replace(artifactName, destName)), StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println(artifactName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
br.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
33
distribution/downloads/src/main/resources/files
Normal file
33
distribution/downloads/src/main/resources/files
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
./
|
||||||
|
keycloak-server-dist:keycloak
|
||||||
|
keycloak-demo-dist:keycloak-demo
|
||||||
|
keycloak-server-overlay:keycloak-overlay
|
||||||
|
keycloak-proxy-dist:keycloak-proxy
|
||||||
|
keycloak-api-docs-dist:keycloak-api-docs
|
||||||
|
keycloak-examples-dist:keycloak-examples
|
||||||
|
|
||||||
|
./adapters/keycloak-oidc
|
||||||
|
keycloak-as7-adapter-dist
|
||||||
|
keycloak-eap6-adapter-dist
|
||||||
|
keycloak-jetty81-adapter-dist
|
||||||
|
keycloak-jetty91-adapter-dist
|
||||||
|
keycloak-jetty92-adapter-dist
|
||||||
|
keycloak-jetty93-adapter-dist
|
||||||
|
keycloak-js-adapter-dist
|
||||||
|
keycloak-tomcat6-adapter-dist
|
||||||
|
keycloak-tomcat7-adapter-dist
|
||||||
|
keycloak-tomcat8-adapter-dist
|
||||||
|
keycloak-wf8-adapter-dist
|
||||||
|
keycloak-wildfly-adapter-dist
|
||||||
|
keycloak-fuse-adapter-dist
|
||||||
|
|
||||||
|
./adapters/saml
|
||||||
|
keycloak-saml-as7-adapter-dist
|
||||||
|
keycloak-saml-eap6-adapter-dist
|
||||||
|
keycloak-saml-jetty81-adapter-dist
|
||||||
|
keycloak-saml-jetty92-adapter-dist
|
||||||
|
keycloak-saml-jetty93-adapter-dist
|
||||||
|
keycloak-saml-tomcat6-adapter-dist
|
||||||
|
keycloak-saml-tomcat7-adapter-dist
|
||||||
|
keycloak-saml-tomcat8-adapter-dist
|
||||||
|
keycloak-saml-wildfly-adapter-dist
|
|
@ -55,6 +55,13 @@
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-undertow-adapter</artifactId>
|
<artifactId>keycloak-undertow-adapter</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Authorization -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-authz-client</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.wildfly</groupId>
|
<groupId>org.wildfly</groupId>
|
||||||
<artifactId>wildfly-feature-pack</artifactId>
|
<artifactId>wildfly-feature-pack</artifactId>
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
<module name="org.keycloak.keycloak-adapter-spi"/>
|
<module name="org.keycloak.keycloak-adapter-spi"/>
|
||||||
<module name="org.keycloak.keycloak-common"/>
|
<module name="org.keycloak.keycloak-common"/>
|
||||||
<module name="org.keycloak.keycloak-core"/>
|
<module name="org.keycloak.keycloak-core"/>
|
||||||
|
<module name="org.keycloak.keycloak-authz-client"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</module>
|
</module>
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
~ * Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
~ * and other contributors as indicated by the @author tags.
|
||||||
|
~ *
|
||||||
|
~ * Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
~ * you may not use this file except in compliance with the License.
|
||||||
|
~ * You may obtain a copy of the License at
|
||||||
|
~ *
|
||||||
|
~ * http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
~ *
|
||||||
|
~ * Unless required by applicable law or agreed to in writing, software
|
||||||
|
~ * distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
~ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
~ * See the License for the specific language governing permissions and
|
||||||
|
~ * limitations under the License.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<module xmlns="urn:jboss:module:1.3" name="org.keycloak.keycloak-authz-client">
|
||||||
|
<resources>
|
||||||
|
<artifact name="${org.keycloak:keycloak-authz-client}"/>
|
||||||
|
</resources>
|
||||||
|
<dependencies>
|
||||||
|
<module name="org.bouncycastle" />
|
||||||
|
<module name="javax.api"/>
|
||||||
|
<module name="javax.activation.api"/>
|
||||||
|
<module name="sun.jdk" optional="true" />
|
||||||
|
<module name="javax.ws.rs.api"/>
|
||||||
|
<module name="org.keycloak.keycloak-core"/>
|
||||||
|
<module name="org.keycloak.keycloak-common"/>
|
||||||
|
<module name="org.apache.httpcomponents"/>
|
||||||
|
<module name="com.fasterxml.jackson.core.jackson-core"/>
|
||||||
|
<module name="com.fasterxml.jackson.core.jackson-annotations"/>
|
||||||
|
<module name="com.fasterxml.jackson.core.jackson-databind"/>
|
||||||
|
<module name="com.fasterxml.jackson.jaxrs.jackson-jaxrs-json-provider"/>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</module>
|
|
@ -1,9 +1,5 @@
|
||||||
embed-host-controller --domain-config=domain.xml
|
embed-host-controller --domain-config=domain.xml
|
||||||
|
|
||||||
# Early versions of keycloak used "default" for the standalone profile name.
|
|
||||||
# Yours maybe be something completely different.
|
|
||||||
set standaloneProfile=auth-server-standalone
|
|
||||||
|
|
||||||
# Early versions of keycloak used "ha" for the clustered profile name.
|
# Early versions of keycloak used "ha" for the clustered profile name.
|
||||||
# Yours maybe be something completely different.
|
# Yours maybe be something completely different.
|
||||||
set clusteredProfile=auth-server-clustered
|
set clusteredProfile=auth-server-clustered
|
||||||
|
@ -12,125 +8,6 @@ set clusteredProfile=auth-server-clustered
|
||||||
set pathToJson=../domain/configuration/keycloak-server.json
|
set pathToJson=../domain/configuration/keycloak-server.json
|
||||||
|
|
||||||
|
|
||||||
echo *** Begin Migration of /profile=$standaloneProfile ***
|
|
||||||
echo
|
|
||||||
|
|
||||||
# Migrate from 1.8.1 to 1.9.1
|
|
||||||
if (outcome == failed) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=work/:read-resource
|
|
||||||
echo Adding local-cache=work to keycloak cache container...
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=work/:add(indexing=NONE,start=LAZY)
|
|
||||||
echo
|
|
||||||
end-if
|
|
||||||
# realmVersions cache deprecated in 2.1.0
|
|
||||||
#if (outcome == failed) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/:read-resource
|
|
||||||
# echo Adding local-cache=realmVersions to keycloak cache container...
|
|
||||||
# /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/:add(indexing=NONE,start=LAZY)
|
|
||||||
# /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/component=transaction/:write-attribute(name=mode,value=BATCH)
|
|
||||||
# echo
|
|
||||||
#end-if
|
|
||||||
|
|
||||||
|
|
||||||
# Migrate from 1.9.1 to 1.9.2
|
|
||||||
if (result == NONE) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=users/component=eviction/:read-attribute(name=strategy)
|
|
||||||
echo Adding eviction strategy to keycloak users cache container...
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=users/component=eviction/:write-attribute(name=strategy,value=LRU)
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=users/component=eviction/:write-attribute(name=max-entries,value=10000)
|
|
||||||
echo
|
|
||||||
end-if
|
|
||||||
|
|
||||||
# Migrate from 1.9.2 to 1.9.8
|
|
||||||
# NO CHANGES
|
|
||||||
|
|
||||||
# Migrate from 1.9.8 to 2.0.0
|
|
||||||
if (outcome == failed) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=authorization/:read-resource
|
|
||||||
echo Adding local-cache=authorization to keycloak cache container...
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=authorization/:add(indexing=NONE,start=LAZY)
|
|
||||||
echo
|
|
||||||
end-if
|
|
||||||
if (result == undefined) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=authorization/component=eviction/:read-attribute(name=strategy,include-defaults=false)
|
|
||||||
echo Updating authorization cache container..
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=authorization/component=eviction/:write-attribute(name=strategy,value=LRU)
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=authorization/component=eviction/:write-attribute(name=max-entries,value=100)
|
|
||||||
end-if
|
|
||||||
|
|
||||||
# Migrate from 2.0.0 to 2.1.0
|
|
||||||
if (outcome == success) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/:read-resource
|
|
||||||
echo Removing deprecated cache 'realmVersions'
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/:remove
|
|
||||||
echo
|
|
||||||
end-if
|
|
||||||
|
|
||||||
# Migrate kecloak-server.json (deprecated in 2.2.0)
|
|
||||||
if (result == []) of /profile=$standaloneProfile/subsystem=keycloak-server/:read-children-names(child-type=spi)
|
|
||||||
echo Migrating keycloak-server.json to keycloak-server subsystem...
|
|
||||||
/profile=$standaloneProfile/subsystem=keycloak-server/:migrate-json(file=$pathToJson)
|
|
||||||
echo
|
|
||||||
end-if
|
|
||||||
|
|
||||||
# Find if we are using jpa or mongo
|
|
||||||
if (result == mongo) of /profile=$standaloneProfile/subsystem=keycloak-server/spi=realm/:read-attribute(name=default-provider)
|
|
||||||
set persistenceProvider=mongo
|
|
||||||
else
|
|
||||||
set persistenceProvider=jpa
|
|
||||||
end-if
|
|
||||||
|
|
||||||
# Migrate from 2.1.0 to 2.2.0
|
|
||||||
if (result == update) of /profile=$standaloneProfile/subsystem=keycloak-server/spi=connectionsJpa/provider=default/:map-get(name=properties,key=databaseSchema)
|
|
||||||
echo Updating connectionsJpa default properties...
|
|
||||||
/profile=$standaloneProfile/subsystem=keycloak-server/spi=connectionsJpa/provider=default/:map-remove(name=properties,key=databaseSchema)
|
|
||||||
/profile=$standaloneProfile/subsystem=keycloak-server/spi=connectionsJpa/provider=default/:map-put(name=properties,key=initializeEmpty,value=true)
|
|
||||||
/profile=$standaloneProfile/subsystem=keycloak-server/spi=connectionsJpa/provider=default/:map-put(name=properties,key=migrationStrategy,value=update)
|
|
||||||
/profile=$standaloneProfile/subsystem=keycloak-server/spi=connectionsJpa/provider=default/:map-put(name=properties,key=migrationExport,value=${jboss.home.dir}/keycloak-database-update.sql)
|
|
||||||
echo
|
|
||||||
end-if
|
|
||||||
if (outcome == failed) of /profile=$standaloneProfile/subsystem=keycloak-server/spi=userFederatedStorage/:read-resource
|
|
||||||
echo Adding spi=userFederatedStorage...
|
|
||||||
/profile=$standaloneProfile/subsystem=keycloak-server/spi=userFederatedStorage/:add(default-provider=$persistenceProvider)
|
|
||||||
echo
|
|
||||||
end-if
|
|
||||||
if (outcome == failed) of /profile=$standaloneProfile/subsystem=keycloak-server/spi=jta-lookup/:read-resource
|
|
||||||
echo Adding spi=jta-lookup...
|
|
||||||
/profile=$standaloneProfile/subsystem=keycloak-server/spi=jta-lookup/:add(default-provider=${keycloak.jta.lookup.provider:jboss})
|
|
||||||
/profile=$standaloneProfile/subsystem=keycloak-server/spi=jta-lookup/provider=jboss/:add(enabled=true)
|
|
||||||
echo
|
|
||||||
end-if
|
|
||||||
|
|
||||||
# Migrate from 2.2.0 to 2.2.1
|
|
||||||
# NO CHANGES
|
|
||||||
|
|
||||||
# Migrate from 2.2.1 to 2.3.0
|
|
||||||
if (outcome == failed) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=keys/:read-resource
|
|
||||||
echo Adding local-cache=keys to keycloak cache container...
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=keys/:add(indexing=NONE,start=LAZY)
|
|
||||||
echo
|
|
||||||
end-if
|
|
||||||
if (result == undefined) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=keys/component=eviction/:read-attribute(name=strategy,include-defaults=false)
|
|
||||||
echo Updating eviction and expiration in local-cache=keys...
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=keys/component=eviction/:write-attribute(name=strategy,value=LRU)
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=keys/component=eviction/:write-attribute(name=max-entries,value=1000)
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=keys/component=expiration/:write-attribute(name=max-idle,value=3600000)
|
|
||||||
echo
|
|
||||||
end-if
|
|
||||||
if (outcome == failed) of /profile=$standaloneProfile/subsystem=keycloak-server/spi=publicKeyStorage/:read-resource
|
|
||||||
echo Adding spi=publicKeyStorage...
|
|
||||||
/profile=$standaloneProfile/subsystem=keycloak-server/spi=publicKeyStorage/:add
|
|
||||||
/profile=$standaloneProfile/subsystem=keycloak-server/spi=publicKeyStorage/provider=infinispan/:add(properties={minTimeBetweenRequests => "10"},enabled=true)
|
|
||||||
echo
|
|
||||||
end-if
|
|
||||||
|
|
||||||
# Migrate from 2.3.0 to 2.4.0
|
|
||||||
# NO CHANGES
|
|
||||||
|
|
||||||
# Migrate from 2.4.0 to 2.5.0
|
|
||||||
if (result == NONE) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realms/component=eviction/:read-attribute(name=strategy)
|
|
||||||
echo Adding eviction strategy to keycloak realms cache...
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realms/component=eviction/:write-attribute(name=strategy,value=LRU)
|
|
||||||
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realms/component=eviction/:write-attribute(name=max-entries,value=10000)
|
|
||||||
echo
|
|
||||||
end-if
|
|
||||||
|
|
||||||
echo *** End Migration of /profile=$standaloneProfile ***
|
|
||||||
echo
|
|
||||||
echo
|
echo
|
||||||
echo *** Begin Migration of /profile=$clusteredProfile ***
|
echo *** Begin Migration of /profile=$clusteredProfile ***
|
||||||
echo
|
echo
|
||||||
|
@ -260,4 +137,4 @@ if (result == NONE) of /profile=$clusteredProfile/subsystem=infinispan/cache-con
|
||||||
echo
|
echo
|
||||||
end-if
|
end-if
|
||||||
|
|
||||||
echo *** End Migration ***
|
echo *** End Migration of /profile=$clusteredProfile ***
|
|
@ -0,0 +1,128 @@
|
||||||
|
embed-host-controller --domain-config=domain.xml
|
||||||
|
|
||||||
|
# Early versions of keycloak used "default" for the standalone profile name.
|
||||||
|
# Yours maybe be something completely different.
|
||||||
|
set standaloneProfile=auth-server-standalone
|
||||||
|
|
||||||
|
# keycloak-server.json is not normally on this path.
|
||||||
|
set pathToJson=../domain/configuration/keycloak-server.json
|
||||||
|
|
||||||
|
|
||||||
|
echo *** Begin Migration of /profile=$standaloneProfile ***
|
||||||
|
echo
|
||||||
|
|
||||||
|
# Migrate from 1.8.1 to 1.9.1
|
||||||
|
if (outcome == failed) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=work/:read-resource
|
||||||
|
echo Adding local-cache=work to keycloak cache container...
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=work/:add(indexing=NONE,start=LAZY)
|
||||||
|
echo
|
||||||
|
end-if
|
||||||
|
# realmVersions cache deprecated in 2.1.0
|
||||||
|
#if (outcome == failed) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/:read-resource
|
||||||
|
# echo Adding local-cache=realmVersions to keycloak cache container...
|
||||||
|
# /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/:add(indexing=NONE,start=LAZY)
|
||||||
|
# /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/component=transaction/:write-attribute(name=mode,value=BATCH)
|
||||||
|
# echo
|
||||||
|
#end-if
|
||||||
|
|
||||||
|
|
||||||
|
# Migrate from 1.9.1 to 1.9.2
|
||||||
|
if (result == NONE) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=users/component=eviction/:read-attribute(name=strategy)
|
||||||
|
echo Adding eviction strategy to keycloak users cache container...
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=users/component=eviction/:write-attribute(name=strategy,value=LRU)
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=users/component=eviction/:write-attribute(name=max-entries,value=10000)
|
||||||
|
echo
|
||||||
|
end-if
|
||||||
|
|
||||||
|
# Migrate from 1.9.2 to 1.9.8
|
||||||
|
# NO CHANGES
|
||||||
|
|
||||||
|
# Migrate from 1.9.8 to 2.0.0
|
||||||
|
if (outcome == failed) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=authorization/:read-resource
|
||||||
|
echo Adding local-cache=authorization to keycloak cache container...
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=authorization/:add(indexing=NONE,start=LAZY)
|
||||||
|
echo
|
||||||
|
end-if
|
||||||
|
if (result == undefined) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=authorization/component=eviction/:read-attribute(name=strategy,include-defaults=false)
|
||||||
|
echo Updating authorization cache container..
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=authorization/component=eviction/:write-attribute(name=strategy,value=LRU)
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=authorization/component=eviction/:write-attribute(name=max-entries,value=100)
|
||||||
|
end-if
|
||||||
|
|
||||||
|
# Migrate from 2.0.0 to 2.1.0
|
||||||
|
if (outcome == success) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/:read-resource
|
||||||
|
echo Removing deprecated cache 'realmVersions'
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realmVersions/:remove
|
||||||
|
echo
|
||||||
|
end-if
|
||||||
|
|
||||||
|
# Migrate kecloak-server.json (deprecated in 2.2.0)
|
||||||
|
if (result == []) of /profile=$standaloneProfile/subsystem=keycloak-server/:read-children-names(child-type=spi)
|
||||||
|
echo Migrating keycloak-server.json to keycloak-server subsystem...
|
||||||
|
/profile=$standaloneProfile/subsystem=keycloak-server/:migrate-json(file=$pathToJson)
|
||||||
|
echo
|
||||||
|
end-if
|
||||||
|
|
||||||
|
# Find if we are using jpa or mongo
|
||||||
|
if (result == mongo) of /profile=$standaloneProfile/subsystem=keycloak-server/spi=realm/:read-attribute(name=default-provider)
|
||||||
|
set persistenceProvider=mongo
|
||||||
|
else
|
||||||
|
set persistenceProvider=jpa
|
||||||
|
end-if
|
||||||
|
|
||||||
|
# Migrate from 2.1.0 to 2.2.0
|
||||||
|
if (result == update) of /profile=$standaloneProfile/subsystem=keycloak-server/spi=connectionsJpa/provider=default/:map-get(name=properties,key=databaseSchema)
|
||||||
|
echo Updating connectionsJpa default properties...
|
||||||
|
/profile=$standaloneProfile/subsystem=keycloak-server/spi=connectionsJpa/provider=default/:map-remove(name=properties,key=databaseSchema)
|
||||||
|
/profile=$standaloneProfile/subsystem=keycloak-server/spi=connectionsJpa/provider=default/:map-put(name=properties,key=initializeEmpty,value=true)
|
||||||
|
/profile=$standaloneProfile/subsystem=keycloak-server/spi=connectionsJpa/provider=default/:map-put(name=properties,key=migrationStrategy,value=update)
|
||||||
|
/profile=$standaloneProfile/subsystem=keycloak-server/spi=connectionsJpa/provider=default/:map-put(name=properties,key=migrationExport,value=${jboss.home.dir}/keycloak-database-update.sql)
|
||||||
|
echo
|
||||||
|
end-if
|
||||||
|
if (outcome == failed) of /profile=$standaloneProfile/subsystem=keycloak-server/spi=userFederatedStorage/:read-resource
|
||||||
|
echo Adding spi=userFederatedStorage...
|
||||||
|
/profile=$standaloneProfile/subsystem=keycloak-server/spi=userFederatedStorage/:add(default-provider=$persistenceProvider)
|
||||||
|
echo
|
||||||
|
end-if
|
||||||
|
if (outcome == failed) of /profile=$standaloneProfile/subsystem=keycloak-server/spi=jta-lookup/:read-resource
|
||||||
|
echo Adding spi=jta-lookup...
|
||||||
|
/profile=$standaloneProfile/subsystem=keycloak-server/spi=jta-lookup/:add(default-provider=${keycloak.jta.lookup.provider:jboss})
|
||||||
|
/profile=$standaloneProfile/subsystem=keycloak-server/spi=jta-lookup/provider=jboss/:add(enabled=true)
|
||||||
|
echo
|
||||||
|
end-if
|
||||||
|
|
||||||
|
# Migrate from 2.2.0 to 2.2.1
|
||||||
|
# NO CHANGES
|
||||||
|
|
||||||
|
# Migrate from 2.2.1 to 2.3.0
|
||||||
|
if (outcome == failed) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=keys/:read-resource
|
||||||
|
echo Adding local-cache=keys to keycloak cache container...
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=keys/:add(indexing=NONE,start=LAZY)
|
||||||
|
echo
|
||||||
|
end-if
|
||||||
|
if (result == undefined) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=keys/component=eviction/:read-attribute(name=strategy,include-defaults=false)
|
||||||
|
echo Updating eviction and expiration in local-cache=keys...
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=keys/component=eviction/:write-attribute(name=strategy,value=LRU)
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=keys/component=eviction/:write-attribute(name=max-entries,value=1000)
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=keys/component=expiration/:write-attribute(name=max-idle,value=3600000)
|
||||||
|
echo
|
||||||
|
end-if
|
||||||
|
if (outcome == failed) of /profile=$standaloneProfile/subsystem=keycloak-server/spi=publicKeyStorage/:read-resource
|
||||||
|
echo Adding spi=publicKeyStorage...
|
||||||
|
/profile=$standaloneProfile/subsystem=keycloak-server/spi=publicKeyStorage/:add
|
||||||
|
/profile=$standaloneProfile/subsystem=keycloak-server/spi=publicKeyStorage/provider=infinispan/:add(properties={minTimeBetweenRequests => "10"},enabled=true)
|
||||||
|
echo
|
||||||
|
end-if
|
||||||
|
|
||||||
|
# Migrate from 2.3.0 to 2.4.0
|
||||||
|
# NO CHANGES
|
||||||
|
|
||||||
|
# Migrate from 2.4.0 to 2.5.0
|
||||||
|
if (result == NONE) of /profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realms/component=eviction/:read-attribute(name=strategy)
|
||||||
|
echo Adding eviction strategy to keycloak realms cache...
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realms/component=eviction/:write-attribute(name=strategy,value=LRU)
|
||||||
|
/profile=$standaloneProfile/subsystem=infinispan/cache-container=keycloak/local-cache=realms/component=eviction/:write-attribute(name=max-entries,value=10000)
|
||||||
|
echo
|
||||||
|
end-if
|
||||||
|
|
||||||
|
echo *** End Migration of /profile=$standaloneProfile ***
|
|
@ -124,6 +124,11 @@ public class LDAPIdentityStore implements IdentityStore {
|
||||||
|
|
||||||
String rdnAttrVal = ldapObject.getAttributeAsString(rdnAttrName);
|
String rdnAttrVal = ldapObject.getAttributeAsString(rdnAttrName);
|
||||||
|
|
||||||
|
// Could be the case when RDN attribute of the target object is not included in Keycloak mappers
|
||||||
|
if (rdnAttrVal == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
String oldRdnAttrVal = ldapObject.getDn().getFirstRdnAttrValue();
|
String oldRdnAttrVal = ldapObject.getDn().getFirstRdnAttrValue();
|
||||||
if (!oldRdnAttrVal.equals(rdnAttrVal)) {
|
if (!oldRdnAttrVal.equals(rdnAttrVal)) {
|
||||||
LDAPDn newLdapDn = ldapObject.getDn().getParentDn();
|
LDAPDn newLdapDn = ldapObject.getDn().getParentDn();
|
||||||
|
|
|
@ -40,7 +40,9 @@ public class MigrateUserFedToComponent extends AbstractUserFedToComponent {
|
||||||
protected void generateStatementsImpl() throws CustomChangeException {
|
protected void generateStatementsImpl() throws CustomChangeException {
|
||||||
List<ProviderFactory> factories = kcSession.getKeycloakSessionFactory().getProviderFactories(UserStorageProvider.class);
|
List<ProviderFactory> factories = kcSession.getKeycloakSessionFactory().getProviderFactories(UserStorageProvider.class);
|
||||||
for (ProviderFactory factory : factories) {
|
for (ProviderFactory factory : factories) {
|
||||||
convertFedProviderToComponent(factory.getId(), null);
|
if (!factory.getId().equals(LDAPConstants.LDAP_PROVIDER)) {
|
||||||
|
convertFedProviderToComponent(factory.getId(), null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ public class PortLdapUserFedToComponentModel extends AbstractUserFedToComponent
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateStatementsImpl() throws CustomChangeException {
|
protected void generateStatementsImpl() throws CustomChangeException {
|
||||||
String providerId = LDAPConstants.LDAP_PROVIDER;
|
|
||||||
convertFedProviderToComponent(LDAPConstants.LDAP_PROVIDER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
|
convertFedProviderToComponent(LDAPConstants.LDAP_PROVIDER, "org.keycloak.storage.ldap.mappers.LDAPStorageMapper");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,9 @@ public class KeyInfoTools {
|
||||||
* @return The object or {@code null} if not found.
|
* @return The object or {@code null} if not found.
|
||||||
*/
|
*/
|
||||||
public static <T> T getContent(Iterable<Object> objects, Class<T> clazz) {
|
public static <T> T getContent(Iterable<Object> objects, Class<T> clazz) {
|
||||||
|
if (objects == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
for (Object o : objects) {
|
for (Object o : objects) {
|
||||||
if (clazz.isInstance(o)) {
|
if (clazz.isInstance(o)) {
|
||||||
return (T) o;
|
return (T) o;
|
||||||
|
@ -45,11 +48,11 @@ public class KeyInfoTools {
|
||||||
|
|
||||||
|
|
||||||
public static KeyName getKeyName(KeyInfo keyInfo) {
|
public static KeyName getKeyName(KeyInfo keyInfo) {
|
||||||
return getContent(keyInfo.getContent(), KeyName.class);
|
return keyInfo == null ? null : getContent(keyInfo.getContent(), KeyName.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static X509Data getX509Data(KeyInfo keyInfo) {
|
public static X509Data getX509Data(KeyInfo keyInfo) {
|
||||||
return getContent(keyInfo.getContent(), X509Data.class);
|
return keyInfo == null ? null : getContent(keyInfo.getContent(), X509Data.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static X509Certificate getX509Certificate(KeyInfo keyInfo) {
|
public static X509Certificate getX509Certificate(KeyInfo keyInfo) {
|
||||||
|
|
|
@ -801,7 +801,7 @@ public class ModelToRepresentation {
|
||||||
representation.setType(model.getType());
|
representation.setType(model.getType());
|
||||||
representation.setDecisionStrategy(model.getDecisionStrategy());
|
representation.setDecisionStrategy(model.getDecisionStrategy());
|
||||||
representation.setLogic(model.getLogic());
|
representation.setLogic(model.getLogic());
|
||||||
representation.setConfig(model.getConfig());
|
representation.setConfig(new HashMap<>(model.getConfig()));
|
||||||
|
|
||||||
return representation;
|
return representation;
|
||||||
}
|
}
|
||||||
|
|
|
@ -173,13 +173,17 @@ public class UserAttributeMapper extends AbstractIdentityProviderMapper {
|
||||||
setIfNotEmpty(user::setLastName, attributeValuesInContext);
|
setIfNotEmpty(user::setLastName, attributeValuesInContext);
|
||||||
} else {
|
} else {
|
||||||
List<String> currentAttributeValues = user.getAttributes().get(attribute);
|
List<String> currentAttributeValues = user.getAttributes().get(attribute);
|
||||||
if (attributeValuesInContext != null
|
if (attributeValuesInContext == null) {
|
||||||
&& currentAttributeValues != null
|
// attribute no longer sent by brokered idp, remove it
|
||||||
&& !CollectionUtil.collectionEquals(attributeValuesInContext, currentAttributeValues)) {
|
|
||||||
user.setAttribute(attribute, attributeValuesInContext);
|
|
||||||
} else if (attributeValuesInContext == null) {
|
|
||||||
user.removeAttribute(attribute);
|
user.removeAttribute(attribute);
|
||||||
|
} else if (currentAttributeValues == null) {
|
||||||
|
// new attribute sent by brokered idp, add it
|
||||||
|
user.setAttribute(attribute, attributeValuesInContext);
|
||||||
|
} else if (!CollectionUtil.collectionEquals(attributeValuesInContext, currentAttributeValues)) {
|
||||||
|
// attribute sent by brokered idp has different values as before, update it
|
||||||
|
user.setAttribute(attribute, attributeValuesInContext);
|
||||||
}
|
}
|
||||||
|
// attribute allready set
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -371,7 +371,7 @@ public class ExportUtils {
|
||||||
Set<Resource> policyResources = policy.getResources();
|
Set<Resource> policyResources = policy.getResources();
|
||||||
|
|
||||||
if (!policyResources.isEmpty()) {
|
if (!policyResources.isEmpty()) {
|
||||||
List<String> resourceNames = scopes.stream().map(Scope::getName).collect(Collectors.toList());
|
List<String> resourceNames = policyResources.stream().map(Resource::getName).collect(Collectors.toList());
|
||||||
config.put("resources", JsonSerialization.writeValueAsString(resourceNames));
|
config.put("resources", JsonSerialization.writeValueAsString(resourceNames));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -740,7 +740,7 @@ public class AuthenticationManager {
|
||||||
if (!isSessionValid(realm, userSession)) {
|
if (!isSessionValid(realm, userSession)) {
|
||||||
// Check if accessToken was for the offline session.
|
// Check if accessToken was for the offline session.
|
||||||
if (!isCookie) {
|
if (!isCookie) {
|
||||||
UserSessionModel offlineUserSession = session.sessions().getUserSession(realm, token.getSessionState());
|
UserSessionModel offlineUserSession = session.sessions().getOfflineUserSession(realm, token.getSessionState());
|
||||||
if (isOfflineSessionValid(realm, offlineUserSession)) {
|
if (isOfflineSessionValid(realm, offlineUserSession)) {
|
||||||
return new AuthResult(user, offlineUserSession, token);
|
return new AuthResult(user, offlineUserSession, token);
|
||||||
}
|
}
|
||||||
|
|
210
testsuite/integration-arquillian/HOW-TO-RUN.md
Normal file
210
testsuite/integration-arquillian/HOW-TO-RUN.md
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
How To Run various testsuite configurations
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
## Base steps
|
||||||
|
|
||||||
|
It's recomended to build the workspace including distribution.
|
||||||
|
|
||||||
|
````
|
||||||
|
cd $KEYCLOAK_SOURCES
|
||||||
|
mvn clean install -DskipTests=true
|
||||||
|
cd distribution
|
||||||
|
mvn clean install
|
||||||
|
````
|
||||||
|
|
||||||
|
## Run adapter tests
|
||||||
|
|
||||||
|
### Wildfly
|
||||||
|
|
||||||
|
````
|
||||||
|
# Prepare servers
|
||||||
|
mvn -f testsuite/integration-arquillian/servers/pom.xml clean install \
|
||||||
|
-Pauth-server-wildfly \
|
||||||
|
-Papp-server-wildfly
|
||||||
|
|
||||||
|
# Run tests
|
||||||
|
mvn -f testsuite/integration-arquillian/tests/other/adapters/jboss/wildfly/pom.xml \
|
||||||
|
clean install \
|
||||||
|
-Pauth-server-wildfly \
|
||||||
|
-Papp-server-wildfly
|
||||||
|
````
|
||||||
|
|
||||||
|
### JBoss Fuse 6.3
|
||||||
|
----------------------------------------
|
||||||
|
1) Download JBoss Fuse 6.3 to your filesystem. It can be downloaded from http://origin-repository.jboss.org/nexus/content/groups/m2-proxy/org/jboss/fuse/jboss-fuse-karaf
|
||||||
|
Assumed you downloaded `jboss-fuse-karaf-6.3.0.redhat-229.zip`
|
||||||
|
|
||||||
|
2) Install to your local maven repository and change the properties according to your env (This step can be likely avoided if you somehow configure your local maven settings to point directly to Fuse repo):
|
||||||
|
|
||||||
|
````
|
||||||
|
mvn install:install-file \
|
||||||
|
-DgroupId=org.jboss.fuse \
|
||||||
|
-DartifactId=jboss-fuse-karaf \
|
||||||
|
-Dversion=6.3.0.redhat-229 \
|
||||||
|
-Dpackaging=zip \
|
||||||
|
-Dfile=/mydownloads/jboss-fuse-karaf-6.3.0.redhat-229.zip
|
||||||
|
````
|
||||||
|
|
||||||
|
3) Prepare Fuse and run the tests (change props according to your environment, versions etc):
|
||||||
|
|
||||||
|
````
|
||||||
|
# Prepare Fuse server
|
||||||
|
mvn -f testsuite/integration-arquillian/servers \
|
||||||
|
clean install \
|
||||||
|
-Pauth-server-wildfly \
|
||||||
|
-Papp-server-fuse63 \
|
||||||
|
-Dfuse63.version=6.3.0.redhat-229 \
|
||||||
|
-Dapp.server.karaf.update.config=true \
|
||||||
|
-Dmaven.local.settings=$HOME/.m2/settings.xml \
|
||||||
|
-Drepositories=,http://download.eng.bos.redhat.com/brewroot/repos/sso-7.1-build/latest/maven/ \
|
||||||
|
-Dmaven.repo.local=$HOME/.m2/repository
|
||||||
|
|
||||||
|
# Run the Fuse adapter tests
|
||||||
|
mvn -f testsuite/integration-arquillian/tests/other/adapters/karaf/fuse63/pom.xml \
|
||||||
|
clean install \
|
||||||
|
-Pauth-server-wildfly \
|
||||||
|
-Papp-server-fuse63 \
|
||||||
|
-Dfuse63.version=6.3.0.redhat-229
|
||||||
|
````
|
||||||
|
|
||||||
|
### EAP6 with Hawtio
|
||||||
|
|
||||||
|
1) Download JBoss EAP 6.4.0.GA zip
|
||||||
|
|
||||||
|
2) Install to your local maven repository and change the properties according to your env (This step can be likely avoided if you somehow configure your local maven settings to point directly to EAP repo):
|
||||||
|
|
||||||
|
````
|
||||||
|
mvn install:install-file \
|
||||||
|
-DgroupId=org.jboss.as \
|
||||||
|
-DartifactId=jboss-as-dist \
|
||||||
|
-Dversion=7.5.0.Final-redhat-21 \
|
||||||
|
-Dpackaging=zip \
|
||||||
|
-Dfile=/mydownloads/jboss-eap-6.4.0.zip
|
||||||
|
````
|
||||||
|
|
||||||
|
3) Download Fuse EAP installer (for example from http://origin-repository.jboss.org/nexus/content/groups/m2-proxy/com/redhat/fuse/eap/fuse-eap-installer/6.3.0.redhat-220/ )
|
||||||
|
|
||||||
|
4) Install previously downloaded file manually
|
||||||
|
|
||||||
|
````
|
||||||
|
mvn install:install-file \
|
||||||
|
-DgroupId=com.redhat.fuse.eap \
|
||||||
|
-DartifactId=fuse-eap-installer \
|
||||||
|
-Dversion=6.3.0.redhat-220 \
|
||||||
|
-Dpackaging=jar \
|
||||||
|
-Dfile=/fuse-eap-installer-6.3.0.redhat-220.jar
|
||||||
|
````
|
||||||
|
|
||||||
|
5) Prepare EAP6 with Hawtio and run the test
|
||||||
|
|
||||||
|
````
|
||||||
|
# Prepare EAP6 and deploy hawtio
|
||||||
|
mvn -f testsuite/integration-arquillian/servers \
|
||||||
|
clean install \
|
||||||
|
-Pauth-server-wildfly \
|
||||||
|
-Papp-server-eap6-fuse \
|
||||||
|
-Dapp.server.jboss.version=7.5.0.Final-redhat-21 \
|
||||||
|
-Dfuse.installer.version=6.3.0.redhat-220
|
||||||
|
|
||||||
|
# Run the test
|
||||||
|
mvn -f testsuite/integration-arquillian/tests/other/adapters/jboss/eap6-fuse/pom.xml \
|
||||||
|
clean install \
|
||||||
|
-Pauth-server-wildfly \
|
||||||
|
-Papp-server-eap6-fuse
|
||||||
|
````
|
||||||
|
|
||||||
|
## Migration test
|
||||||
|
|
||||||
|
### DB migration test
|
||||||
|
|
||||||
|
This test will:
|
||||||
|
- start Keycloak 1.9.8
|
||||||
|
- import realm and some data to MySQL DB
|
||||||
|
- stop Keycloak 1.9.8
|
||||||
|
- start latest KEycloak, which automatically updates DB from 1.9.8
|
||||||
|
- Do some test that data are correct
|
||||||
|
|
||||||
|
|
||||||
|
1) Prepare MySQL DB and ensure that MySQL DB is empty. See [../../misc/DatabaseTesting.md](../../misc/DatabaseTesting.md) for some hints for locally prepare Docker MySQL image.
|
||||||
|
|
||||||
|
2) Run the test (Update according to your DB connection, versions etc):
|
||||||
|
|
||||||
|
````
|
||||||
|
export DB_HOST=localhost
|
||||||
|
|
||||||
|
mvn -f testsuite/integration-arquillian/pom.xml \
|
||||||
|
clean install \
|
||||||
|
-Pauth-server-wildfly,jpa,clean-jpa,auth-server-migration \
|
||||||
|
-Dtest=MigrationTest \
|
||||||
|
-Dmigration.mode=auto \
|
||||||
|
-Dmigrated.auth.server.version=1.9.8.Final \
|
||||||
|
-Djdbc.mvn.groupId=mysql \
|
||||||
|
-Djdbc.mvn.version=5.1.29 \
|
||||||
|
-Djdbc.mvn.artifactId=mysql-connector-java \
|
||||||
|
-Dkeycloak.connectionsJpa.url=jdbc:mysql://$DB_HOST/keycloak \
|
||||||
|
-Dkeycloak.connectionsJpa.user=keycloak \
|
||||||
|
-Dkeycloak.connectionsJpa.password=keycloak
|
||||||
|
````
|
||||||
|
|
||||||
|
### JSON export/import migration test
|
||||||
|
This will start latest Keycloak and import the realm JSON file, which was previously exported from Keycloak 1.9.8.Final
|
||||||
|
|
||||||
|
````
|
||||||
|
mvn -f testsuite/integration-arquillian/pom.xml \
|
||||||
|
clean install \
|
||||||
|
-Pauth-server-wildfly,migration-import \
|
||||||
|
-Dtest=MigrationTest \
|
||||||
|
-Dmigration.mode=import \
|
||||||
|
-Dmigrated.auth.server.version=1.9.8.Final
|
||||||
|
````
|
||||||
|
|
||||||
|
|
||||||
|
## Social Login
|
||||||
|
The social login tests require setup of all social networks including an example social user. These details can't be
|
||||||
|
shared as it would result in the clients and users eventually being blocked. By default these tests are skipped.
|
||||||
|
|
||||||
|
To run the full test you need to configure clients in Google, Facebook, GitHub, Twitter, LinkedIn, Microsoft and
|
||||||
|
StackOverflow. See the server administration guide for details on how to do that. Further, you also need to create a
|
||||||
|
sample user that can login to the social network.
|
||||||
|
|
||||||
|
The details should be added to a standard properties file. For some properties you can use shared common properties and
|
||||||
|
override when needed. Or you can specify these for all providers. All providers require at least clientId and
|
||||||
|
clientSecret (StackOverflow also requires clientKey).
|
||||||
|
|
||||||
|
An example social.properties file looks like:
|
||||||
|
|
||||||
|
common.username=sampleuser@example.org
|
||||||
|
common.password=commonpassword
|
||||||
|
common.profile.firstName=Foo
|
||||||
|
common.profile.lastName=Bar
|
||||||
|
common.profile.email=sampleuser@example.org
|
||||||
|
|
||||||
|
google.clientId=asdfasdfasdfasdfsadf
|
||||||
|
google.clientSecret=zxcvzxcvzxcvzxcv
|
||||||
|
|
||||||
|
facebook.clientId=asdfasdfasdfasdfsadf
|
||||||
|
facebook.clientSecret=zxcvzxcvzxcvzxcv
|
||||||
|
facebook.profile.lastName=Test
|
||||||
|
|
||||||
|
In the example above the common username, password and profile are shared for all providers, but Facebook has a
|
||||||
|
different last name.
|
||||||
|
|
||||||
|
Some providers actively block bots so you need to use a proper browser to test. Either Firefox or Chrome should work.
|
||||||
|
|
||||||
|
To run the tests run:
|
||||||
|
|
||||||
|
mvn -f testsuite/integration-arquillian/pom.xml \
|
||||||
|
clean install \
|
||||||
|
-Pauth-server-wildfly \
|
||||||
|
-Dtest=SocialLoginTest \
|
||||||
|
-Dbrowser=chrome \
|
||||||
|
-Dsocial.config=/path/to/social.properties
|
||||||
|
|
||||||
|
|
||||||
|
## Different Browsers
|
||||||
|
|
||||||
|
To run with Chrome add `-Dbrowser=chrome`. Depending on the Chrome version you have you may need to download the latest
|
||||||
|
chromedriver from https://sites.google.com/a/chromium.org/chromedriver/downloads and point to it with
|
||||||
|
`-Dwebdriver.chrome.driver=/path/to/chromedriver`.
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@
|
||||||
|
|
||||||
For overview see the **Modules Overview** section at the bottom of this README.
|
For overview see the **Modules Overview** section at the bottom of this README.
|
||||||
|
|
||||||
|
## How to run tests
|
||||||
|
|
||||||
|
See the file [HOW-TO-RUN.md](HOW-TO-RUN.md) .
|
||||||
|
|
||||||
## Container Lifecycles
|
## Container Lifecycles
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,8 @@ do
|
||||||
if "$UPDATE_CONFIG" == "true"; then
|
if "$UPDATE_CONFIG" == "true"; then
|
||||||
echo "Updating Config"
|
echo "Updating Config"
|
||||||
./client $CLIENT_AUTH -f update-config.cli
|
./client $CLIENT_AUTH -f update-config.cli
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Call update-config.cli failed!";
|
||||||
RESULT=1;
|
RESULT=1;
|
||||||
else
|
else
|
||||||
./client $CLIENT_AUTH config:list | grep org.ops4j.pax.url.mvn.
|
./client $CLIENT_AUTH config:list | grep org.ops4j.pax.url.mvn.
|
||||||
|
@ -34,12 +35,16 @@ do
|
||||||
|
|
||||||
echo "Installing features."
|
echo "Installing features."
|
||||||
./client $CLIENT_AUTH -f install-features.cli
|
./client $CLIENT_AUTH -f install-features.cli
|
||||||
if [ $? -ne 0 ]; then RESULT=1; fi
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Call install-features.cli failed!";
|
||||||
|
RESULT=1;
|
||||||
|
fi
|
||||||
|
|
||||||
if "$UPDATE_CONFIG" == "true"; then
|
if "$UPDATE_CONFIG" == "true"; then
|
||||||
echo "Updating Config - Keycloak authentication"
|
echo "Updating Config - Keycloak authentication"
|
||||||
./client $CLIENT_AUTH -f update-config-auth.cli
|
./client $CLIENT_AUTH -f update-config-auth.cli
|
||||||
if [ $? -ne 0 ]; then
|
if [ $? -ne 0 ]; then
|
||||||
|
echo "Call update-config-auth.cli failed!";
|
||||||
RESULT=1;
|
RESULT=1;
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
Binary file not shown.
|
@ -35,12 +35,17 @@ import static org.keycloak.testsuite.arquillian.AppServerTestEnricher.getAppServ
|
||||||
*/
|
*/
|
||||||
public class DeploymentTargetModifier extends AnnotationDeploymentScenarioGenerator {
|
public class DeploymentTargetModifier extends AnnotationDeploymentScenarioGenerator {
|
||||||
|
|
||||||
|
// Will be replaced in runtime by real auth-server-container
|
||||||
|
public static final String AUTH_SERVER_CURRENT = "auth-server-current";
|
||||||
|
|
||||||
protected final Logger log = Logger.getLogger(this.getClass());
|
protected final Logger log = Logger.getLogger(this.getClass());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<DeploymentDescription> generate(TestClass testClass) {
|
public List<DeploymentDescription> generate(TestClass testClass) {
|
||||||
List<DeploymentDescription> deployments = super.generate(testClass);
|
List<DeploymentDescription> deployments = super.generate(testClass);
|
||||||
|
|
||||||
|
checkAuthServerTestDeployment(deployments, testClass);
|
||||||
|
|
||||||
String appServerQualifier = getAppServerQualifier(
|
String appServerQualifier = getAppServerQualifier(
|
||||||
testClass.getJavaClass());
|
testClass.getJavaClass());
|
||||||
|
|
||||||
|
@ -56,4 +61,17 @@ public class DeploymentTargetModifier extends AnnotationDeploymentScenarioGenera
|
||||||
return deployments;
|
return deployments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkAuthServerTestDeployment(List<DeploymentDescription> descriptions, TestClass testClass) {
|
||||||
|
for (DeploymentDescription deployment : descriptions) {
|
||||||
|
if (deployment.getTarget() != null) {
|
||||||
|
String containerQualifier = deployment.getTarget().getName();
|
||||||
|
if (AUTH_SERVER_CURRENT.equals(containerQualifier)) {
|
||||||
|
String authServerQualifier = AuthServerTestEnricher.AUTH_SERVER_CONTAINER;
|
||||||
|
log.infof("Setting target container for deployment %s.%s: %s", testClass.getName(), deployment.getName(), authServerQualifier);
|
||||||
|
deployment.setTarget(new TargetDescription(authServerQualifier));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
package org.keycloak.testsuite.arquillian;
|
package org.keycloak.testsuite.arquillian;
|
||||||
|
|
||||||
import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
|
import org.jboss.arquillian.container.spi.client.container.DeployableContainer;
|
||||||
|
import org.jboss.arquillian.container.osgi.OSGiApplicationArchiveProcessor;
|
||||||
import org.jboss.arquillian.container.test.impl.enricher.resource.URLResourceProvider;
|
import org.jboss.arquillian.container.test.impl.enricher.resource.URLResourceProvider;
|
||||||
import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor;
|
import org.jboss.arquillian.container.test.spi.client.deployment.ApplicationArchiveProcessor;
|
||||||
import org.jboss.arquillian.container.test.spi.client.deployment.DeploymentScenarioGenerator;
|
import org.jboss.arquillian.container.test.spi.client.deployment.DeploymentScenarioGenerator;
|
||||||
|
@ -63,7 +64,8 @@ public class KeycloakArquillianExtension implements LoadableExtension {
|
||||||
builder
|
builder
|
||||||
.override(ResourceProvider.class, URLResourceProvider.class, URLProvider.class)
|
.override(ResourceProvider.class, URLResourceProvider.class, URLProvider.class)
|
||||||
.override(ResourceProvider.class, CustomizableURLResourceProvider.class, URLProvider.class)
|
.override(ResourceProvider.class, CustomizableURLResourceProvider.class, URLProvider.class)
|
||||||
.override(ResourceProvider.class, ContainerCustomizableURLResourceProvider.class, URLProvider.class);
|
.override(ResourceProvider.class, ContainerCustomizableURLResourceProvider.class, URLProvider.class)
|
||||||
|
.override(ApplicationArchiveProcessor.class, OSGiApplicationArchiveProcessor.class, KeycloakOSGiApplicationArchiveProcessor.class);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.testsuite.arquillian;
|
||||||
|
|
||||||
|
import org.jboss.arquillian.container.osgi.OSGiApplicationArchiveProcessor;
|
||||||
|
import org.jboss.arquillian.test.spi.TestClass;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.jboss.shrinkwrap.api.Archive;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
public class KeycloakOSGiApplicationArchiveProcessor extends OSGiApplicationArchiveProcessor {
|
||||||
|
|
||||||
|
private static final Logger log = Logger.getLogger(KeycloakOSGiApplicationArchiveProcessor.class);
|
||||||
|
|
||||||
|
// We want to ignore OSGI for exampleAdapter tests
|
||||||
|
@Override
|
||||||
|
public void process(Archive<?> appArchive, TestClass testClass) {
|
||||||
|
Class<?> clazz = testClass.getJavaClass();
|
||||||
|
boolean isExampleAdapterTest = isExampleAdapterTest(clazz);
|
||||||
|
|
||||||
|
if (isExampleAdapterTest) {
|
||||||
|
log.infof("Ignore OSGiApplicationArchiveProcessor for test %s", clazz.getName());
|
||||||
|
} else {
|
||||||
|
super.process(appArchive, testClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isExampleAdapterTest(Class<?> clazz) {
|
||||||
|
Class<?> parent = clazz;
|
||||||
|
while (true) {
|
||||||
|
parent = parent.getSuperclass();
|
||||||
|
if (parent == null) {
|
||||||
|
return false;
|
||||||
|
} else if (parent.getName().equals("org.keycloak.testsuite.adapter.AbstractExampleAdapterTest")) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -63,6 +63,10 @@ public class AccountUpdateProfilePage extends AbstractAccountPage {
|
||||||
return RealmsResource.accountUrl(UriBuilder.fromUri(getAuthServerRoot())).build("test").toString();
|
return RealmsResource.accountUrl(UriBuilder.fromUri(getAuthServerRoot())).build("test").toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getPath(String realm) {
|
||||||
|
return RealmsResource.accountUrl(UriBuilder.fromUri(getAuthServerRoot())).build(realm).toString();
|
||||||
|
}
|
||||||
|
|
||||||
public void updateProfile(String firstName, String lastName, String email) {
|
public void updateProfile(String firstName, String lastName, String email) {
|
||||||
firstNameInput.clear();
|
firstNameInput.clear();
|
||||||
firstNameInput.sendKeys(firstName);
|
firstNameInput.sendKeys(firstName);
|
||||||
|
@ -141,6 +145,10 @@ public class AccountUpdateProfilePage extends AbstractAccountPage {
|
||||||
driver.navigate().to(getPath());
|
driver.navigate().to(getPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void open(String realm) {
|
||||||
|
driver.navigate().to(getPath(realm));
|
||||||
|
}
|
||||||
|
|
||||||
public void backToApplication() {
|
public void backToApplication() {
|
||||||
backToApplicationLink.click();
|
backToApplicationLink.click();
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,12 +41,18 @@ public class LoginUpdateProfilePage extends AbstractPage {
|
||||||
private WebElement loginErrorMessage;
|
private WebElement loginErrorMessage;
|
||||||
|
|
||||||
public void update(String firstName, String lastName, String email) {
|
public void update(String firstName, String lastName, String email) {
|
||||||
firstNameInput.clear();
|
if (firstName != null) {
|
||||||
firstNameInput.sendKeys(firstName);
|
firstNameInput.clear();
|
||||||
lastNameInput.clear();
|
firstNameInput.sendKeys(firstName);
|
||||||
lastNameInput.sendKeys(lastName);
|
}
|
||||||
emailInput.clear();
|
if (lastName != null) {
|
||||||
emailInput.sendKeys(email);
|
lastNameInput.clear();
|
||||||
|
lastNameInput.sendKeys(lastName);
|
||||||
|
}
|
||||||
|
if (email != null) {
|
||||||
|
emailInput.clear();
|
||||||
|
emailInput.sendKeys(email);
|
||||||
|
}
|
||||||
submitButton.click();
|
submitButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,6 +116,7 @@ public abstract class AbstractFuseExampleAdapterTest extends AbstractExampleAdap
|
||||||
testRealmLoginPage.form().login("admin", "password");
|
testRealmLoginPage.form().login("admin", "password");
|
||||||
assertCurrentUrlStartsWith(adminInterface);
|
assertCurrentUrlStartsWith(adminInterface);
|
||||||
assertTrue(driver.getPageSource().contains("Hello admin!"));
|
assertTrue(driver.getPageSource().contains("Hello admin!"));
|
||||||
|
assertTrue(driver.getPageSource().contains("This second sentence is returned from a Camel RestDSL endpoint"));
|
||||||
|
|
||||||
customerListing.navigateTo();
|
customerListing.navigateTo();
|
||||||
customerListing.clickLogOut();
|
customerListing.clickLogOut();
|
||||||
|
|
|
@ -233,4 +233,24 @@ public abstract class AbstractUserAttributeMapperTest extends AbstractBaseBroker
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testAddBasicMappingMultipleValues() {
|
||||||
|
testValueMapping(ImmutableMap.<String, List<String>>builder()
|
||||||
|
.build(),
|
||||||
|
ImmutableMap.<String, List<String>>builder()
|
||||||
|
.put(ATTRIBUTE_TO_MAP_NAME, ImmutableList.<String>builder().add("second value").add("second value 2").build())
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDeleteBasicMappingMultipleValues() {
|
||||||
|
testValueMapping(ImmutableMap.<String, List<String>>builder()
|
||||||
|
.put(ATTRIBUTE_TO_MAP_NAME, ImmutableList.<String>builder().add("second value").add("second value 2").build())
|
||||||
|
.build(),
|
||||||
|
ImmutableMap.<String, List<String>>builder()
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,232 @@
|
||||||
|
package org.keycloak.testsuite.broker;
|
||||||
|
|
||||||
|
import org.jboss.arquillian.graphene.Graphene;
|
||||||
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
|
import org.jboss.arquillian.graphene.wait.WebDriverWait;
|
||||||
|
import org.junit.Assume;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.keycloak.common.Profile;
|
||||||
|
import org.keycloak.representations.idm.IdentityProviderRepresentation;
|
||||||
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
|
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||||
|
import org.keycloak.testsuite.cli.exec.ExecutionException;
|
||||||
|
import org.keycloak.testsuite.pages.AccountUpdateProfilePage;
|
||||||
|
import org.keycloak.testsuite.pages.LoginPage;
|
||||||
|
import org.keycloak.testsuite.pages.LoginUpdateProfilePage;
|
||||||
|
import org.keycloak.testsuite.util.IdentityProviderBuilder;
|
||||||
|
import org.keycloak.testsuite.util.RealmBuilder;
|
||||||
|
import org.openqa.selenium.By;
|
||||||
|
import org.openqa.selenium.support.ui.ExpectedConditions;
|
||||||
|
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.junit.Assume.assumeTrue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by st on 19.01.17.
|
||||||
|
*/
|
||||||
|
public class SocialLoginTest extends AbstractKeycloakTest {
|
||||||
|
|
||||||
|
public static final String SOCIAL_CONFIG = "social.config";
|
||||||
|
|
||||||
|
private static Properties config = new Properties();
|
||||||
|
|
||||||
|
@Page
|
||||||
|
public AccountUpdateProfilePage account;
|
||||||
|
|
||||||
|
@Page
|
||||||
|
public LoginPage loginPage;
|
||||||
|
|
||||||
|
@Page
|
||||||
|
public LoginUpdateProfilePage updateProfilePage;
|
||||||
|
|
||||||
|
@BeforeClass
|
||||||
|
public static void loadConfig() throws Exception {
|
||||||
|
assumeTrue(System.getProperties().containsKey(SOCIAL_CONFIG));
|
||||||
|
|
||||||
|
config.load(new FileInputStream(System.getProperty(SOCIAL_CONFIG)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||||
|
RealmRepresentation rep = RealmBuilder.create().name("social").build();
|
||||||
|
List<IdentityProviderRepresentation> idps = new LinkedList<>();
|
||||||
|
rep.setIdentityProviders(idps);
|
||||||
|
|
||||||
|
idps.add(buildIdp("google"));
|
||||||
|
idps.add(buildIdp("facebook"));
|
||||||
|
idps.add(buildIdp("github"));
|
||||||
|
idps.add(buildIdp("twitter"));
|
||||||
|
idps.add(buildIdp("linkedin"));
|
||||||
|
idps.add(buildIdp("microsoft"));
|
||||||
|
idps.add(buildIdp("stackoverflow"));
|
||||||
|
|
||||||
|
testRealms.add(rep);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void googleLogin() throws InterruptedException {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("google");
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.id("Email")));
|
||||||
|
|
||||||
|
driver.findElement(By.id("Email")).sendKeys(config.getProperty("google.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.id("next")).click();
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.id("Passwd")));
|
||||||
|
|
||||||
|
driver.findElement(By.id("Passwd")).sendKeys(config.getProperty("google.password", config.getProperty("common.password")));
|
||||||
|
driver.findElement(By.id("signIn")).click();
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.elementToBeClickable(By.id("submit_approve_access")));
|
||||||
|
|
||||||
|
driver.findElement(By.id("submit_approve_access")).click();
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("google.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("google.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("google.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void faceBookLogin() {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("facebook");
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.id("email")));
|
||||||
|
driver.findElement(By.id("email")).sendKeys(config.getProperty("facebook.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.id("pass")).sendKeys(config.getProperty("facebook.password", config.getProperty("common.password")));
|
||||||
|
|
||||||
|
driver.findElement(By.id("loginbutton")).click();
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("facebook.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("facebook.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("facebook.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void githubLogin() {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("github");
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.id("login_field")));
|
||||||
|
driver.findElement(By.id("login_field")).sendKeys(config.getProperty("github.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.id("password")).sendKeys(config.getProperty("github.password", config.getProperty("common.password")));
|
||||||
|
|
||||||
|
driver.findElement(By.name("commit")).click();
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("github.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("github.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("github.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void twitterLogin() {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("twitter");
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.id("username_or_email")));
|
||||||
|
driver.findElement(By.id("username_or_email")).sendKeys(config.getProperty("twitter.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.id("password")).sendKeys(config.getProperty("twitter.password", config.getProperty("common.password")));
|
||||||
|
|
||||||
|
driver.findElement(By.id("allow")).click();
|
||||||
|
|
||||||
|
assertTrue(updateProfilePage.isCurrent());
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("twitter.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("twitter.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals("", updateProfilePage.getEmail());
|
||||||
|
|
||||||
|
updateProfilePage.update(null, null, "keycloakey@gmail.com");
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("twitter.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("twitter.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("twitter.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void linkedinLogin() {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("linkedin");
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.id("session_key-oauth2SAuthorizeForm")));
|
||||||
|
driver.findElement(By.id("session_key-oauth2SAuthorizeForm")).sendKeys(config.getProperty("linkedin.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.id("session_password-oauth2SAuthorizeForm")).sendKeys(config.getProperty("linkedin.password", config.getProperty("common.password")));
|
||||||
|
|
||||||
|
driver.findElement(By.name("authorize")).click();
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("linkedin.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("linkedin.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("linkedin.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void microsoftLogin() {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("microsoft");
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.name("loginfmt")));
|
||||||
|
driver.findElement(By.name("loginfmt")).sendKeys(config.getProperty("microsoft.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.xpath("//input[@value='Next']")).click();
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.name("passwd")));
|
||||||
|
driver.findElement(By.name("passwd")).sendKeys(config.getProperty("microsoft.password", config.getProperty("common.password")));
|
||||||
|
driver.findElement(By.xpath("//input[@value='Sign in']")).click();
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("microsoft.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("microsoft.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("microsoft.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void stackoverflowLogin() {
|
||||||
|
account.open("social");
|
||||||
|
|
||||||
|
loginPage.clickSocial("stackoverflow");
|
||||||
|
|
||||||
|
Graphene.waitModel().until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//a[@title='log in with Stack_Exchange']")));
|
||||||
|
driver.findElement(By.xpath("//a[@title='log in with Stack_Exchange']")).click();
|
||||||
|
|
||||||
|
driver.switchTo().frame(driver.findElement(By.id("affiliate-signin-iframe")));
|
||||||
|
|
||||||
|
Graphene.waitGui().until(ExpectedConditions.visibilityOfElementLocated(By.name("email")));
|
||||||
|
driver.findElement(By.name("email")).sendKeys(config.getProperty("stackoverflow.username", config.getProperty("common.username")));
|
||||||
|
driver.findElement(By.name("password")).sendKeys(config.getProperty("stackoverflow.password", config.getProperty("common.password")));
|
||||||
|
|
||||||
|
driver.findElement(By.xpath("//input[@value='Sign In']")).click();
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("stackoverflow.profile.firstName", config.getProperty("common.profile.firstName")), updateProfilePage.getFirstName());
|
||||||
|
assertEquals(config.getProperty("stackoverflow.profile.lastName", config.getProperty("common.profile.lastName")), updateProfilePage.getLastName());
|
||||||
|
assertEquals("", updateProfilePage.getEmail());
|
||||||
|
|
||||||
|
updateProfilePage.update(null, null, "keycloakey@gmail.com");
|
||||||
|
|
||||||
|
assertEquals(config.getProperty("stackoverflow.profile.firstName", config.getProperty("common.profile.firstName")), account.getFirstName());
|
||||||
|
assertEquals(config.getProperty("stackoverflow.profile.lastName", config.getProperty("common.profile.lastName")), account.getLastName());
|
||||||
|
assertEquals(config.getProperty("stackoverflow.profile.email", config.getProperty("common.profile.email")), account.getEmail());
|
||||||
|
}
|
||||||
|
|
||||||
|
private IdentityProviderRepresentation buildIdp(String id) {
|
||||||
|
IdentityProviderRepresentation idp = IdentityProviderBuilder.create().alias(id).providerId(id).build();
|
||||||
|
idp.setEnabled(true);
|
||||||
|
idp.getConfig().put("clientId", config.getProperty(id + ".clientId"));
|
||||||
|
idp.getConfig().put("clientSecret", config.getProperty(id + ".clientSecret"));
|
||||||
|
if (id.equals("stackoverflow")) {
|
||||||
|
idp.getConfig().put("key", config.getProperty(id + ".clientKey"));
|
||||||
|
}
|
||||||
|
return idp;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -23,6 +23,7 @@ import java.util.stream.Collectors;
|
||||||
import javax.ws.rs.NotFoundException;
|
import javax.ws.rs.NotFoundException;
|
||||||
|
|
||||||
import org.jboss.arquillian.container.test.api.Deployment;
|
import org.jboss.arquillian.container.test.api.Deployment;
|
||||||
|
import org.jboss.arquillian.container.test.api.TargetsContainer;
|
||||||
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
import org.jboss.shrinkwrap.api.spec.WebArchive;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -52,6 +53,7 @@ import org.keycloak.representations.idm.authorization.PolicyRepresentation;
|
||||||
import org.keycloak.storage.UserStorageProvider;
|
import org.keycloak.storage.UserStorageProvider;
|
||||||
import org.keycloak.testsuite.AbstractKeycloakTest;
|
import org.keycloak.testsuite.AbstractKeycloakTest;
|
||||||
import org.keycloak.testsuite.Assert;
|
import org.keycloak.testsuite.Assert;
|
||||||
|
import org.keycloak.testsuite.arquillian.DeploymentTargetModifier;
|
||||||
import org.keycloak.testsuite.arquillian.migration.Migration;
|
import org.keycloak.testsuite.arquillian.migration.Migration;
|
||||||
import org.keycloak.testsuite.runonserver.RunHelpers;
|
import org.keycloak.testsuite.runonserver.RunHelpers;
|
||||||
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
|
import org.keycloak.testsuite.runonserver.RunOnServerDeployment;
|
||||||
|
@ -78,6 +80,7 @@ public class MigrationTest extends AbstractKeycloakTest {
|
||||||
private RealmResource masterRealm;
|
private RealmResource masterRealm;
|
||||||
|
|
||||||
@Deployment
|
@Deployment
|
||||||
|
@TargetsContainer(DeploymentTargetModifier.AUTH_SERVER_CURRENT)
|
||||||
public static WebArchive deploy() {
|
public static WebArchive deploy() {
|
||||||
return RunOnServerDeployment.create();
|
return RunOnServerDeployment.create();
|
||||||
}
|
}
|
||||||
|
@ -361,14 +364,27 @@ public class MigrationTest extends AbstractKeycloakTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void testOfflineTokenLogin() {
|
private void testOfflineTokenLogin() {
|
||||||
log.info("test login with old offline token");
|
if (isImportMigrationMode()) {
|
||||||
String oldOfflineToken = suiteContext.getMigrationContext().getOfflineToken();
|
log.info("Skip offline token login test in the 'import' migrationMode");
|
||||||
Assert.assertNotNull(oldOfflineToken);
|
} else {
|
||||||
|
log.info("test login with old offline token");
|
||||||
|
String oldOfflineToken = suiteContext.getMigrationContext().getOfflineToken();
|
||||||
|
Assert.assertNotNull(oldOfflineToken);
|
||||||
|
|
||||||
oauth.realm(MIGRATION);
|
oauth.realm(MIGRATION);
|
||||||
oauth.clientId("migration-test-client");
|
oauth.clientId("migration-test-client");
|
||||||
OAuthClient.AccessTokenResponse response = oauth.doRefreshTokenRequest(oldOfflineToken, "b2c07929-69e3-44c6-8d7f-76939000b3e4");
|
OAuthClient.AccessTokenResponse response = oauth.doRefreshTokenRequest(oldOfflineToken, "b2c07929-69e3-44c6-8d7f-76939000b3e4");
|
||||||
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
|
AccessToken accessToken = oauth.verifyToken(response.getAccessToken());
|
||||||
assertEquals("migration-test-user", accessToken.getPreferredUsername());
|
assertEquals("migration-test-user", accessToken.getPreferredUsername());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getMigrationMode() {
|
||||||
|
return System.getProperty("migration.mode");
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isImportMigrationMode() {
|
||||||
|
String mode = getMigrationMode();
|
||||||
|
return "import".equals(mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -465,6 +465,9 @@ public class OfflineTokenTest extends AbstractKeycloakTest {
|
||||||
// Set the time offset, so that "normal" userSession expires
|
// Set the time offset, so that "normal" userSession expires
|
||||||
setTimeOffset(86400);
|
setTimeOffset(86400);
|
||||||
|
|
||||||
|
// Remove expired sessions. This will remove "normal" userSession
|
||||||
|
testingClient.testing().removeUserSessions(appRealm.toRepresentation().getId());
|
||||||
|
|
||||||
// Refresh with the offline token
|
// Refresh with the offline token
|
||||||
tokenResponse = oauth.doRefreshTokenRequest(tokenResponse.getRefreshToken(), "secret1");
|
tokenResponse = oauth.doRefreshTokenRequest(tokenResponse.getRefreshToken(), "secret1");
|
||||||
|
|
||||||
|
|
Binary file not shown.
|
@ -24,7 +24,7 @@
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>org.keycloak.testsuite</groupId>
|
<groupId>org.keycloak.testsuite</groupId>
|
||||||
<artifactId>integration-arquillian-tests-other</artifactId>
|
<artifactId>integration-arquillian-tests-other</artifactId>
|
||||||
<version>2.5.1.Final-SNAPSHOT</version>
|
<version>3.0.0.CR1-SNAPSHOT</version>
|
||||||
<relativePath>../pom.xml</relativePath>
|
<relativePath>../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
|
@ -323,7 +323,8 @@
|
||||||
</java-opts>
|
</java-opts>
|
||||||
<execute-commands>
|
<execute-commands>
|
||||||
<scripts>
|
<scripts>
|
||||||
<script>${jbossHome}/bin/migrate-domain.cli</script>
|
<script>${jbossHome}/bin/migrate-domain-standalone.cli</script>
|
||||||
|
<script>${jbossHome}/bin/migrate-domain-clustered.cli</script>
|
||||||
</scripts>
|
</scripts>
|
||||||
</execute-commands>
|
</execute-commands>
|
||||||
</configuration>
|
</configuration>
|
||||||
|
|
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2016 Red Hat, Inc. and/or its affiliates
|
||||||
|
* and other contributors as indicated by the @author tags.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.keycloak.testsuite.federation.storage.ldap;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.ClassRule;
|
||||||
|
import org.junit.FixMethodOrder;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.RuleChain;
|
||||||
|
import org.junit.rules.TestRule;
|
||||||
|
import org.junit.runners.MethodSorters;
|
||||||
|
import org.keycloak.common.util.MultivaluedHashMap;
|
||||||
|
import org.keycloak.component.ComponentModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.LDAPConstants;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.services.managers.RealmManager;
|
||||||
|
import org.keycloak.storage.UserStorageProvider;
|
||||||
|
import org.keycloak.storage.UserStorageProviderModel;
|
||||||
|
import org.keycloak.storage.ldap.LDAPStorageProvider;
|
||||||
|
import org.keycloak.storage.ldap.LDAPStorageProviderFactory;
|
||||||
|
import org.keycloak.storage.ldap.idm.model.LDAPObject;
|
||||||
|
import org.keycloak.storage.ldap.mappers.LDAPStorageMapper;
|
||||||
|
import org.keycloak.testsuite.rule.KeycloakRule;
|
||||||
|
import org.keycloak.testsuite.rule.LDAPRule;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for special scenarios, which don't work on MSAD (eg. renaming user RDN to "sn=john2" )
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
*/
|
||||||
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
|
public class LDAPNoMSADTest {
|
||||||
|
|
||||||
|
private static final Logger log = Logger.getLogger(LDAPProvidersIntegrationTest.class);
|
||||||
|
|
||||||
|
|
||||||
|
// Skip this test on MSAD
|
||||||
|
private static LDAPRule ldapRule = new LDAPRule((Map<String, String> ldapConfig) -> {
|
||||||
|
|
||||||
|
String vendor = ldapConfig.get(LDAPConstants.VENDOR);
|
||||||
|
return (vendor.equals(LDAPConstants.VENDOR_ACTIVE_DIRECTORY));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
private static ComponentModel ldapModel = null;
|
||||||
|
|
||||||
|
|
||||||
|
private static KeycloakRule keycloakRule = new KeycloakRule(new KeycloakRule.KeycloakSetup() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void config(RealmManager manager, RealmModel adminstrationRealm, RealmModel appRealm) {
|
||||||
|
LDAPTestUtils.addLocalUser(manager.getSession(), appRealm, "marykeycloak", "mary@test.com", "password-app");
|
||||||
|
|
||||||
|
MultivaluedHashMap<String,String> ldapConfig = LDAPTestUtils.getLdapRuleConfig(ldapRule);
|
||||||
|
ldapConfig.putSingle(LDAPConstants.SYNC_REGISTRATIONS, "true");
|
||||||
|
ldapConfig.putSingle(LDAPConstants.EDIT_MODE, UserStorageProvider.EditMode.WRITABLE.toString());
|
||||||
|
UserStorageProviderModel model = new UserStorageProviderModel();
|
||||||
|
model.setLastSync(0);
|
||||||
|
model.setChangedSyncPeriod(-1);
|
||||||
|
model.setFullSyncPeriod(-1);
|
||||||
|
model.setName("test-ldap");
|
||||||
|
model.setPriority(0);
|
||||||
|
model.setProviderId(LDAPStorageProviderFactory.PROVIDER_NAME);
|
||||||
|
model.setConfig(ldapConfig);
|
||||||
|
|
||||||
|
ldapModel = appRealm.addComponentModel(model);
|
||||||
|
LDAPTestUtils.addZipCodeLDAPMapper(appRealm, ldapModel);
|
||||||
|
|
||||||
|
// Delete all LDAP users and add some new for testing
|
||||||
|
LDAPStorageProvider ldapFedProvider = LDAPTestUtils.getLdapProvider(session, ldapModel);
|
||||||
|
LDAPTestUtils.removeAllLDAPUsers(ldapFedProvider, appRealm);
|
||||||
|
|
||||||
|
LDAPObject john = LDAPTestUtils.addLDAPUser(ldapFedProvider, appRealm, "johnkeycloak", "John", "Doe", "john@email.org", null, "1234");
|
||||||
|
LDAPTestUtils.updateLDAPPassword(ldapFedProvider, john, "Password1");
|
||||||
|
|
||||||
|
LDAPObject existing = LDAPTestUtils.addLDAPUser(ldapFedProvider, appRealm, "existing", "Existing", "Foo", "existing@email.org", null, "5678");
|
||||||
|
|
||||||
|
appRealm.getClientByClientId("test-app").setDirectAccessGrantsEnabled(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
@ClassRule
|
||||||
|
public static TestRule chain = RuleChain
|
||||||
|
.outerRule(ldapRule)
|
||||||
|
.around(keycloakRule);
|
||||||
|
|
||||||
|
|
||||||
|
// KEYCLOAK-4364
|
||||||
|
@Test
|
||||||
|
public void testUpdateWithUnmappedRdnAttribute() {
|
||||||
|
KeycloakSession session = keycloakRule.startSession();
|
||||||
|
ComponentModel snMapper = null;
|
||||||
|
try {
|
||||||
|
// Create LDAP user with "sn" attribute in RDN like "sn=johnkeycloak2,ou=People,dc=domain,dc=com"
|
||||||
|
RealmModel appRealm = session.realms().getRealmByName("test");
|
||||||
|
LDAPStorageProvider ldapProvider = LDAPTestUtils.getLdapProvider(session, ldapModel);
|
||||||
|
LDAPObject john2 = LDAPTestUtils.addLDAPUser(ldapProvider, appRealm, "johnkeycloak2", "john2", "Doe2", "john2@email.org", null, "4321");
|
||||||
|
|
||||||
|
john2.setRdnAttributeName("sn");
|
||||||
|
ldapProvider.getLdapIdentityStore().update(john2);
|
||||||
|
|
||||||
|
// Remove "sn" mapper
|
||||||
|
List<ComponentModel> components = appRealm.getComponents(ldapModel.getId(), LDAPStorageMapper.class.getName());
|
||||||
|
for (ComponentModel mapper : components) {
|
||||||
|
if (mapper.getName().equals("last name")) {
|
||||||
|
snMapper = mapper;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Assert.assertNotNull(snMapper);
|
||||||
|
appRealm.removeComponent(snMapper);
|
||||||
|
} finally {
|
||||||
|
keycloakRule.stopSession(session, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Try to update johnkeycloak2 user. It shouldn't try to update DN
|
||||||
|
session = keycloakRule.startSession();
|
||||||
|
try {
|
||||||
|
RealmModel appRealm = session.realms().getRealmByName("test");
|
||||||
|
UserModel johnkeycloak2 = session.users().getUserByUsername("johnkeycloak2", appRealm);
|
||||||
|
Assert.assertNotNull(johnkeycloak2);
|
||||||
|
|
||||||
|
johnkeycloak2.setFirstName("foo2");
|
||||||
|
johnkeycloak2.setLastName("foo");
|
||||||
|
} finally {
|
||||||
|
keycloakRule.stopSession(session, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Re-create "sn" mapper back
|
||||||
|
session = keycloakRule.startSession();
|
||||||
|
try {
|
||||||
|
RealmModel appRealm = session.realms().getRealmByName("test");
|
||||||
|
snMapper.setId(null);
|
||||||
|
appRealm.addComponentModel(snMapper);
|
||||||
|
} finally {
|
||||||
|
keycloakRule.stopSession(session, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue