Merge remote-tracking branch 'upstream/master' into fixDataTable
This commit is contained in:
commit
4ca3bf530f
100 changed files with 828 additions and 652 deletions
|
@ -1103,6 +1103,7 @@ module.factory('PasswordPolicy', function() {
|
||||||
var p = {};
|
var p = {};
|
||||||
|
|
||||||
p.policyMessages = {
|
p.policyMessages = {
|
||||||
|
hashAlgorithm: "Default hashing algorithm. Default is 'pbkdf2'.",
|
||||||
hashIterations: "Number of hashing iterations. Default is 1. Recommended is 50000.",
|
hashIterations: "Number of hashing iterations. Default is 1. Recommended is 50000.",
|
||||||
length: "Minimal password length (integer type). Default value is 8.",
|
length: "Minimal password length (integer type). Default value is 8.",
|
||||||
digits: "Minimal number (integer type) of digits in password. Default value is 1.",
|
digits: "Minimal number (integer type) of digits in password. Default value is 1.",
|
||||||
|
@ -1116,6 +1117,7 @@ module.factory('PasswordPolicy', function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
p.allPolicies = [
|
p.allPolicies = [
|
||||||
|
{ name: 'hashAlgorithm', value: 'pbkdf2' },
|
||||||
{ name: 'hashIterations', value: 1 },
|
{ name: 'hashIterations', value: 1 },
|
||||||
{ name: 'length', value: 8 },
|
{ name: 'length', value: 8 },
|
||||||
{ name: 'digits', value: 1 },
|
{ name: 'digits', value: 1 },
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
package org.keycloak.hash;
|
||||||
|
|
||||||
|
import org.keycloak.models.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
*/
|
||||||
|
public class PasswordHashManager {
|
||||||
|
|
||||||
|
public static UserCredentialValueModel encode(KeycloakSession session, RealmModel realm, String rawPassword) {
|
||||||
|
PasswordPolicy passwordPolicy = realm.getPasswordPolicy();
|
||||||
|
String algorithm = passwordPolicy.getHashAlgorithm();
|
||||||
|
int iterations = passwordPolicy.getHashIterations();
|
||||||
|
if (iterations < 1) {
|
||||||
|
iterations = 1;
|
||||||
|
}
|
||||||
|
PasswordHashProvider provider = session.getProvider(PasswordHashProvider.class, algorithm);
|
||||||
|
if (provider == null) {
|
||||||
|
throw new RuntimeException("Password hash provider for algorithm " + algorithm + " not found");
|
||||||
|
}
|
||||||
|
return provider.encode(rawPassword, iterations);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean verify(KeycloakSession session, RealmModel realm, String password, UserCredentialValueModel credential) {
|
||||||
|
String algorithm = credential.getAlgorithm() != null ? credential.getAlgorithm() : realm.getPasswordPolicy().getHashAlgorithm();
|
||||||
|
PasswordHashProvider provider = session.getProvider(PasswordHashProvider.class, algorithm);
|
||||||
|
return provider.verify(password, credential);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package org.keycloak.hash;
|
||||||
|
|
||||||
|
import org.keycloak.models.UserCredentialValueModel;
|
||||||
|
import org.keycloak.provider.Provider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:me@tsudot.com">Kunal Kerkar</a>
|
||||||
|
*/
|
||||||
|
public interface PasswordHashProvider extends Provider {
|
||||||
|
|
||||||
|
UserCredentialValueModel encode(String rawPassword, int iterations);
|
||||||
|
|
||||||
|
boolean verify(String rawPassword, UserCredentialValueModel credential);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package org.keycloak.hash;
|
||||||
|
|
||||||
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:me@tsudot.com">Kunal Kerkar</a>
|
||||||
|
*/
|
||||||
|
public interface PasswordHashProviderFactory extends ProviderFactory<PasswordHashProvider> {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package org.keycloak.hash;
|
||||||
|
|
||||||
|
import org.keycloak.provider.Provider;
|
||||||
|
import org.keycloak.provider.ProviderFactory;
|
||||||
|
import org.keycloak.provider.Spi;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:me@tsudot.com">Kunal Kerkar</a>
|
||||||
|
*/
|
||||||
|
public class PasswordHashSpi implements Spi {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isInternal() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "password-hash";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends Provider> getProviderClass() {
|
||||||
|
return PasswordHashProvider.class;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Class<? extends ProviderFactory> getProviderFactoryClass() {
|
||||||
|
return PasswordHashProviderFactory.class;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
package org.keycloak.hash;
|
||||||
|
|
||||||
|
import org.keycloak.Config;
|
||||||
|
import org.keycloak.common.util.Base64;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.models.UserCredentialModel;
|
||||||
|
import org.keycloak.models.UserCredentialValueModel;
|
||||||
|
|
||||||
|
import javax.crypto.SecretKeyFactory;
|
||||||
|
import javax.crypto.spec.PBEKeySpec;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
import java.security.spec.KeySpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:me@tsudot.com">Kunal Kerkar</a>
|
||||||
|
*/
|
||||||
|
public class Pbkdf2PasswordHashProvider implements PasswordHashProviderFactory, PasswordHashProvider {
|
||||||
|
|
||||||
|
public static final String ID = "pbkdf2";
|
||||||
|
|
||||||
|
private static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1";
|
||||||
|
private static final int DERIVED_KEY_SIZE = 512;
|
||||||
|
|
||||||
|
public UserCredentialValueModel encode(String rawPassword, int iterations) {
|
||||||
|
byte[] salt = getSalt();
|
||||||
|
String encodedPassword = encode(rawPassword, iterations, salt);
|
||||||
|
|
||||||
|
UserCredentialValueModel credentials = new UserCredentialValueModel();
|
||||||
|
credentials.setAlgorithm(ID);
|
||||||
|
credentials.setType(UserCredentialModel.PASSWORD);
|
||||||
|
credentials.setSalt(salt);
|
||||||
|
credentials.setHashIterations(iterations);
|
||||||
|
credentials.setValue(encodedPassword);
|
||||||
|
return credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean verify(String rawPassword, UserCredentialValueModel credential) {
|
||||||
|
return encode(rawPassword, credential.getHashIterations(), credential.getSalt()).equals(credential.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PasswordHashProvider create(KeycloakSession session) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void init(Config.Scope config) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void postInit(KeycloakSessionFactory factory) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String encode(String rawPassword, int iterations, byte[] salt) {
|
||||||
|
KeySpec spec = new PBEKeySpec(rawPassword.toCharArray(), salt, iterations, DERIVED_KEY_SIZE);
|
||||||
|
|
||||||
|
try {
|
||||||
|
byte[] key = getSecretKeyFactory().generateSecret(spec).getEncoded();
|
||||||
|
return Base64.encodeBytes(key);
|
||||||
|
} catch (InvalidKeySpecException e) {
|
||||||
|
throw new RuntimeException("Credential could not be encoded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private byte[] getSalt() {
|
||||||
|
byte[] buffer = new byte[16];
|
||||||
|
SecureRandom secureRandom = new SecureRandom();
|
||||||
|
secureRandom.nextBytes(buffer);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SecretKeyFactory getSecretKeyFactory() {
|
||||||
|
try {
|
||||||
|
return SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("PBKDF2 algorithm not found");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,6 +21,8 @@ public interface Constants {
|
||||||
String[] BROKER_SERVICE_ROLES = {READ_TOKEN_ROLE};
|
String[] BROKER_SERVICE_ROLES = {READ_TOKEN_ROLE};
|
||||||
String OFFLINE_ACCESS_ROLE = OAuth2Constants.OFFLINE_ACCESS;
|
String OFFLINE_ACCESS_ROLE = OAuth2Constants.OFFLINE_ACCESS;
|
||||||
|
|
||||||
|
String DEFAULT_HASH_ALGORITHM = "pbkdf2";
|
||||||
|
|
||||||
// 15 minutes
|
// 15 minutes
|
||||||
int DEFAULT_ACCESS_TOKEN_LIFESPAN_FOR_IMPLICIT_FLOW_TIMEOUT = 900;
|
int DEFAULT_ACCESS_TOKEN_LIFESPAN_FOR_IMPLICIT_FLOW_TIMEOUT = 900;
|
||||||
// 30 days
|
// 30 days
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.keycloak.models;
|
package org.keycloak.models;
|
||||||
|
|
||||||
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
import org.keycloak.hash.PasswordHashManager;
|
||||||
|
import org.keycloak.hash.PasswordHashProvider;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -67,6 +68,8 @@ public class PasswordPolicy implements Serializable {
|
||||||
list.add(new SpecialChars(arg));
|
list.add(new SpecialChars(arg));
|
||||||
} else if (name.equals(NotUsername.NAME)) {
|
} else if (name.equals(NotUsername.NAME)) {
|
||||||
list.add(new NotUsername(arg));
|
list.add(new NotUsername(arg));
|
||||||
|
} else if (name.equals(HashAlgorithm.NAME)) {
|
||||||
|
list.add(new HashAlgorithm(arg));
|
||||||
} else if (name.equals(HashIterations.NAME)) {
|
} else if (name.equals(HashIterations.NAME)) {
|
||||||
list.add(new HashIterations(arg));
|
list.add(new HashIterations(arg));
|
||||||
} else if (name.equals(RegexPatterns.NAME)) {
|
} else if (name.equals(RegexPatterns.NAME)) {
|
||||||
|
@ -83,6 +86,18 @@ public class PasswordPolicy implements Serializable {
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getHashAlgorithm() {
|
||||||
|
if (policies == null)
|
||||||
|
return Constants.DEFAULT_HASH_ALGORITHM;
|
||||||
|
for (Policy p : policies) {
|
||||||
|
if (p instanceof HashAlgorithm) {
|
||||||
|
return ((HashAlgorithm) p).algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return Constants.DEFAULT_HASH_ALGORITHM;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return -1 if no hash iterations setting
|
* @return -1 if no hash iterations setting
|
||||||
|
@ -131,9 +146,9 @@ public class PasswordPolicy implements Serializable {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Error validate(UserModel user, String password) {
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
for (Policy p : policies) {
|
for (Policy p : policies) {
|
||||||
Error error = p.validate(user, password);
|
Error error = p.validate(session, user, password);
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -141,9 +156,9 @@ public class PasswordPolicy implements Serializable {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Error validate(String user, String password) {
|
public Error validate(KeycloakSession session, String user, String password) {
|
||||||
for (Policy p : policies) {
|
for (Policy p : policies) {
|
||||||
Error error = p.validate(user, password);
|
Error error = p.validate(session, user, password);
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -152,8 +167,8 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static interface Policy extends Serializable {
|
private static interface Policy extends Serializable {
|
||||||
public Error validate(UserModel user, String password);
|
public Error validate(KeycloakSession session, UserModel user, String password);
|
||||||
public Error validate(String user, String password);
|
public Error validate(KeycloakSession session, String user, String password);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Error {
|
public static class Error {
|
||||||
|
@ -174,6 +189,25 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class HashAlgorithm implements Policy {
|
||||||
|
private static final String NAME = "hashAlgorithm";
|
||||||
|
private String algorithm;
|
||||||
|
|
||||||
|
public HashAlgorithm(String arg) {
|
||||||
|
algorithm = stringArg(NAME, Constants.DEFAULT_HASH_ALGORITHM, arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Error validate(KeycloakSession session, String user, String password) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static class HashIterations implements Policy {
|
private static class HashIterations implements Policy {
|
||||||
private static final String NAME = "hashIterations";
|
private static final String NAME = "hashIterations";
|
||||||
private int iterations;
|
private int iterations;
|
||||||
|
@ -183,12 +217,12 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(String user, String password) {
|
public Error validate(KeycloakSession session, String user, String password) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(UserModel user, String password) {
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -200,13 +234,13 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(String username, String password) {
|
public Error validate(KeycloakSession session, String username, String password) {
|
||||||
return username.equals(password) ? new Error(INVALID_PASSWORD_NOT_USERNAME) : null;
|
return username.equals(password) ? new Error(INVALID_PASSWORD_NOT_USERNAME) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(UserModel user, String password) {
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
return validate(user.getUsername(), password);
|
return validate(session, user.getUsername(), password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,13 +255,13 @@ public class PasswordPolicy implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(String username, String password) {
|
public Error validate(KeycloakSession session, String username, String password) {
|
||||||
return password.length() < min ? new Error(INVALID_PASSWORD_MIN_LENGTH_MESSAGE, min) : null;
|
return password.length() < min ? new Error(INVALID_PASSWORD_MIN_LENGTH_MESSAGE, min) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(UserModel user, String password) {
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
return validate(user.getUsername(), password);
|
return validate(session, user.getUsername(), password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -242,7 +276,7 @@ public class PasswordPolicy implements Serializable {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(String username, String password) {
|
public Error validate(KeycloakSession session, String username, String password) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (char c : password.toCharArray()) {
|
for (char c : password.toCharArray()) {
|
||||||
if (Character.isDigit(c)) {
|
if (Character.isDigit(c)) {
|
||||||
|
@ -253,8 +287,8 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(UserModel user, String password) {
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
return validate(user.getUsername(), password);
|
return validate(session, user.getUsername(), password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +302,7 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(String username, String password) {
|
public Error validate(KeycloakSession session, String username, String password) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (char c : password.toCharArray()) {
|
for (char c : password.toCharArray()) {
|
||||||
if (Character.isLowerCase(c)) {
|
if (Character.isLowerCase(c)) {
|
||||||
|
@ -279,8 +313,8 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(UserModel user, String password) {
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
return validate(user.getUsername(), password);
|
return validate(session, user.getUsername(), password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -293,7 +327,7 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(String username, String password) {
|
public Error validate(KeycloakSession session, String username, String password) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (char c : password.toCharArray()) {
|
for (char c : password.toCharArray()) {
|
||||||
if (Character.isUpperCase(c)) {
|
if (Character.isUpperCase(c)) {
|
||||||
|
@ -304,8 +338,8 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(UserModel user, String password) {
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
return validate(user.getUsername(), password);
|
return validate(session, user.getUsername(), password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,7 +353,7 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(String username, String password) {
|
public Error validate(KeycloakSession session, String username, String password) {
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (char c : password.toCharArray()) {
|
for (char c : password.toCharArray()) {
|
||||||
if (!Character.isLetterOrDigit(c)) {
|
if (!Character.isLetterOrDigit(c)) {
|
||||||
|
@ -330,8 +364,8 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(UserModel user, String password) {
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
return validate(user.getUsername(), password);
|
return validate(session, user.getUsername(), password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,7 +379,7 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(String username, String password) {
|
public Error validate(KeycloakSession session, String username, String password) {
|
||||||
Pattern pattern = Pattern.compile(regexPattern);
|
Pattern pattern = Pattern.compile(regexPattern);
|
||||||
Matcher matcher = pattern.matcher(password);
|
Matcher matcher = pattern.matcher(password);
|
||||||
if (!matcher.matches()) {
|
if (!matcher.matches()) {
|
||||||
|
@ -355,8 +389,8 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(UserModel user, String password) {
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
return validate(user.getUsername(), password);
|
return validate(session, user.getUsername(), password);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -370,18 +404,19 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(String user, String password) {
|
public Error validate(KeycloakSession session, String user, String password) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(UserModel user, String password) {
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
|
|
||||||
if (passwordHistoryPolicyValue != -1) {
|
if (passwordHistoryPolicyValue != -1) {
|
||||||
|
|
||||||
UserCredentialValueModel cred = getCredentialValueModel(user, UserCredentialModel.PASSWORD);
|
UserCredentialValueModel cred = getCredentialValueModel(user, UserCredentialModel.PASSWORD);
|
||||||
if (cred != null) {
|
if (cred != null) {
|
||||||
if(new Pbkdf2PasswordEncoder(cred.getSalt()).verify(password, cred.getValue(), cred.getHashIterations())) {
|
PasswordHashProvider hashProvider = session.getProvider(PasswordHashProvider.class, cred.getAlgorithm());
|
||||||
|
if(hashProvider.verify(password, cred)) {
|
||||||
return new Error(INVALID_PASSWORD_HISTORY, passwordHistoryPolicyValue);
|
return new Error(INVALID_PASSWORD_HISTORY, passwordHistoryPolicyValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -389,7 +424,8 @@ public class PasswordPolicy implements Serializable {
|
||||||
List<UserCredentialValueModel> passwordExpiredCredentials = getCredentialValueModels(user, passwordHistoryPolicyValue - 1,
|
List<UserCredentialValueModel> passwordExpiredCredentials = getCredentialValueModels(user, passwordHistoryPolicyValue - 1,
|
||||||
UserCredentialModel.PASSWORD_HISTORY);
|
UserCredentialModel.PASSWORD_HISTORY);
|
||||||
for (UserCredentialValueModel credential : passwordExpiredCredentials) {
|
for (UserCredentialValueModel credential : passwordExpiredCredentials) {
|
||||||
if (new Pbkdf2PasswordEncoder(credential.getSalt()).verify(password, credential.getValue(), credential.getHashIterations())) {
|
PasswordHashProvider hashProvider = session.getProvider(PasswordHashProvider.class, cred.getAlgorithm());
|
||||||
|
if (hashProvider.verify(password, credential)) {
|
||||||
return new Error(INVALID_PASSWORD_HISTORY, passwordHistoryPolicyValue);
|
return new Error(INVALID_PASSWORD_HISTORY, passwordHistoryPolicyValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -444,12 +480,12 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(String username, String password) {
|
public Error validate(KeycloakSession session, String username, String password) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Error validate(UserModel user, String password) {
|
public Error validate(KeycloakSession session, UserModel user, String password) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,6 +498,14 @@ public class PasswordPolicy implements Serializable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String stringArg(String policy, String defaultValue, String arg) {
|
||||||
|
if (arg == null) {
|
||||||
|
return defaultValue;
|
||||||
|
} else {
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return policyString;
|
return policyString;
|
||||||
|
|
|
@ -21,6 +21,7 @@ public class UserCredentialModel {
|
||||||
protected String type;
|
protected String type;
|
||||||
protected String value;
|
protected String value;
|
||||||
protected String device;
|
protected String device;
|
||||||
|
protected String algorithm;
|
||||||
|
|
||||||
public UserCredentialModel() {
|
public UserCredentialModel() {
|
||||||
}
|
}
|
||||||
|
@ -107,4 +108,12 @@ public class UserCredentialModel {
|
||||||
public void setDevice(String device) {
|
public void setDevice(String device) {
|
||||||
this.device = device;
|
this.device = device;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getAlgorithm() {
|
||||||
|
return algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAlgorithm(String algorithm) {
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -395,7 +395,7 @@ public class UserFederationManager implements UserProvider {
|
||||||
public void updateCredential(RealmModel realm, UserModel user, UserCredentialModel credential) {
|
public void updateCredential(RealmModel realm, UserModel user, UserCredentialModel credential) {
|
||||||
if (credential.getType().equals(UserCredentialModel.PASSWORD)) {
|
if (credential.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||||
if (realm.getPasswordPolicy() != null) {
|
if (realm.getPasswordPolicy() != null) {
|
||||||
PasswordPolicy.Error error = realm.getPasswordPolicy().validate(user, credential.getValue());
|
PasswordPolicy.Error error = realm.getPasswordPolicy().validate(session, user, credential.getValue());
|
||||||
if (error != null) throw new ModelException(error.getMessage(), error.getParameters());
|
if (error != null) throw new ModelException(error.getMessage(), error.getParameters());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -403,7 +403,7 @@ public class UserFederationManager implements UserProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
||||||
UserFederationProvider link = getFederationLink(realm, user);
|
UserFederationProvider link = getFederationLink(realm, user);
|
||||||
if (link != null) {
|
if (link != null) {
|
||||||
validateUser(realm, user);
|
validateUser(realm, user);
|
||||||
|
@ -421,10 +421,10 @@ public class UserFederationManager implements UserProvider {
|
||||||
if (!link.validCredentials(realm, user, fedCreds)) {
|
if (!link.validCredentials(realm, user, fedCreds)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return session.userStorage().validCredentials(realm, user, localCreds);
|
return session.userStorage().validCredentials(session, realm, user, localCreds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return session.userStorage().validCredentials(realm, user, input);
|
return session.userStorage().validCredentials(session, realm, user, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -466,12 +466,12 @@ public class UserFederationManager implements UserProvider {
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
|
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel... input) {
|
||||||
return validCredentials(realm, user, Arrays.asList(input));
|
return validCredentials(session, realm, user, Arrays.asList(input));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
|
public CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input) {
|
||||||
List<UserFederationProviderModel> fedProviderModels = realm.getUserFederationProviders();
|
List<UserFederationProviderModel> fedProviderModels = realm.getUserFederationProviders();
|
||||||
List<UserFederationProvider> fedProviders = new ArrayList<UserFederationProvider>();
|
List<UserFederationProvider> fedProviders = new ArrayList<UserFederationProvider>();
|
||||||
for (UserFederationProviderModel fedProviderModel : fedProviderModels) {
|
for (UserFederationProviderModel fedProviderModel : fedProviderModels) {
|
||||||
|
|
|
@ -59,9 +59,9 @@ public interface UserProvider extends Provider {
|
||||||
void preRemove(RealmModel realm, ClientModel client);
|
void preRemove(RealmModel realm, ClientModel client);
|
||||||
void preRemove(ClientModel realm, ProtocolMapperModel protocolMapper);
|
void preRemove(ClientModel realm, ProtocolMapperModel protocolMapper);
|
||||||
|
|
||||||
boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input);
|
boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input);
|
||||||
boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input);
|
boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel... input);
|
||||||
CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input);
|
CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input);
|
||||||
|
|
||||||
void close();
|
void close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
package org.keycloak.models.utils;
|
package org.keycloak.models.utils;
|
||||||
|
|
||||||
|
import org.keycloak.hash.PasswordHashManager;
|
||||||
import org.keycloak.jose.jws.JWSInput;
|
import org.keycloak.jose.jws.JWSInput;
|
||||||
import org.keycloak.jose.jws.JWSInputException;
|
import org.keycloak.jose.jws.JWSInputException;
|
||||||
import org.keycloak.jose.jws.crypto.RSAProvider;
|
import org.keycloak.jose.jws.crypto.RSAProvider;
|
||||||
|
import org.keycloak.models.Constants;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.OTPPolicy;
|
import org.keycloak.models.OTPPolicy;
|
||||||
import org.keycloak.models.PasswordPolicy;
|
import org.keycloak.models.PasswordPolicy;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
|
@ -11,8 +14,8 @@ import org.keycloak.models.UserCredentialValueModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.representations.PasswordToken;
|
import org.keycloak.representations.PasswordToken;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
|
import org.keycloak.hash.PasswordHashProvider;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -38,7 +41,7 @@ public class CredentialValidation {
|
||||||
* @param password
|
* @param password
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static boolean validPassword(RealmModel realm, UserModel user, String password) {
|
public static boolean validPassword(KeycloakSession session, RealmModel realm, UserModel user, String password) {
|
||||||
UserCredentialValueModel passwordCred = null;
|
UserCredentialValueModel passwordCred = null;
|
||||||
for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
|
for (UserCredentialValueModel cred : user.getCredentialsDirectly()) {
|
||||||
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||||
|
@ -47,25 +50,23 @@ public class CredentialValidation {
|
||||||
}
|
}
|
||||||
if (passwordCred == null) return false;
|
if (passwordCred == null) return false;
|
||||||
|
|
||||||
return validateHashedCredential(realm, user, password, passwordCred);
|
return validateHashedCredential(session, realm, user, password, passwordCred);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean validateHashedCredential(RealmModel realm, UserModel user, String unhashedCredValue, UserCredentialValueModel credential) {
|
|
||||||
|
public static boolean validateHashedCredential(KeycloakSession session, RealmModel realm, UserModel user, String unhashedCredValue, UserCredentialValueModel credential) {
|
||||||
if(unhashedCredValue == null){
|
if(unhashedCredValue == null){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean validated = new Pbkdf2PasswordEncoder(credential.getSalt()).verify(unhashedCredValue, credential.getValue(), credential.getHashIterations());
|
boolean validated = PasswordHashManager.verify(session, realm, unhashedCredValue, credential);
|
||||||
|
|
||||||
if (validated) {
|
if (validated) {
|
||||||
int iterations = hashIterations(realm);
|
int iterations = hashIterations(realm);
|
||||||
if (iterations > -1 && iterations != credential.getHashIterations()) {
|
if (iterations > -1 && iterations != credential.getHashIterations()) {
|
||||||
UserCredentialValueModel newCred = new UserCredentialValueModel();
|
|
||||||
newCred.setType(credential.getType());
|
UserCredentialValueModel newCred = PasswordHashManager.encode(session, realm, unhashedCredValue);
|
||||||
newCred.setDevice(credential.getDevice());
|
|
||||||
newCred.setSalt(credential.getSalt());
|
|
||||||
newCred.setHashIterations(iterations);
|
|
||||||
newCred.setValue(new Pbkdf2PasswordEncoder(newCred.getSalt()).encode(unhashedCredValue, iterations));
|
|
||||||
user.updateCredentialDirectly(newCred);
|
user.updateCredentialDirectly(newCred);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,9 +158,9 @@ public class CredentialValidation {
|
||||||
* @param credentials
|
* @param credentials
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> credentials) {
|
public static boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> credentials) {
|
||||||
for (UserCredentialModel credential : credentials) {
|
for (UserCredentialModel credential : credentials) {
|
||||||
if (!validCredential(realm, user, credential)) return false;
|
if (!validCredential(session, realm, user, credential)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -172,16 +173,16 @@ public class CredentialValidation {
|
||||||
* @param credentials
|
* @param credentials
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public static boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... credentials) {
|
public static boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel... credentials) {
|
||||||
for (UserCredentialModel credential : credentials) {
|
for (UserCredentialModel credential : credentials) {
|
||||||
if (!validCredential(realm, user, credential)) return false;
|
if (!validCredential(session, realm, user, credential)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean validCredential(RealmModel realm, UserModel user, UserCredentialModel credential) {
|
private static boolean validCredential(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel credential) {
|
||||||
if (credential.getType().equals(UserCredentialModel.PASSWORD)) {
|
if (credential.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||||
if (!validPassword(realm, user, credential.getValue())) {
|
if (!validPassword(session, realm, user, credential.getValue())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else if (credential.getType().equals(UserCredentialModel.PASSWORD_TOKEN)) {
|
} else if (credential.getType().equals(UserCredentialModel.PASSWORD_TOKEN)) {
|
||||||
|
|
|
@ -1,106 +0,0 @@
|
||||||
package org.keycloak.models.utils;
|
|
||||||
|
|
||||||
import org.keycloak.common.util.Base64;
|
|
||||||
|
|
||||||
import javax.crypto.SecretKeyFactory;
|
|
||||||
import javax.crypto.spec.PBEKeySpec;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
import java.security.SecureRandom;
|
|
||||||
import java.security.spec.InvalidKeySpecException;
|
|
||||||
import java.security.spec.KeySpec;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* Encoder that uses PBKDF2 function to cryptographically derive passwords.
|
|
||||||
* </p>
|
|
||||||
* <p>Passwords are returned with a Base64 encoding.</p>
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:bruno@abstractj.org">Bruno Oliveira</a>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class Pbkdf2PasswordEncoder {
|
|
||||||
|
|
||||||
public static final String PBKDF2_ALGORITHM = "PBKDF2WithHmacSHA1";
|
|
||||||
public static final String RNG_ALGORITHM = "SHA1PRNG";
|
|
||||||
|
|
||||||
private static final int DERIVED_KEY_SIZE = 512;
|
|
||||||
private static final int ITERATIONS = 1;
|
|
||||||
|
|
||||||
private final int iterations;
|
|
||||||
private byte[] salt;
|
|
||||||
|
|
||||||
public Pbkdf2PasswordEncoder(byte[] salt, int iterations) {
|
|
||||||
this.salt = salt;
|
|
||||||
this.iterations = iterations;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Pbkdf2PasswordEncoder(byte[] salt) {
|
|
||||||
this(salt, ITERATIONS);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode the raw password provided
|
|
||||||
* @param rawPassword The password used as a master key to derive into a session key
|
|
||||||
* @return encoded password in Base64
|
|
||||||
*/
|
|
||||||
public String encode(String rawPassword, int iterations) {
|
|
||||||
|
|
||||||
String encodedPassword;
|
|
||||||
|
|
||||||
KeySpec spec = new PBEKeySpec(rawPassword.toCharArray(), salt, iterations, DERIVED_KEY_SIZE);
|
|
||||||
|
|
||||||
try {
|
|
||||||
byte[] key = getSecretKeyFactory().generateSecret(spec).getEncoded();
|
|
||||||
encodedPassword = Base64.encodeBytes(key);
|
|
||||||
} catch (InvalidKeySpecException e) {
|
|
||||||
throw new RuntimeException("Credential could not be encoded");
|
|
||||||
}
|
|
||||||
|
|
||||||
return encodedPassword;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String encode(String rawPassword) {
|
|
||||||
return encode(rawPassword, iterations);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode the password provided and compare with the hash stored into the database
|
|
||||||
* @param rawPassword The password provided
|
|
||||||
* @param encodedPassword Encoded hash stored into the database
|
|
||||||
* @return true if the password is valid, otherwise false for invalid credentials
|
|
||||||
*/
|
|
||||||
public boolean verify(String rawPassword, String encodedPassword) {
|
|
||||||
return encode(rawPassword).equals(encodedPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode the password provided and compare with the hash stored into the database
|
|
||||||
* @param rawPassword The password provided
|
|
||||||
* @param encodedPassword Encoded hash stored into the database
|
|
||||||
* @return true if the password is valid, otherwise false for invalid credentials
|
|
||||||
*/
|
|
||||||
public boolean verify(String rawPassword, String encodedPassword, int iterations) {
|
|
||||||
return encode(rawPassword, iterations).equals(encodedPassword);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate a salt for each password
|
|
||||||
* @return cryptographically strong random number
|
|
||||||
*/
|
|
||||||
public static byte[] getSalt() {
|
|
||||||
byte[] buffer = new byte[16];
|
|
||||||
|
|
||||||
SecureRandom secureRandom = new SecureRandom();
|
|
||||||
secureRandom.nextBytes(buffer);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static SecretKeyFactory getSecretKeyFactory() {
|
|
||||||
try {
|
|
||||||
return SecretKeyFactory.getInstance(PBKDF2_ALGORITHM);
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException("PBKDF2 algorithm not found");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1 @@
|
||||||
|
org.keycloak.hash.Pbkdf2PasswordHashProvider
|
|
@ -5,3 +5,4 @@ org.keycloak.models.UserSessionSpi
|
||||||
org.keycloak.models.UserSpi
|
org.keycloak.models.UserSpi
|
||||||
org.keycloak.models.session.UserSessionPersisterSpi
|
org.keycloak.models.session.UserSessionPersisterSpi
|
||||||
org.keycloak.migration.MigrationSpi
|
org.keycloak.migration.MigrationSpi
|
||||||
|
org.keycloak.hash.PasswordHashSpi
|
||||||
|
|
|
@ -15,73 +15,73 @@ public class PasswordPolicyTest {
|
||||||
@Test
|
@Test
|
||||||
public void testLength() {
|
public void testLength() {
|
||||||
PasswordPolicy policy = new PasswordPolicy("length");
|
PasswordPolicy policy = new PasswordPolicy("length");
|
||||||
Assert.assertEquals("invalidPasswordMinLengthMessage", policy.validate("jdoe", "1234567").getMessage());
|
Assert.assertEquals("invalidPasswordMinLengthMessage", policy.validate(null, "jdoe", "1234567").getMessage());
|
||||||
Assert.assertArrayEquals(new Object[]{8}, policy.validate("jdoe", "1234567").getParameters());
|
Assert.assertArrayEquals(new Object[]{8}, policy.validate(null, "jdoe", "1234567").getParameters());
|
||||||
Assert.assertNull(policy.validate("jdoe", "12345678"));
|
Assert.assertNull(policy.validate(null, "jdoe", "12345678"));
|
||||||
|
|
||||||
policy = new PasswordPolicy("length(4)");
|
policy = new PasswordPolicy("length(4)");
|
||||||
Assert.assertEquals("invalidPasswordMinLengthMessage", policy.validate("jdoe", "123").getMessage());
|
Assert.assertEquals("invalidPasswordMinLengthMessage", policy.validate(null, "jdoe", "123").getMessage());
|
||||||
Assert.assertArrayEquals(new Object[]{4}, policy.validate("jdoe", "123").getParameters());
|
Assert.assertArrayEquals(new Object[]{4}, policy.validate(null, "jdoe", "123").getParameters());
|
||||||
Assert.assertNull(policy.validate("jdoe", "1234"));
|
Assert.assertNull(policy.validate(null, "jdoe", "1234"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDigits() {
|
public void testDigits() {
|
||||||
PasswordPolicy policy = new PasswordPolicy("digits");
|
PasswordPolicy policy = new PasswordPolicy("digits");
|
||||||
Assert.assertEquals("invalidPasswordMinDigitsMessage", policy.validate("jdoe", "abcd").getMessage());
|
Assert.assertEquals("invalidPasswordMinDigitsMessage", policy.validate(null, "jdoe", "abcd").getMessage());
|
||||||
Assert.assertArrayEquals(new Object[]{1}, policy.validate("jdoe", "abcd").getParameters());
|
Assert.assertArrayEquals(new Object[]{1}, policy.validate(null, "jdoe", "abcd").getParameters());
|
||||||
Assert.assertNull(policy.validate("jdoe", "abcd1"));
|
Assert.assertNull(policy.validate(null, "jdoe", "abcd1"));
|
||||||
|
|
||||||
policy = new PasswordPolicy("digits(2)");
|
policy = new PasswordPolicy("digits(2)");
|
||||||
Assert.assertEquals("invalidPasswordMinDigitsMessage", policy.validate("jdoe", "abcd1").getMessage());
|
Assert.assertEquals("invalidPasswordMinDigitsMessage", policy.validate(null, "jdoe", "abcd1").getMessage());
|
||||||
Assert.assertArrayEquals(new Object[]{2}, policy.validate("jdoe", "abcd1").getParameters());
|
Assert.assertArrayEquals(new Object[]{2}, policy.validate(null, "jdoe", "abcd1").getParameters());
|
||||||
Assert.assertNull(policy.validate("jdoe", "abcd12"));
|
Assert.assertNull(policy.validate(null, "jdoe", "abcd12"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLowerCase() {
|
public void testLowerCase() {
|
||||||
PasswordPolicy policy = new PasswordPolicy("lowerCase");
|
PasswordPolicy policy = new PasswordPolicy("lowerCase");
|
||||||
Assert.assertEquals("invalidPasswordMinLowerCaseCharsMessage", policy.validate("jdoe", "ABCD1234").getMessage());
|
Assert.assertEquals("invalidPasswordMinLowerCaseCharsMessage", policy.validate(null, "jdoe", "ABCD1234").getMessage());
|
||||||
Assert.assertArrayEquals(new Object[]{1}, policy.validate("jdoe", "ABCD1234").getParameters());
|
Assert.assertArrayEquals(new Object[]{1}, policy.validate(null, "jdoe", "ABCD1234").getParameters());
|
||||||
Assert.assertNull(policy.validate("jdoe", "ABcD1234"));
|
Assert.assertNull(policy.validate(null, "jdoe", "ABcD1234"));
|
||||||
|
|
||||||
policy = new PasswordPolicy("lowerCase(2)");
|
policy = new PasswordPolicy("lowerCase(2)");
|
||||||
Assert.assertEquals("invalidPasswordMinLowerCaseCharsMessage", policy.validate("jdoe", "ABcD1234").getMessage());
|
Assert.assertEquals("invalidPasswordMinLowerCaseCharsMessage", policy.validate(null, "jdoe", "ABcD1234").getMessage());
|
||||||
Assert.assertArrayEquals(new Object[]{2}, policy.validate("jdoe", "ABcD1234").getParameters());
|
Assert.assertArrayEquals(new Object[]{2}, policy.validate(null, "jdoe", "ABcD1234").getParameters());
|
||||||
Assert.assertNull(policy.validate("jdoe", "aBcD1234"));
|
Assert.assertNull(policy.validate(null, "jdoe", "aBcD1234"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUpperCase() {
|
public void testUpperCase() {
|
||||||
PasswordPolicy policy = new PasswordPolicy("upperCase");
|
PasswordPolicy policy = new PasswordPolicy("upperCase");
|
||||||
Assert.assertEquals("invalidPasswordMinUpperCaseCharsMessage", policy.validate("jdoe", "abcd1234").getMessage());
|
Assert.assertEquals("invalidPasswordMinUpperCaseCharsMessage", policy.validate(null, "jdoe", "abcd1234").getMessage());
|
||||||
Assert.assertArrayEquals(new Object[]{1}, policy.validate("jdoe", "abcd1234").getParameters());
|
Assert.assertArrayEquals(new Object[]{1}, policy.validate(null, "jdoe", "abcd1234").getParameters());
|
||||||
Assert.assertNull(policy.validate("jdoe", "abCd1234"));
|
Assert.assertNull(policy.validate(null, "jdoe", "abCd1234"));
|
||||||
|
|
||||||
policy = new PasswordPolicy("upperCase(2)");
|
policy = new PasswordPolicy("upperCase(2)");
|
||||||
Assert.assertEquals("invalidPasswordMinUpperCaseCharsMessage", policy.validate("jdoe", "abCd1234").getMessage());
|
Assert.assertEquals("invalidPasswordMinUpperCaseCharsMessage", policy.validate(null, "jdoe", "abCd1234").getMessage());
|
||||||
Assert.assertArrayEquals(new Object[]{2}, policy.validate("jdoe", "abCd1234").getParameters());
|
Assert.assertArrayEquals(new Object[]{2}, policy.validate(null, "jdoe", "abCd1234").getParameters());
|
||||||
Assert.assertNull(policy.validate("jdoe", "AbCd1234"));
|
Assert.assertNull(policy.validate(null, "jdoe", "AbCd1234"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSpecialChars() {
|
public void testSpecialChars() {
|
||||||
PasswordPolicy policy = new PasswordPolicy("specialChars");
|
PasswordPolicy policy = new PasswordPolicy("specialChars");
|
||||||
Assert.assertEquals("invalidPasswordMinSpecialCharsMessage", policy.validate("jdoe", "abcd1234").getMessage());
|
Assert.assertEquals("invalidPasswordMinSpecialCharsMessage", policy.validate(null, "jdoe", "abcd1234").getMessage());
|
||||||
Assert.assertArrayEquals(new Object[]{1}, policy.validate("jdoe", "abcd1234").getParameters());
|
Assert.assertArrayEquals(new Object[]{1}, policy.validate(null, "jdoe", "abcd1234").getParameters());
|
||||||
Assert.assertNull(policy.validate("jdoe", "ab&d1234"));
|
Assert.assertNull(policy.validate(null, "jdoe", "ab&d1234"));
|
||||||
|
|
||||||
policy = new PasswordPolicy("specialChars(2)");
|
policy = new PasswordPolicy("specialChars(2)");
|
||||||
Assert.assertEquals("invalidPasswordMinSpecialCharsMessage", policy.validate("jdoe", "ab&d1234").getMessage());
|
Assert.assertEquals("invalidPasswordMinSpecialCharsMessage", policy.validate(null, "jdoe", "ab&d1234").getMessage());
|
||||||
Assert.assertArrayEquals(new Object[]{2}, policy.validate("jdoe", "ab&d1234").getParameters());
|
Assert.assertArrayEquals(new Object[]{2}, policy.validate(null, "jdoe", "ab&d1234").getParameters());
|
||||||
Assert.assertNull(policy.validate("jdoe", "ab&d-234"));
|
Assert.assertNull(policy.validate(null, "jdoe", "ab&d-234"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNotUsername() {
|
public void testNotUsername() {
|
||||||
PasswordPolicy policy = new PasswordPolicy("notUsername");
|
PasswordPolicy policy = new PasswordPolicy("notUsername");
|
||||||
Assert.assertEquals("invalidPasswordNotUsernameMessage", policy.validate("jdoe", "jdoe").getMessage());
|
Assert.assertEquals("invalidPasswordNotUsernameMessage", policy.validate(null, "jdoe", "jdoe").getMessage());
|
||||||
Assert.assertNull(policy.validate("jdoe", "ab&d1234"));
|
Assert.assertNull(policy.validate(null, "jdoe", "ab&d1234"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -119,33 +119,33 @@ public class PasswordPolicyTest {
|
||||||
|
|
||||||
//Fails to match one of the regex pattern
|
//Fails to match one of the regex pattern
|
||||||
policy = new PasswordPolicy("regexPattern(jdoe) and regexPattern(j*d)");
|
policy = new PasswordPolicy("regexPattern(jdoe) and regexPattern(j*d)");
|
||||||
Assert.assertEquals("invalidPasswordRegexPatternMessage", policy.validate("jdoe", "jdoe").getMessage());
|
Assert.assertEquals("invalidPasswordRegexPatternMessage", policy.validate(null, "jdoe", "jdoe").getMessage());
|
||||||
|
|
||||||
////Fails to match all of the regex patterns
|
////Fails to match all of the regex patterns
|
||||||
policy = new PasswordPolicy("regexPattern(j*p) and regexPattern(j*d) and regexPattern(adoe)");
|
policy = new PasswordPolicy("regexPattern(j*p) and regexPattern(j*d) and regexPattern(adoe)");
|
||||||
Assert.assertEquals("invalidPasswordRegexPatternMessage", policy.validate("jdoe", "jdoe").getMessage());
|
Assert.assertEquals("invalidPasswordRegexPatternMessage", policy.validate(null, "jdoe", "jdoe").getMessage());
|
||||||
|
|
||||||
policy = new PasswordPolicy("regexPattern([a-z][a-z][a-z][a-z][0-9])");
|
policy = new PasswordPolicy("regexPattern([a-z][a-z][a-z][a-z][0-9])");
|
||||||
Assert.assertEquals("invalidPasswordRegexPatternMessage", policy.validate("jdoe", "jdoe").getMessage());
|
Assert.assertEquals("invalidPasswordRegexPatternMessage", policy.validate(null, "jdoe", "jdoe").getMessage());
|
||||||
|
|
||||||
policy = new PasswordPolicy("regexPattern(jdoe)");
|
policy = new PasswordPolicy("regexPattern(jdoe)");
|
||||||
Assert.assertNull(policy.validate("jdoe", "jdoe"));
|
Assert.assertNull(policy.validate(null, "jdoe", "jdoe"));
|
||||||
|
|
||||||
policy = new PasswordPolicy("regexPattern([a-z][a-z][a-z][a-z][0-9])");
|
policy = new PasswordPolicy("regexPattern([a-z][a-z][a-z][a-z][0-9])");
|
||||||
Assert.assertNull(policy.validate("jdoe", "jdoe0"));
|
Assert.assertNull(policy.validate(null, "jdoe", "jdoe0"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testComplex() {
|
public void testComplex() {
|
||||||
PasswordPolicy policy = new PasswordPolicy("length(8) and digits(2) and lowerCase(2) and upperCase(2) and specialChars(2) and notUsername()");
|
PasswordPolicy policy = new PasswordPolicy("length(8) and digits(2) and lowerCase(2) and upperCase(2) and specialChars(2) and notUsername()");
|
||||||
Assert.assertNotNull(policy.validate("jdoe", "12aaBB&"));
|
Assert.assertNotNull(policy.validate(null, "jdoe", "12aaBB&"));
|
||||||
Assert.assertNotNull(policy.validate("jdoe", "aaaaBB&-"));
|
Assert.assertNotNull(policy.validate(null, "jdoe", "aaaaBB&-"));
|
||||||
Assert.assertNotNull(policy.validate("jdoe", "12AABB&-"));
|
Assert.assertNotNull(policy.validate(null, "jdoe", "12AABB&-"));
|
||||||
Assert.assertNotNull(policy.validate("jdoe", "12aabb&-"));
|
Assert.assertNotNull(policy.validate(null, "jdoe", "12aabb&-"));
|
||||||
Assert.assertNotNull(policy.validate("jdoe", "12aaBBcc"));
|
Assert.assertNotNull(policy.validate(null, "jdoe", "12aaBBcc"));
|
||||||
Assert.assertNotNull(policy.validate("12aaBB&-", "12aaBB&-"));
|
Assert.assertNotNull(policy.validate(null, "12aaBB&-", "12aaBB&-"));
|
||||||
|
|
||||||
Assert.assertNull(policy.validate("jdoe", "12aaBB&-"));
|
Assert.assertNull(policy.validate(null, "jdoe", "12aaBB&-"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -299,18 +299,18 @@ public class DefaultCacheUserProvider implements CacheUserProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
||||||
return getDelegate().validCredentials(realm, user, input);
|
return getDelegate().validCredentials(session, realm, user, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
|
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel... input) {
|
||||||
return getDelegate().validCredentials(realm, user, input);
|
return getDelegate().validCredentials(session, realm, user, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
|
public CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input) {
|
||||||
return getDelegate().validCredentials(realm, input);
|
return getDelegate().validCredentials(session, realm, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -4,6 +4,7 @@ import org.keycloak.common.util.MultivaluedHashMap;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.ModelDuplicateException;
|
import org.keycloak.models.ModelDuplicateException;
|
||||||
import org.keycloak.models.ModelException;
|
import org.keycloak.models.ModelException;
|
||||||
import org.keycloak.models.OTPPolicy;
|
import org.keycloak.models.OTPPolicy;
|
||||||
|
@ -29,7 +30,6 @@ import org.keycloak.models.jpa.entities.UserEntity;
|
||||||
import org.keycloak.models.jpa.entities.UserRequiredActionEntity;
|
import org.keycloak.models.jpa.entities.UserRequiredActionEntity;
|
||||||
import org.keycloak.models.jpa.entities.UserRoleMappingEntity;
|
import org.keycloak.models.jpa.entities.UserRoleMappingEntity;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
|
@ -43,8 +43,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
|
|
|
@ -59,7 +59,7 @@ public class JpaUserProvider implements UserProvider {
|
||||||
entity.setRealmId(realm.getId());
|
entity.setRealmId(realm.getId());
|
||||||
em.persist(entity);
|
em.persist(entity);
|
||||||
em.flush();
|
em.flush();
|
||||||
UserModel userModel = new UserAdapter(realm, em, entity);
|
UserModel userModel = new UserAdapter(session, realm, em, entity);
|
||||||
|
|
||||||
if (addDefaultRoles) {
|
if (addDefaultRoles) {
|
||||||
for (String r : realm.getDefaultRoles()) {
|
for (String r : realm.getDefaultRoles()) {
|
||||||
|
@ -241,7 +241,7 @@ public class JpaUserProvider implements UserProvider {
|
||||||
|
|
||||||
List<UserModel> users = new ArrayList<UserModel>();
|
List<UserModel> users = new ArrayList<UserModel>();
|
||||||
for (UserEntity user : results) {
|
for (UserEntity user : results) {
|
||||||
users.add(new UserAdapter(realm, em, user));
|
users.add(new UserAdapter(session, realm, em, user));
|
||||||
}
|
}
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
@ -259,7 +259,7 @@ public class JpaUserProvider implements UserProvider {
|
||||||
query.setParameter("realmId", realm.getId());
|
query.setParameter("realmId", realm.getId());
|
||||||
List<UserEntity> entities = query.getResultList();
|
List<UserEntity> entities = query.getResultList();
|
||||||
if (entities.size() == 0) return null;
|
if (entities.size() == 0) return null;
|
||||||
return new UserAdapter(realm, em, entities.get(0));
|
return new UserAdapter(session, realm, em, entities.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -269,7 +269,7 @@ public class JpaUserProvider implements UserProvider {
|
||||||
query.setParameter("realmId", realm.getId());
|
query.setParameter("realmId", realm.getId());
|
||||||
List<UserEntity> results = query.getResultList();
|
List<UserEntity> results = query.getResultList();
|
||||||
if (results.size() == 0) return null;
|
if (results.size() == 0) return null;
|
||||||
return new UserAdapter(realm, em, results.get(0));
|
return new UserAdapter(session, realm, em, results.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -278,7 +278,7 @@ public class JpaUserProvider implements UserProvider {
|
||||||
query.setParameter("email", email.toLowerCase());
|
query.setParameter("email", email.toLowerCase());
|
||||||
query.setParameter("realmId", realm.getId());
|
query.setParameter("realmId", realm.getId());
|
||||||
List<UserEntity> results = query.getResultList();
|
List<UserEntity> results = query.getResultList();
|
||||||
return results.isEmpty() ? null : new UserAdapter(realm, em, results.get(0));
|
return results.isEmpty() ? null : new UserAdapter(session, realm, em, results.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -299,7 +299,7 @@ public class JpaUserProvider implements UserProvider {
|
||||||
", userId=" + identity.getUserId() + ", results=" + results);
|
", userId=" + identity.getUserId() + ", results=" + results);
|
||||||
} else {
|
} else {
|
||||||
UserEntity user = results.get(0);
|
UserEntity user = results.get(0);
|
||||||
return new UserAdapter(realm, em, user);
|
return new UserAdapter(session, realm, em, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,7 +316,7 @@ public class JpaUserProvider implements UserProvider {
|
||||||
", results=" + results);
|
", results=" + results);
|
||||||
} else {
|
} else {
|
||||||
UserEntity user = results.get(0);
|
UserEntity user = results.get(0);
|
||||||
return new UserAdapter(client.getRealm(), em, user);
|
return new UserAdapter(session, client.getRealm(), em, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,7 +347,7 @@ public class JpaUserProvider implements UserProvider {
|
||||||
}
|
}
|
||||||
List<UserEntity> results = query.getResultList();
|
List<UserEntity> results = query.getResultList();
|
||||||
List<UserModel> users = new ArrayList<UserModel>();
|
List<UserModel> users = new ArrayList<UserModel>();
|
||||||
for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
|
for (UserEntity entity : results) users.add(new UserAdapter(session, realm, em, entity));
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,7 +365,7 @@ public class JpaUserProvider implements UserProvider {
|
||||||
|
|
||||||
List<UserModel> users = new ArrayList<UserModel>();
|
List<UserModel> users = new ArrayList<UserModel>();
|
||||||
for (UserEntity user : results) {
|
for (UserEntity user : results) {
|
||||||
users.add(new UserAdapter(realm, em, user));
|
users.add(new UserAdapter(session, realm, em, user));
|
||||||
}
|
}
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
@ -388,7 +388,7 @@ public class JpaUserProvider implements UserProvider {
|
||||||
}
|
}
|
||||||
List<UserEntity> results = query.getResultList();
|
List<UserEntity> results = query.getResultList();
|
||||||
List<UserModel> users = new ArrayList<UserModel>();
|
List<UserModel> users = new ArrayList<UserModel>();
|
||||||
for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
|
for (UserEntity entity : results) users.add(new UserAdapter(session, realm, em, entity));
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -446,7 +446,7 @@ public class JpaUserProvider implements UserProvider {
|
||||||
}
|
}
|
||||||
List<UserEntity> results = query.getResultList();
|
List<UserEntity> results = query.getResultList();
|
||||||
List<UserModel> users = new ArrayList<UserModel>();
|
List<UserModel> users = new ArrayList<UserModel>();
|
||||||
for (UserEntity entity : results) users.add(new UserAdapter(realm, em, entity));
|
for (UserEntity entity : results) users.add(new UserAdapter(session, realm, em, entity));
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -460,7 +460,7 @@ public class JpaUserProvider implements UserProvider {
|
||||||
List<UserModel> users = new ArrayList<UserModel>();
|
List<UserModel> users = new ArrayList<UserModel>();
|
||||||
for (UserAttributeEntity attr : results) {
|
for (UserAttributeEntity attr : results) {
|
||||||
UserEntity user = attr.getUser();
|
UserEntity user = attr.getUser();
|
||||||
users.add(new UserAdapter(realm, em, user));
|
users.add(new UserAdapter(session, realm, em, user));
|
||||||
}
|
}
|
||||||
return users;
|
return users;
|
||||||
}
|
}
|
||||||
|
@ -495,17 +495,17 @@ public class JpaUserProvider implements UserProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
||||||
return CredentialValidation.validCredentials(realm, user, input);
|
return CredentialValidation.validCredentials(session, realm, user, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
|
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel... input) {
|
||||||
return CredentialValidation.validCredentials(realm, user, input);
|
return CredentialValidation.validCredentials(session, realm, user, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
|
public CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input) {
|
||||||
// Not supported yet
|
// Not supported yet
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package org.keycloak.models.jpa;
|
package org.keycloak.models.jpa;
|
||||||
|
|
||||||
|
import org.keycloak.hash.PasswordHashManager;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.OTPPolicy;
|
import org.keycloak.models.OTPPolicy;
|
||||||
import org.keycloak.models.ProtocolMapperModel;
|
import org.keycloak.models.ProtocolMapperModel;
|
||||||
import org.keycloak.models.UserConsentModel;
|
import org.keycloak.models.UserConsentModel;
|
||||||
|
@ -24,9 +26,9 @@ import org.keycloak.models.jpa.entities.UserGroupMembershipEntity;
|
||||||
import org.keycloak.models.jpa.entities.UserRequiredActionEntity;
|
import org.keycloak.models.jpa.entities.UserRequiredActionEntity;
|
||||||
import org.keycloak.models.jpa.entities.UserRoleMappingEntity;
|
import org.keycloak.models.jpa.entities.UserRoleMappingEntity;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
|
||||||
import org.keycloak.common.util.MultivaluedHashMap;
|
import org.keycloak.common.util.MultivaluedHashMap;
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
|
import org.keycloak.hash.PasswordHashProvider;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import javax.persistence.TypedQuery;
|
import javax.persistence.TypedQuery;
|
||||||
|
@ -41,8 +43,6 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
|
@ -52,11 +52,13 @@ public class UserAdapter implements UserModel {
|
||||||
protected UserEntity user;
|
protected UserEntity user;
|
||||||
protected EntityManager em;
|
protected EntityManager em;
|
||||||
protected RealmModel realm;
|
protected RealmModel realm;
|
||||||
|
private final KeycloakSession session;
|
||||||
|
|
||||||
public UserAdapter(RealmModel realm, EntityManager em, UserEntity user) {
|
public UserAdapter(KeycloakSession session, RealmModel realm, EntityManager em, UserEntity user) {
|
||||||
this.em = em;
|
this.em = em;
|
||||||
this.user = user;
|
this.user = user;
|
||||||
this.realm = realm;
|
this.realm = realm;
|
||||||
|
this.session = session;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserEntity getUser() {
|
public UserEntity getUser() {
|
||||||
|
@ -387,18 +389,12 @@ public class UserAdapter implements UserModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setValue(CredentialEntity credentialEntity, UserCredentialModel cred) {
|
private void setValue(CredentialEntity credentialEntity, UserCredentialModel cred) {
|
||||||
byte[] salt = getSalt();
|
UserCredentialValueModel encoded = PasswordHashManager.encode(session, realm, cred.getValue());
|
||||||
int hashIterations = 1;
|
|
||||||
PasswordPolicy policy = realm.getPasswordPolicy();
|
|
||||||
if (policy != null) {
|
|
||||||
hashIterations = policy.getHashIterations();
|
|
||||||
if (hashIterations == -1)
|
|
||||||
hashIterations = 1;
|
|
||||||
}
|
|
||||||
credentialEntity.setCreatedDate(Time.toMillis(Time.currentTime()));
|
credentialEntity.setCreatedDate(Time.toMillis(Time.currentTime()));
|
||||||
credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue(), hashIterations));
|
credentialEntity.setAlgorithm(encoded.getAlgorithm());
|
||||||
credentialEntity.setSalt(salt);
|
credentialEntity.setValue(encoded.getValue());
|
||||||
credentialEntity.setHashIterations(hashIterations);
|
credentialEntity.setSalt(encoded.getSalt());
|
||||||
|
credentialEntity.setHashIterations(encoded.getHashIterations());
|
||||||
}
|
}
|
||||||
|
|
||||||
private CredentialEntity getCredentialEntity(UserEntity userEntity, String credType) {
|
private CredentialEntity getCredentialEntity(UserEntity userEntity, String credType) {
|
||||||
|
|
|
@ -474,17 +474,17 @@ public class MongoUserProvider implements UserProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validCredentials(RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, List<UserCredentialModel> input) {
|
||||||
return CredentialValidation.validCredentials(realm, user, input);
|
return CredentialValidation.validCredentials(session, realm, user, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean validCredentials(RealmModel realm, UserModel user, UserCredentialModel... input) {
|
public boolean validCredentials(KeycloakSession session, RealmModel realm, UserModel user, UserCredentialModel... input) {
|
||||||
return CredentialValidation.validCredentials(realm, user, input);
|
return CredentialValidation.validCredentials(session, realm, user, input);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CredentialValidationOutput validCredentials(RealmModel realm, UserCredentialModel... input) {
|
public CredentialValidationOutput validCredentials(KeycloakSession session, RealmModel realm, UserCredentialModel... input) {
|
||||||
// Not supported yet
|
// Not supported yet
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package org.keycloak.models.mongo.keycloak.adapters;
|
package org.keycloak.models.mongo.keycloak.adapters;
|
||||||
|
|
||||||
import static org.keycloak.models.utils.Pbkdf2PasswordEncoder.getSalt;
|
|
||||||
|
|
||||||
import com.mongodb.DBObject;
|
import com.mongodb.DBObject;
|
||||||
import com.mongodb.QueryBuilder;
|
import com.mongodb.QueryBuilder;
|
||||||
|
|
||||||
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
|
||||||
|
import org.keycloak.hash.PasswordHashManager;
|
||||||
import org.keycloak.models.ClientModel;
|
import org.keycloak.models.ClientModel;
|
||||||
import org.keycloak.models.GroupModel;
|
import org.keycloak.models.GroupModel;
|
||||||
import org.keycloak.models.OTPPolicy;
|
import org.keycloak.models.OTPPolicy;
|
||||||
|
@ -26,8 +25,8 @@ import org.keycloak.models.mongo.keycloak.entities.MongoUserConsentEntity;
|
||||||
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
|
import org.keycloak.models.mongo.keycloak.entities.MongoUserEntity;
|
||||||
import org.keycloak.models.mongo.utils.MongoModelUtils;
|
import org.keycloak.models.mongo.utils.MongoModelUtils;
|
||||||
import org.keycloak.models.utils.KeycloakModelUtils;
|
import org.keycloak.models.utils.KeycloakModelUtils;
|
||||||
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
|
||||||
import org.keycloak.common.util.Time;
|
import org.keycloak.common.util.Time;
|
||||||
|
import org.keycloak.hash.PasswordHashProvider;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -329,18 +328,12 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setValue(CredentialEntity credentialEntity, UserCredentialModel cred) {
|
private void setValue(CredentialEntity credentialEntity, UserCredentialModel cred) {
|
||||||
byte[] salt = getSalt();
|
UserCredentialValueModel encoded = PasswordHashManager.encode(session, realm, cred.getValue());
|
||||||
int hashIterations = 1;
|
|
||||||
PasswordPolicy policy = realm.getPasswordPolicy();
|
|
||||||
if (policy != null) {
|
|
||||||
hashIterations = policy.getHashIterations();
|
|
||||||
if (hashIterations == -1)
|
|
||||||
hashIterations = 1;
|
|
||||||
}
|
|
||||||
credentialEntity.setCreatedDate(Time.toMillis(Time.currentTime()));
|
credentialEntity.setCreatedDate(Time.toMillis(Time.currentTime()));
|
||||||
credentialEntity.setValue(new Pbkdf2PasswordEncoder(salt).encode(cred.getValue(), hashIterations));
|
credentialEntity.setAlgorithm(encoded.getAlgorithm());
|
||||||
credentialEntity.setSalt(salt);
|
credentialEntity.setValue(encoded.getValue());
|
||||||
credentialEntity.setHashIterations(hashIterations);
|
credentialEntity.setSalt(encoded.getSalt());
|
||||||
|
credentialEntity.setHashIterations(encoded.getHashIterations());
|
||||||
}
|
}
|
||||||
|
|
||||||
private CredentialEntity getCredentialEntity(MongoUserEntity userEntity, String credType) {
|
private CredentialEntity getCredentialEntity(MongoUserEntity userEntity, String credType) {
|
||||||
|
|
|
@ -149,7 +149,7 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
|
||||||
List<UserCredentialModel> credentials = new LinkedList<>();
|
List<UserCredentialModel> credentials = new LinkedList<>();
|
||||||
String password = inputData.getFirst(CredentialRepresentation.PASSWORD);
|
String password = inputData.getFirst(CredentialRepresentation.PASSWORD);
|
||||||
credentials.add(UserCredentialModel.password(password));
|
credentials.add(UserCredentialModel.password(password));
|
||||||
boolean valid = context.getSession().users().validCredentials(context.getRealm(), user, credentials);
|
boolean valid = context.getSession().users().validCredentials(context.getSession(), context.getRealm(), user, credentials);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
context.getEvent().user(user);
|
context.getEvent().user(user);
|
||||||
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class OTPFormAuthenticator extends AbstractUsernameFormAuthenticator impl
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
credentials.add(UserCredentialModel.otp(context.getRealm().getOTPPolicy().getType(), password));
|
credentials.add(UserCredentialModel.otp(context.getRealm().getOTPPolicy().getType(), password));
|
||||||
boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
|
boolean valid = context.getSession().users().validCredentials(context.getSession(), context.getRealm(), context.getUser(), credentials);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
context.getEvent().user(context.getUser())
|
context.getEvent().user(context.getUser())
|
||||||
.error(Errors.INVALID_USER_CREDENTIALS);
|
.error(Errors.INVALID_USER_CREDENTIALS);
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class SpnegoAuthenticator extends AbstractUsernameFormAuthenticator imple
|
||||||
String spnegoToken = tokens[1];
|
String spnegoToken = tokens[1];
|
||||||
UserCredentialModel spnegoCredential = UserCredentialModel.kerberos(spnegoToken);
|
UserCredentialModel spnegoCredential = UserCredentialModel.kerberos(spnegoToken);
|
||||||
|
|
||||||
CredentialValidationOutput output = context.getSession().users().validCredentials(context.getRealm(), spnegoCredential);
|
CredentialValidationOutput output = context.getSession().users().validCredentials(context.getSession(), context.getRealm(), spnegoCredential);
|
||||||
|
|
||||||
if (output.getAuthStatus() == CredentialValidationOutput.Status.AUTHENTICATED) {
|
if (output.getAuthStatus() == CredentialValidationOutput.Status.AUTHENTICATED) {
|
||||||
context.setUser(output.getAuthenticatedUser());
|
context.setUser(output.getAuthenticatedUser());
|
||||||
|
|
|
@ -51,7 +51,7 @@ public class ValidateOTP extends AbstractDirectGrantAuthenticator {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
credentials.add(UserCredentialModel.otp(context.getRealm().getOTPPolicy().getType(), otp));
|
credentials.add(UserCredentialModel.otp(context.getRealm().getOTPPolicy().getType(), otp));
|
||||||
boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
|
boolean valid = context.getSession().users().validCredentials(context.getSession(), context.getRealm(), context.getUser(), credentials);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
context.getEvent().user(context.getUser());
|
context.getEvent().user(context.getUser());
|
||||||
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class ValidatePassword extends AbstractDirectGrantAuthenticator {
|
||||||
List<UserCredentialModel> credentials = new LinkedList<>();
|
List<UserCredentialModel> credentials = new LinkedList<>();
|
||||||
String password = inputData.getFirst(CredentialRepresentation.PASSWORD);
|
String password = inputData.getFirst(CredentialRepresentation.PASSWORD);
|
||||||
credentials.add(UserCredentialModel.password(password));
|
credentials.add(UserCredentialModel.password(password));
|
||||||
boolean valid = context.getSession().users().validCredentials(context.getRealm(), context.getUser(), credentials);
|
boolean valid = context.getSession().users().validCredentials(context.getSession(), context.getRealm(), context.getUser(), credentials);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
context.getEvent().user(context.getUser());
|
context.getEvent().user(context.getUser());
|
||||||
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
context.getEvent().error(Errors.INVALID_USER_CREDENTIALS);
|
||||||
|
|
|
@ -53,7 +53,7 @@ public class RegistrationPassword implements FormAction, FormActionFactory {
|
||||||
errors.add(new FormMessage(RegistrationPage.FIELD_PASSWORD_CONFIRM, Messages.INVALID_PASSWORD_CONFIRM));
|
errors.add(new FormMessage(RegistrationPage.FIELD_PASSWORD_CONFIRM, Messages.INVALID_PASSWORD_CONFIRM));
|
||||||
}
|
}
|
||||||
if (formData.getFirst(RegistrationPage.FIELD_PASSWORD) != null) {
|
if (formData.getFirst(RegistrationPage.FIELD_PASSWORD) != null) {
|
||||||
PasswordPolicy.Error err = context.getRealm().getPasswordPolicy().validate(context.getRealm().isRegistrationEmailAsUsername() ? formData.getFirst(RegistrationPage.FIELD_EMAIL) : formData.getFirst(RegistrationPage.FIELD_USERNAME), formData.getFirst(RegistrationPage.FIELD_PASSWORD));
|
PasswordPolicy.Error err = context.getRealm().getPasswordPolicy().validate(context.getSession(), context.getRealm().isRegistrationEmailAsUsername() ? formData.getFirst(RegistrationPage.FIELD_EMAIL) : formData.getFirst(RegistrationPage.FIELD_USERNAME), formData.getFirst(RegistrationPage.FIELD_PASSWORD));
|
||||||
if (err != null)
|
if (err != null)
|
||||||
errors.add(new FormMessage(RegistrationPage.FIELD_PASSWORD, err.getMessage(), err.getParameters()));
|
errors.add(new FormMessage(RegistrationPage.FIELD_PASSWORD, err.getMessage(), err.getParameters()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,7 +73,7 @@ public class UpdateTotp implements RequiredActionProvider, RequiredActionFactory
|
||||||
UserCredentialModel cred = new UserCredentialModel();
|
UserCredentialModel cred = new UserCredentialModel();
|
||||||
cred.setType(context.getRealm().getOTPPolicy().getType());
|
cred.setType(context.getRealm().getOTPPolicy().getType());
|
||||||
cred.setValue(totp);
|
cred.setValue(totp);
|
||||||
context.getSession().users().validCredentials(context.getRealm(), context.getUser(), cred);
|
context.getSession().users().validCredentials(context.getSession(), context.getRealm(), context.getUser(), cred);
|
||||||
|
|
||||||
context.getUser().setOtpEnabled(true);
|
context.getUser().setOtpEnabled(true);
|
||||||
context.success();
|
context.success();
|
||||||
|
|
|
@ -572,7 +572,7 @@ public class AccountService extends AbstractSecuredLocalService {
|
||||||
UserCredentialModel cred = new UserCredentialModel();
|
UserCredentialModel cred = new UserCredentialModel();
|
||||||
cred.setType(realm.getOTPPolicy().getType());
|
cred.setType(realm.getOTPPolicy().getType());
|
||||||
cred.setValue(totp);
|
cred.setValue(totp);
|
||||||
session.users().validCredentials(realm, user, cred);
|
session.users().validCredentials(session, realm, user, cred);
|
||||||
|
|
||||||
event.event(EventType.UPDATE_TOTP).client(auth.getClient()).user(auth.getUser()).success();
|
event.event(EventType.UPDATE_TOTP).client(auth.getClient()).user(auth.getUser()).success();
|
||||||
|
|
||||||
|
@ -619,7 +619,7 @@ public class AccountService extends AbstractSecuredLocalService {
|
||||||
}
|
}
|
||||||
|
|
||||||
UserCredentialModel cred = UserCredentialModel.password(password);
|
UserCredentialModel cred = UserCredentialModel.password(password);
|
||||||
if (!session.users().validCredentials(realm, user, cred)) {
|
if (!session.users().validCredentials(session, realm, user, cred)) {
|
||||||
setReferrerOnPage();
|
setReferrerOnPage();
|
||||||
return account.setError(Messages.INVALID_PASSWORD_EXISTING).createResponse(AccountPages.PASSWORD);
|
return account.setError(Messages.INVALID_PASSWORD_EXISTING).createResponse(AccountPages.PASSWORD);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.keycloak.services.validation;
|
package org.keycloak.services.validation;
|
||||||
|
|
||||||
import org.keycloak.authentication.requiredactions.util.UpdateProfileContext;
|
import org.keycloak.authentication.requiredactions.util.UpdateProfileContext;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.PasswordPolicy;
|
import org.keycloak.models.PasswordPolicy;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.utils.FormMessage;
|
import org.keycloak.models.utils.FormMessage;
|
||||||
|
@ -25,7 +26,7 @@ public class Validation {
|
||||||
// Actually allow same emails like angular. See ValidationTest.testEmailValidation()
|
// Actually allow same emails like angular. See ValidationTest.testEmailValidation()
|
||||||
private static final Pattern EMAIL_PATTERN = Pattern.compile("[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*");
|
private static final Pattern EMAIL_PATTERN = Pattern.compile("[a-zA-Z0-9!#$%&'*+/=?^_`{|}~.-]+@[a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*");
|
||||||
|
|
||||||
public static List<FormMessage> validateRegistrationForm(RealmModel realm, MultivaluedMap<String, String> formData, List<String> requiredCredentialTypes, PasswordPolicy policy) {
|
public static List<FormMessage> validateRegistrationForm(KeycloakSession session, RealmModel realm, MultivaluedMap<String, String> formData, List<String> requiredCredentialTypes, PasswordPolicy policy) {
|
||||||
List<FormMessage> errors = new ArrayList<>();
|
List<FormMessage> errors = new ArrayList<>();
|
||||||
|
|
||||||
if (!realm.isRegistrationEmailAsUsername() && isBlank(formData.getFirst(FIELD_USERNAME))) {
|
if (!realm.isRegistrationEmailAsUsername() && isBlank(formData.getFirst(FIELD_USERNAME))) {
|
||||||
|
@ -55,7 +56,7 @@ public class Validation {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (formData.getFirst(FIELD_PASSWORD) != null) {
|
if (formData.getFirst(FIELD_PASSWORD) != null) {
|
||||||
PasswordPolicy.Error err = policy.validate(realm.isRegistrationEmailAsUsername()?formData.getFirst(FIELD_EMAIL):formData.getFirst(FIELD_USERNAME), formData.getFirst(FIELD_PASSWORD));
|
PasswordPolicy.Error err = policy.validate(session, realm.isRegistrationEmailAsUsername()?formData.getFirst(FIELD_EMAIL):formData.getFirst(FIELD_USERNAME), formData.getFirst(FIELD_PASSWORD));
|
||||||
if (err != null)
|
if (err != null)
|
||||||
errors.add(new FormMessage(FIELD_PASSWORD, err.getMessage(), err.getParameters()));
|
errors.add(new FormMessage(FIELD_PASSWORD, err.getMessage(), err.getParameters()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,5 +41,4 @@
|
||||||
</pluginManagement>
|
</pluginManagement>
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -5,7 +5,7 @@ import org.jboss.arquillian.container.test.api.OperateOnDeployment;
|
||||||
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
||||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||||
import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
|
import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
|
||||||
import org.keycloak.testsuite.util.WaitUtils;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,7 +61,7 @@ public class CustomerPortalExample extends AbstractPageWithInjectedUrl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void customerSession() {
|
public void customerSession() {
|
||||||
WaitUtils.waitGuiForElement(customerSessionLink);
|
waitUntilElement(customerSessionLink).is().present();
|
||||||
customerSessionLink.click();
|
customerSessionLink.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,11 +70,11 @@ public class CustomerPortalExample extends AbstractPageWithInjectedUrl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForCustomerListingHeader() {
|
public void waitForCustomerListingHeader() {
|
||||||
WaitUtils.waitGuiForElementNotPresent(customerListingHeader);
|
waitUntilElement(customerListingHeader).is().not().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForCustomerSessionHeader() {
|
public void waitForCustomerSessionHeader() {
|
||||||
WaitUtils.waitGuiForElementNotPresent(customerSessionHeader);
|
waitUntilElement(customerSessionHeader).is().not().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import org.jboss.arquillian.container.test.api.OperateOnDeployment;
|
||||||
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
||||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||||
import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
|
import org.keycloak.testsuite.page.AbstractPageWithInjectedUrl;
|
||||||
import org.keycloak.testsuite.util.WaitUtils;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,7 +48,7 @@ public class ProductPortalExample extends AbstractPageWithInjectedUrl {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForProductListingHeader() {
|
public void waitForProductListingHeader() {
|
||||||
WaitUtils.waitGuiForElementNotPresent(productListingHeader);
|
waitUntilElement(productListingHeader).is().not().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void logOut() {
|
public void logOut() {
|
||||||
|
|
|
@ -2,8 +2,7 @@ package org.keycloak.testsuite.auth.page.account;
|
||||||
|
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.testsuite.page.Form;
|
import org.keycloak.testsuite.page.Form;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElementNotPresent;
|
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
@ -49,11 +48,11 @@ public class AccountFields extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForUsernameInputPresent() {
|
public void waitForUsernameInputPresent() {
|
||||||
waitAjaxForElement(usernameInput);
|
waitUntilElement(usernameInput).is().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForUsernameInputNotPresent() {
|
public void waitForUsernameInputNotPresent() {
|
||||||
waitAjaxForElementNotPresent(usernameInput);
|
waitUntilElement(usernameInput).is().not().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import javax.ws.rs.core.UriBuilder;
|
||||||
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
||||||
import org.keycloak.admin.client.resource.RealmResource;
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
import org.keycloak.testsuite.auth.page.AuthRealm;
|
import org.keycloak.testsuite.auth.page.AuthRealm;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElementPresent;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
@ -66,7 +66,7 @@ public class AccountManagement extends AuthRealm {
|
||||||
private WebElement error;
|
private WebElement error;
|
||||||
|
|
||||||
public String getErrorMessage() {
|
public String getErrorMessage() {
|
||||||
waitGuiForElementPresent(error, "Error message should be visible");
|
waitUntilElement(error, "Error message should be present").is().present();
|
||||||
return error.getText();
|
return error.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +107,6 @@ public class AccountManagement extends AuthRealm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForAccountLinkPresent() {
|
public void waitForAccountLinkPresent() {
|
||||||
waitGuiForElementPresent(accountLink, "account link should be present");
|
waitUntilElement(accountLink, "account link should be present").is().present();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
package org.keycloak.testsuite.auth.page.account;
|
package org.keycloak.testsuite.auth.page.account;
|
||||||
|
|
||||||
import org.keycloak.testsuite.page.Form;
|
import org.keycloak.testsuite.page.Form;
|
||||||
import org.keycloak.testsuite.util.WaitUtils;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
@ -54,6 +54,6 @@ public class PasswordFields extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForConfirmPasswordInputPresent() {
|
public void waitForConfirmPasswordInputPresent() {
|
||||||
WaitUtils.waitGuiForElement(confirmPasswordInput);
|
waitUntilElement(confirmPasswordInput).is().present();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* JBoss, Home of Professional Open Source
|
||||||
|
*
|
||||||
|
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.auth.page.account.fragment;
|
||||||
|
|
||||||
|
import org.keycloak.testsuite.page.AbstractAlert;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author tkyjovsk
|
||||||
|
*/
|
||||||
|
public class AccountManagementAlert extends AbstractAlert {
|
||||||
|
|
||||||
|
public boolean isError() {
|
||||||
|
return getAttributeClass().contains("alert-error");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -20,8 +20,7 @@ package org.keycloak.testsuite.auth.page.login;
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
import org.jboss.arquillian.graphene.page.Page;
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
import org.keycloak.testsuite.auth.page.AuthRealm;
|
import org.keycloak.testsuite.auth.page.AuthRealm;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElementNotPresent;
|
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
@ -62,11 +61,11 @@ public abstract class Login extends AuthRealm {
|
||||||
private WebElement keycloakTheme;
|
private WebElement keycloakTheme;
|
||||||
|
|
||||||
public void waitForKeycloakThemeNotPresent() {
|
public void waitForKeycloakThemeNotPresent() {
|
||||||
waitGuiForElementNotPresent(keycloakTheme);
|
waitUntilElement(keycloakTheme).is().not().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForKeycloakThemePresent() {
|
public void waitForKeycloakThemePresent() {
|
||||||
waitGuiForElement(keycloakTheme);
|
waitUntilElement(keycloakTheme).is().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.keycloak.testsuite.auth.page.login;
|
||||||
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
import org.keycloak.testsuite.auth.page.AuthRealm;
|
import org.keycloak.testsuite.auth.page.AuthRealm;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElementPresent;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
@ -45,7 +45,7 @@ public class LoginActions extends AuthRealm {
|
||||||
private WebElement feedbackText;
|
private WebElement feedbackText;
|
||||||
|
|
||||||
public String getFeedbackText() {
|
public String getFeedbackText() {
|
||||||
waitGuiForElementPresent(feedbackText, "Feedback message should be visible");
|
waitUntilElement(feedbackText, "Feedback message should be present").is().present();
|
||||||
return feedbackText.getText();
|
return feedbackText.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -70,17 +70,17 @@ public class LoginForm extends Form {
|
||||||
|
|
||||||
public void register() {
|
public void register() {
|
||||||
waitForUsernameInputPresent();
|
waitForUsernameInputPresent();
|
||||||
waitAjaxForElement(registerLink);
|
waitUntilElement(registerLink).is().present();
|
||||||
registerLink.click();
|
registerLink.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void login() {
|
public void login() {
|
||||||
waitAjaxForElement(loginButton);
|
waitUntilElement(loginButton).is().present();
|
||||||
loginButton.click();
|
loginButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void forgotPassword() {
|
public void forgotPassword() {
|
||||||
waitAjaxForElement(forgottenPassword);
|
waitUntilElement(forgottenPassword).is().present();
|
||||||
forgottenPassword.click();
|
forgottenPassword.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,32 +94,31 @@ public class LoginForm extends Form {
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
// public void cancel() {
|
// public void cancel() {
|
||||||
// waitAjaxForElement(cancelButton);
|
// waitUntilElement(cancelButton).is().present();
|
||||||
// cancelButton.click();
|
// cancelButton.click();
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public void waitForUsernameInputPresent() {
|
public void waitForUsernameInputPresent() {
|
||||||
accountFields.waitForUsernameInputPresent();
|
accountFields.waitForUsernameInputPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForRegisterLinkNotPresent() {
|
public void waitForRegisterLinkNotPresent() {
|
||||||
waitAjaxForElementNotPresent(registerLink);
|
waitUntilElement(registerLink).is().not().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForResetPasswordLinkNotPresent() {
|
public void waitForResetPasswordLinkNotPresent() {
|
||||||
waitAjaxForElementNotPresent(forgottenPassword);
|
waitUntilElement(forgottenPassword).is().not().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForRememberMePresent() {
|
public void waitForRememberMePresent() {
|
||||||
waitAjaxForElement(rememberMe);
|
waitUntilElement(rememberMe).is().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForRememberMeNotPresent() {
|
public void waitForRememberMeNotPresent() {
|
||||||
waitAjaxForElementNotPresent(rememberMe);
|
waitUntilElement(rememberMe).is().not().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForLoginButtonPresent() {
|
public void waitForLoginButtonPresent() {
|
||||||
waitGuiForElement(loginButton);
|
waitUntilElement(loginButton).is().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ import javax.ws.rs.core.UriBuilder;
|
||||||
import org.jboss.arquillian.graphene.page.Page;
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
import org.keycloak.testsuite.auth.page.account.AccountFields;
|
import org.keycloak.testsuite.auth.page.account.AccountFields;
|
||||||
import org.keycloak.testsuite.auth.page.account.PasswordFields;
|
import org.keycloak.testsuite.auth.page.account.PasswordFields;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElementPresent;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ public class ResetCredentials extends LoginActions {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getInfoMessage() {
|
public String getInfoMessage() {
|
||||||
waitGuiForElementPresent(info, "Info message should be visible");
|
waitUntilElement(info, "Info message should be visible").is().present();
|
||||||
return info.getText();
|
return info.getText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.testsuite.auth.page.login;
|
package org.keycloak.testsuite.auth.page.login;
|
||||||
|
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ public class VerifyEmail extends Authenticate {
|
||||||
private WebElement instruction;
|
private WebElement instruction;
|
||||||
|
|
||||||
public String getInstructionMessage() {
|
public String getInstructionMessage() {
|
||||||
waitGuiForElement(instruction);
|
waitUntilElement(instruction).is().present();
|
||||||
return instruction.getText();
|
return instruction.getText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,7 @@ package org.keycloak.testsuite.console.page;
|
||||||
import org.keycloak.admin.client.resource.RealmResource;
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||||
|
|
||||||
import org.keycloak.testsuite.util.WaitUtils;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
@ -39,7 +38,7 @@ public class AdminConsoleRealm extends AdminConsoleRealmsRoot {
|
||||||
private ConfigureMenu configureMenu;
|
private ConfigureMenu configureMenu;
|
||||||
|
|
||||||
public ConfigureMenu configure() {
|
public ConfigureMenu configure() {
|
||||||
waitGuiForElement(By.xpath("//div[./h2[text()='Configure']]"));
|
waitUntilElement(By.xpath("//div[./h2[text()='Configure']]")).is().present();
|
||||||
return configureMenu;
|
return configureMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +91,7 @@ public class AdminConsoleRealm extends AdminConsoleRealmsRoot {
|
||||||
protected ManageMenu manageMenu;
|
protected ManageMenu manageMenu;
|
||||||
|
|
||||||
public ManageMenu manage() {
|
public ManageMenu manage() {
|
||||||
WaitUtils.waitGuiForElement(By.xpath("//div[./h2[text()='Manage']]"));
|
waitUntilElement(By.xpath("//div[./h2[text()='Manage']]")).is().present();
|
||||||
return manageMenu;
|
return manageMenu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,12 +24,12 @@ public class Authentication extends AdminConsoleRealm {
|
||||||
private WebElement close;
|
private WebElement close;
|
||||||
|
|
||||||
public String getSuccessMessage() {
|
public String getSuccessMessage() {
|
||||||
waitAjaxForElement(success);
|
waitUntilElement(success).is().present();
|
||||||
return success.getText();
|
return success.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getErrorMessage() {
|
public String getErrorMessage() {
|
||||||
waitAjaxForElement(error);
|
waitUntilElement(error).is().present();
|
||||||
return error.getText();
|
return error.getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ public class Authentication extends AdminConsoleRealm {
|
||||||
if (close.isDisplayed()) {
|
if (close.isDisplayed()) {
|
||||||
close.click();
|
close.click();
|
||||||
}
|
}
|
||||||
waitAjaxForElementNotVisible(close);
|
waitUntilElement(close).is().not().visible();
|
||||||
}
|
}
|
||||||
|
|
||||||
public AuthenticationTabs tabs() {
|
public AuthenticationTabs tabs() {
|
||||||
|
|
|
@ -8,7 +8,7 @@ import org.openqa.selenium.support.ui.Select;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Petr Mensik
|
* @author Petr Mensik
|
||||||
|
@ -32,7 +32,7 @@ public class PasswordPolicy extends Authentication {
|
||||||
private List<WebElement> allRows;
|
private List<WebElement> allRows;
|
||||||
|
|
||||||
public void addPolicy(PasswordPolicy.Type policy, String value) {
|
public void addPolicy(PasswordPolicy.Type policy, String value) {
|
||||||
waitGuiForElement(addPolicySelectElement);
|
waitUntilElement(addPolicySelectElement).is().present();
|
||||||
addPolicySelect.selectByVisibleText(policy.getName());
|
addPolicySelect.selectByVisibleText(policy.getName());
|
||||||
setPolicyValue(policy, value);
|
setPolicyValue(policy, value);
|
||||||
primaryButton.click();
|
primaryButton.click();
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.testsuite.console.page.authentication.flows;
|
package org.keycloak.testsuite.console.page.authentication.flows;
|
||||||
|
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
@ -71,7 +71,7 @@ public class FlowsTable {
|
||||||
|
|
||||||
private WebElement getRowByLabelText(String text) {
|
private WebElement getRowByLabelText(String text) {
|
||||||
WebElement row = tbody.findElement(By.xpath("//span[text() = '" + text + "']/../.."));
|
WebElement row = tbody.findElement(By.xpath("//span[text() = '" + text + "']/../.."));
|
||||||
waitAjaxForElement(row);
|
waitUntilElement(row).is().present();
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,17 +38,17 @@ public class ClientMappers extends Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createMapper() {
|
public void createMapper() {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickHeaderLink(CREATE);
|
clickHeaderLink(CREATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addBuiltin() {
|
public void addBuiltin() {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickHeaderLink(ADD_BUILTIN);
|
clickHeaderLink(ADD_BUILTIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clickMapper(String mapperName) {
|
public void clickMapper(String mapperName) {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
body().findElement(By.linkText(mapperName)).click();
|
body().findElement(By.linkText(mapperName)).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@ public class ClientMappers extends Client {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clickMapperActionButton(String mapperName, String buttonText) {
|
private void clickMapperActionButton(String mapperName, String buttonText) {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickRowActionButton(getRowByLinkText(mapperName), buttonText);
|
clickRowActionButton(getRowByLinkText(mapperName), buttonText);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,32 +62,32 @@ public class Clients extends AdminConsoleRealm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createClient() {
|
public void createClient() {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickHeaderLink(CREATE);
|
clickHeaderLink(CREATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void importClient() {
|
public void importClient() {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickHeaderLink(IMPORT);
|
clickHeaderLink(IMPORT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clickClient(ClientRepresentation client) {
|
public void clickClient(ClientRepresentation client) {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickClient(client.getClientId());
|
clickClient(client.getClientId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clickClient(String clientId) {
|
public void clickClient(String clientId) {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
body().findElement(linkText(clientId)).click();
|
body().findElement(linkText(clientId)).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void editClient(String clientId) {
|
public void editClient(String clientId) {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickRowActionButton(getRowByLinkText(clientId), EDIT);
|
clickRowActionButton(getRowByLinkText(clientId), EDIT);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteClient(String clientId) {
|
public void deleteClient(String clientId) {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickRowActionButton(getRowByLinkText(clientId), DELETE);
|
clickRowActionButton(getRowByLinkText(clientId), DELETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
|
||||||
import org.keycloak.testsuite.page.Form;
|
import org.keycloak.testsuite.page.Form;
|
||||||
import static org.keycloak.testsuite.page.Form.getInputValue;
|
import static org.keycloak.testsuite.page.Form.getInputValue;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.pause;
|
import static org.keycloak.testsuite.util.WaitUtils.pause;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.keycloak.testsuite.util.Timer;
|
import org.keycloak.testsuite.util.Timer;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
@ -69,7 +69,7 @@ public class CreateClientForm extends Form {
|
||||||
private List<WebElement> deleteRedirectUriIcons;
|
private List<WebElement> deleteRedirectUriIcons;
|
||||||
|
|
||||||
public void setValues(ClientRepresentation client) {
|
public void setValues(ClientRepresentation client) {
|
||||||
waitAjaxForElement(clientIdInput);
|
waitUntilElement(clientIdInput).is().present();
|
||||||
|
|
||||||
setClientId(client.getClientId());
|
setClientId(client.getClientId());
|
||||||
setName(client.getName());
|
setName(client.getName());
|
||||||
|
@ -230,7 +230,7 @@ public class CreateClientForm extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getProtocol() {
|
public String getProtocol() {
|
||||||
waitAjaxForElement(protocolSelect.getFirstSelectedOption());
|
waitUntilElement(protocolSelect.getFirstSelectedOption()).is().present();
|
||||||
return protocolSelect.getFirstSelectedOption().getText();
|
return protocolSelect.getFirstSelectedOption().getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,17 +33,17 @@ public class AdminEvents extends Events {
|
||||||
private AdminEventsTableFilterForm filterForm;
|
private AdminEventsTableFilterForm filterForm;
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickHeaderButton("Update");
|
clickHeaderButton("Update");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickHeaderButton("Reset");
|
clickHeaderButton("Reset");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void filter() {
|
public void filter() {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
filterButton.click();
|
filterButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,7 +104,7 @@ public class Config extends Events {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForClearEventsButtonPresent() {
|
public void waitForClearEventsButtonPresent() {
|
||||||
waitAjaxForElement(clearLoginEventsButton);
|
waitUntilElement(clearLoginEventsButton).is().present();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,17 +33,17 @@ public class LoginEvents extends Events {
|
||||||
private LoginEventsTableFilterForm filterForm;
|
private LoginEventsTableFilterForm filterForm;
|
||||||
|
|
||||||
public void update() {
|
public void update() {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickHeaderButton("Update");
|
clickHeaderButton("Update");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reset() {
|
public void reset() {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickHeaderButton("Reset");
|
clickHeaderButton("Reset");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void filter() {
|
public void filter() {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
filterButton.click();
|
filterButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.keycloak.testsuite.console.page.federation;
|
package org.keycloak.testsuite.console.page.federation;
|
||||||
|
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
|
|
||||||
import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
|
import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
|
||||||
import org.keycloak.testsuite.page.Form;
|
import org.keycloak.testsuite.page.Form;
|
||||||
|
@ -50,7 +50,7 @@ public class KerberosUserProviderForm extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKerberosRealmInput(String kerberosRealm) {
|
public void setKerberosRealmInput(String kerberosRealm) {
|
||||||
waitGuiForElement(By.id("kerberosRealm"));
|
waitUntilElement(By.id("kerberosRealm")).is().present();
|
||||||
setInputValue(kerberosRealmInput, kerberosRealm);
|
setInputValue(kerberosRealmInput, kerberosRealm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ public class KerberosUserProviderForm extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectEditMode(String mode) {
|
public void selectEditMode(String mode) {
|
||||||
waitGuiForElement(By.id("editMode"));
|
waitUntilElement(By.id("editMode")).is().present();
|
||||||
editModeSelect.selectByVisibleText(mode);
|
editModeSelect.selectByVisibleText(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package org.keycloak.testsuite.console.page.federation;
|
package org.keycloak.testsuite.console.page.federation;
|
||||||
|
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
|
|
||||||
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
||||||
import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
|
import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
|
||||||
|
@ -156,17 +156,14 @@ public class LdapUserProviderForm extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKerberosRealmInput(String kerberosRealm) {
|
public void setKerberosRealmInput(String kerberosRealm) {
|
||||||
waitAjaxForElement(kerberosRealmInput);
|
|
||||||
setInputValue(kerberosRealmInput, kerberosRealm);
|
setInputValue(kerberosRealmInput, kerberosRealm);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setServerPrincipalInput(String serverPrincipal) {
|
public void setServerPrincipalInput(String serverPrincipal) {
|
||||||
waitAjaxForElement(serverPrincipalInput);
|
|
||||||
setInputValue(serverPrincipalInput, serverPrincipal);
|
setInputValue(serverPrincipalInput, serverPrincipal);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setKeyTabInput(String keyTab) {
|
public void setKeyTabInput(String keyTab) {
|
||||||
waitAjaxForElement(keyTabInput);
|
|
||||||
setInputValue(keyTabInput, keyTab);
|
setInputValue(keyTabInput, keyTab);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,22 +172,22 @@ public class LdapUserProviderForm extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectEditMode(String mode) {
|
public void selectEditMode(String mode) {
|
||||||
waitGuiForElement(By.id("editMode"));
|
waitUntilElement(By.id("editMode")).is().present();
|
||||||
editModeSelect.selectByVisibleText(mode);
|
editModeSelect.selectByVisibleText(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectVendor(String vendor) {
|
public void selectVendor(String vendor) {
|
||||||
waitGuiForElement(By.id("vendor"));
|
waitUntilElement(By.id("vendor")).is().present();
|
||||||
vendorSelect.selectByVisibleText(vendor);
|
vendorSelect.selectByVisibleText(vendor);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectAuthenticationType(String authenticationType) {
|
public void selectAuthenticationType(String authenticationType) {
|
||||||
waitGuiForElement(By.id("authType"));
|
waitUntilElement(By.id("authType")).is().present();
|
||||||
authTypeSelect.selectByVisibleText(authenticationType);
|
authTypeSelect.selectByVisibleText(authenticationType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectSearchScope(String searchScope) {
|
public void selectSearchScope(String searchScope) {
|
||||||
waitGuiForElement(By.id("searchScope"));
|
waitUntilElement(By.id("searchScope")).is().present();
|
||||||
searchScopeSelect.selectByVisibleText(searchScope);
|
searchScopeSelect.selectByVisibleText(searchScope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +245,7 @@ public class LdapUserProviderForm extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void synchronizeAllUsers() {
|
public void synchronizeAllUsers() {
|
||||||
waitAjaxForElement(synchronizeAllUsersButton);
|
waitUntilElement(synchronizeAllUsersButton).is().present();
|
||||||
synchronizeAllUsersButton.click();
|
synchronizeAllUsersButton.click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import org.keycloak.testsuite.console.page.AdminConsoleRealm;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.support.ui.Select;
|
import org.openqa.selenium.support.ui.Select;
|
||||||
|
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by fkiss.
|
* Created by fkiss.
|
||||||
|
@ -21,7 +21,7 @@ public class UserFederation extends AdminConsoleRealm {
|
||||||
private Select addProviderSelect;
|
private Select addProviderSelect;
|
||||||
|
|
||||||
public void addProvider(String provider) {
|
public void addProvider(String provider) {
|
||||||
waitGuiForElement(By.cssSelector("select[ng-model*='selectedProvider']"));
|
waitUntilElement(By.cssSelector("select[ng-model*='selectedProvider']")).is().present();
|
||||||
addProviderSelect.selectByVisibleText(provider);
|
addProviderSelect.selectByVisibleText(provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* JBoss, Home of Professional Open Source
|
||||||
|
*
|
||||||
|
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
|
||||||
|
*
|
||||||
|
* 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.console.page.fragment;
|
||||||
|
|
||||||
|
import org.keycloak.testsuite.page.AbstractAlert;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Petr Mensik
|
||||||
|
* @author tkyjovsk
|
||||||
|
*/
|
||||||
|
public class AdminConsoleAlert extends AbstractAlert {
|
||||||
|
|
||||||
|
@FindBy(xpath = "//button[@class='close']")
|
||||||
|
protected WebElement closeButton;
|
||||||
|
|
||||||
|
public boolean isInfo() {
|
||||||
|
return getAttributeClass().contains("alert-info");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWarning() {
|
||||||
|
return getAttributeClass().contains("alert-warning");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isDanger() {
|
||||||
|
return getAttributeClass().contains("alert-danger");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
closeButton.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -7,7 +7,8 @@ import org.openqa.selenium.support.FindBy;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.pause;
|
import static org.keycloak.testsuite.util.WaitUtils.pause;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
|
import org.openqa.selenium.By;
|
||||||
import static org.openqa.selenium.By.xpath;
|
import static org.openqa.selenium.By.xpath;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,18 +33,18 @@ public class DataTable {
|
||||||
private WebElement infoRow;
|
private WebElement infoRow;
|
||||||
|
|
||||||
public void search(String pattern) {
|
public void search(String pattern) {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
searchInput.sendKeys(pattern);
|
searchInput.sendKeys(pattern);
|
||||||
searchButton.click();
|
searchButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clickHeaderButton(String buttonText) {
|
public void clickHeaderButton(String buttonText) {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
header.findElement(By.xpath(".//button[text()='" + buttonText + "']")).click();
|
header.findElement(By.xpath(".//button[text()='" + buttonText + "']")).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clickHeaderLink(String linkText) {
|
public void clickHeaderLink(String linkText) {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
header.findElement(By.linkText(linkText)).click();
|
header.findElement(By.linkText(linkText)).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,19 +52,19 @@ public class DataTable {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitAjaxForBody() {
|
public void waitForBody() {
|
||||||
waitAjaxForElement(body);
|
waitUntilElement(body).is().present();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<WebElement> rows() {
|
public List<WebElement> rows() {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
pause(250);
|
pause(250);
|
||||||
return rows;
|
return rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebElement getRowByLinkText(String text) {
|
public WebElement getRowByLinkText(String text) {
|
||||||
WebElement row = body.findElement(By.xpath(".//tr[./td/a[text()='" + text + "']]"));
|
WebElement row = body.findElement(By.xpath(".//tr[./td/a[text()='" + text + "']]"));
|
||||||
waitAjaxForElement(row);
|
waitUntilElement(row).is().present();
|
||||||
return row;
|
return row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,66 +0,0 @@
|
||||||
/*
|
|
||||||
* JBoss, Home of Professional Open Source
|
|
||||||
*
|
|
||||||
* Copyright 2013 Red Hat, Inc. and/or its affiliates.
|
|
||||||
*
|
|
||||||
* 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.console.page.fragment;
|
|
||||||
|
|
||||||
import static org.jboss.arquillian.graphene.Graphene.waitGui;
|
|
||||||
import org.jboss.arquillian.graphene.fragment.Root;
|
|
||||||
|
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElementPresent;
|
|
||||||
import org.openqa.selenium.WebElement;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Petr Mensik
|
|
||||||
*/
|
|
||||||
public class FlashMessage {
|
|
||||||
|
|
||||||
@Root
|
|
||||||
private WebElement root;
|
|
||||||
|
|
||||||
public boolean isSuccess() {
|
|
||||||
waitGui().until("Flash message should be success")
|
|
||||||
.element(root)
|
|
||||||
.attribute("class")
|
|
||||||
.contains("success");
|
|
||||||
return root.getAttribute("class").contains("success");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isError() {
|
|
||||||
waitGui().until("Flash message should be error")
|
|
||||||
.element(root)
|
|
||||||
.attribute("class")
|
|
||||||
.contains("error");
|
|
||||||
return root.getAttribute("class").contains("error");
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDanger() {
|
|
||||||
waitGui().until("Flash message should be danger")
|
|
||||||
.element(root)
|
|
||||||
.attribute("class")
|
|
||||||
.contains("danger");
|
|
||||||
return root.getAttribute("class").contains("danger");
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getText() {
|
|
||||||
return root.getText();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void waitUntilPresent() {
|
|
||||||
waitGuiForElementPresent(root, "Flash message should be visible.");
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -18,7 +18,7 @@
|
||||||
package org.keycloak.testsuite.console.page.fragment;
|
package org.keycloak.testsuite.console.page.fragment;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
|
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
|
@ -53,7 +53,7 @@ public class Menu {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getCurrentRealm() {
|
public String getCurrentRealm() {
|
||||||
waitGuiForElement(By.cssSelector(MENU_LOCATOR));
|
waitUntilElement(By.cssSelector(MENU_LOCATOR)).is().present();
|
||||||
return toggle.get(1).getText();
|
return toggle.get(1).getText();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ public class Menu {
|
||||||
menuOrder = 0;
|
menuOrder = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
waitGuiForElement(By.cssSelector(MENU_LOCATOR));
|
waitUntilElement(By.cssSelector(MENU_LOCATOR)).is().present();
|
||||||
if (!menuList.get(menuOrder).isDisplayed()) {
|
if (!menuList.get(menuOrder).isDisplayed()) {
|
||||||
toggle.get(menuOrder).click();
|
toggle.get(menuOrder).click();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package org.keycloak.testsuite.console.page.fragment;
|
package org.keycloak.testsuite.console.page.fragment;
|
||||||
|
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
|
@ -21,22 +21,22 @@ public class ModalDialog {
|
||||||
private WebElement nameInput;
|
private WebElement nameInput;
|
||||||
|
|
||||||
public void ok() {
|
public void ok() {
|
||||||
waitAjaxForElement(okButton);
|
waitUntilElement(okButton).is().present();
|
||||||
okButton.click();
|
okButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void confirmDeletion() {
|
public void confirmDeletion() {
|
||||||
waitAjaxForElement(deleteButton);
|
waitUntilElement(deleteButton).is().present();
|
||||||
deleteButton.click();
|
deleteButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
waitAjaxForElement(cancelButton);
|
waitUntilElement(cancelButton).is().present();
|
||||||
cancelButton.click();
|
cancelButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setName(String name) {
|
public void setName(String name) {
|
||||||
waitAjaxForElement(nameInput);
|
waitUntilElement(nameInput).is().present();
|
||||||
nameInput.clear();
|
nameInput.clear();
|
||||||
nameInput.sendKeys(name);
|
nameInput.sendKeys(name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ package org.keycloak.testsuite.console.page.fragment;
|
||||||
|
|
||||||
import org.jboss.arquillian.graphene.fragment.Root;
|
import org.jboss.arquillian.graphene.fragment.Root;
|
||||||
import org.jboss.arquillian.test.api.ArquillianResource;
|
import org.jboss.arquillian.test.api.ArquillianResource;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.interactions.Actions;
|
import org.openqa.selenium.interactions.Actions;
|
||||||
|
@ -45,12 +45,12 @@ public class OnOffSwitch {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOn() {
|
public boolean isOn() {
|
||||||
waitAjaxForElement(root);
|
waitUntilElement(root).is().present();
|
||||||
return root.findElement(By.tagName("input")).isSelected();
|
return root.findElement(By.tagName("input")).isSelected();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void click() {
|
private void click() {
|
||||||
waitAjaxForElement(root);
|
waitUntilElement(root).is().present();
|
||||||
actions.moveToElement(root.findElements(By.tagName("span")).get(0))
|
actions.moveToElement(root.findElements(By.tagName("span")).get(0))
|
||||||
.click().build().perform();
|
.click().build().perform();
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ package org.keycloak.testsuite.console.page.realm;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
import org.openqa.selenium.support.ui.Select;
|
import org.openqa.selenium.support.ui.Select;
|
||||||
|
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,7 +47,7 @@ public class ThemeSettings extends RealmSettings {
|
||||||
private Select emailThemeSelect;
|
private Select emailThemeSelect;
|
||||||
|
|
||||||
public void changeLoginTheme(String themeName) {
|
public void changeLoginTheme(String themeName) {
|
||||||
waitGuiForElement(By.id("loginTheme"));
|
waitUntilElement(By.id("loginTheme")).is().present();
|
||||||
loginThemeSelect.selectByVisibleText(themeName);
|
loginThemeSelect.selectByVisibleText(themeName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ import org.openqa.selenium.support.FindBy;
|
||||||
import org.openqa.selenium.support.ui.Select;
|
import org.openqa.selenium.support.ui.Select;
|
||||||
|
|
||||||
import static java.lang.String.valueOf;
|
import static java.lang.String.valueOf;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import static org.apache.commons.lang3.text.WordUtils.capitalize;
|
import static org.apache.commons.lang3.text.WordUtils.capitalize;
|
||||||
import org.jboss.arquillian.graphene.page.Page;
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
import org.keycloak.testsuite.page.Form;
|
import org.keycloak.testsuite.page.Form;
|
||||||
|
@ -70,7 +70,7 @@ public class TokenSettings extends RealmSettings {
|
||||||
|
|
||||||
private void setTimeout(Select timeoutElement, WebElement unitElement,
|
private void setTimeout(Select timeoutElement, WebElement unitElement,
|
||||||
int timeout, TimeUnit unit) {
|
int timeout, TimeUnit unit) {
|
||||||
waitGuiForElement(sessionTimeout);
|
waitUntilElement(sessionTimeout).is().present();
|
||||||
timeoutElement.selectByValue(capitalize(unit.name().toLowerCase()));
|
timeoutElement.selectByValue(capitalize(unit.name().toLowerCase()));
|
||||||
unitElement.clear();
|
unitElement.clear();
|
||||||
unitElement.sendKeys(valueOf(timeout));
|
unitElement.sendKeys(valueOf(timeout));
|
||||||
|
|
|
@ -9,7 +9,7 @@ import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import org.keycloak.representations.idm.RoleRepresentation.Composites;
|
import org.keycloak.representations.idm.RoleRepresentation.Composites;
|
||||||
import org.keycloak.testsuite.page.Form;
|
import org.keycloak.testsuite.page.Form;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitGuiForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
@ -127,7 +127,7 @@ public class RoleCompositeRoles extends Form {
|
||||||
|
|
||||||
// *** original methods ***
|
// *** original methods ***
|
||||||
public void addAvailableRole(String... roles) {
|
public void addAvailableRole(String... roles) {
|
||||||
waitGuiForElement(By.id("available"));
|
waitUntilElement(By.id("available")).is().present();
|
||||||
for (String role : roles) {
|
for (String role : roles) {
|
||||||
availableRealmRolesSelect.selectByVisibleText(role);
|
availableRealmRolesSelect.selectByVisibleText(role);
|
||||||
addSelectedRealmRolesButton.click();
|
addSelectedRealmRolesButton.click();
|
||||||
|
@ -135,13 +135,13 @@ public class RoleCompositeRoles extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAssignedRole(String role) {
|
public void removeAssignedRole(String role) {
|
||||||
waitGuiForElement(By.id("assigned"));
|
waitUntilElement(By.id("assigned")).is().present();
|
||||||
assignedRealmRolesSelect.selectByVisibleText(role);
|
assignedRealmRolesSelect.selectByVisibleText(role);
|
||||||
removeSelectedRealmRolesButton.click();
|
removeSelectedRealmRolesButton.click();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAssignedRole(String role) {
|
public boolean isAssignedRole(String role) {
|
||||||
waitGuiForElement(By.id("assigned"));
|
waitUntilElement(By.id("assigned")).is().present();
|
||||||
try {
|
try {
|
||||||
assignedRealmRolesSelect.selectByVisibleText(role);
|
assignedRealmRolesSelect.selectByVisibleText(role);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -151,7 +151,7 @@ public class RoleCompositeRoles extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isAssignedClientRole(String role) {
|
public boolean isAssignedClientRole(String role) {
|
||||||
waitGuiForElement(By.id("assigned"));
|
waitUntilElement(By.id("assigned")).is().present();
|
||||||
try {
|
try {
|
||||||
assignedClientRolesSelect.selectByVisibleText(role);
|
assignedClientRolesSelect.selectByVisibleText(role);
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
|
@ -161,12 +161,12 @@ public class RoleCompositeRoles extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectClientRole(String client) {
|
public void selectClientRole(String client) {
|
||||||
waitGuiForElement(By.id("clients"));
|
waitUntilElement(By.id("clients")).is().present();
|
||||||
clientSelect.selectByVisibleText(client);
|
clientSelect.selectByVisibleText(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addAvailableClientRole(String... roles) {
|
public void addAvailableClientRole(String... roles) {
|
||||||
waitGuiForElement(By.id("available-client"));
|
waitUntilElement(By.id("available-client")).is().present();
|
||||||
for (String role : roles) {
|
for (String role : roles) {
|
||||||
availableClientRolesSelect.selectByVisibleText(role);
|
availableClientRolesSelect.selectByVisibleText(role);
|
||||||
addSelectedClientRolesButton.click();
|
addSelectedClientRolesButton.click();
|
||||||
|
@ -174,7 +174,7 @@ public class RoleCompositeRoles extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeAssignedClientRole(String client) {
|
public void removeAssignedClientRole(String client) {
|
||||||
waitGuiForElement(By.id("assigned-client"));
|
waitUntilElement(By.id("assigned-client")).is().present();
|
||||||
assignedClientRolesSelect.selectByVisibleText(client);
|
assignedClientRolesSelect.selectByVisibleText(client);
|
||||||
removeSelectedClientRolesButton.click();
|
removeSelectedClientRolesButton.click();
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,7 @@ public class RolesTable extends DataTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clickRole(String name) {
|
public void clickRole(String name) {
|
||||||
waitAjaxForBody();
|
waitForBody();
|
||||||
clickRowByLinkText(name);
|
clickRowByLinkText(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import java.util.List;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
|
import org.keycloak.testsuite.console.page.fragment.OnOffSwitch;
|
||||||
import org.keycloak.testsuite.page.Form;
|
import org.keycloak.testsuite.page.Form;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
import org.openqa.selenium.support.ui.Select;
|
import org.openqa.selenium.support.ui.Select;
|
||||||
|
@ -125,7 +125,7 @@ public class UserAttributesForm extends Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValues(UserRepresentation user) {
|
public void setValues(UserRepresentation user) {
|
||||||
waitAjaxForElement(usernameInput);
|
waitUntilElement(usernameInput).is().present();
|
||||||
setUsername(user.getUsername());
|
setUsername(user.getUsername());
|
||||||
setEmail(user.getEmail());
|
setEmail(user.getEmail());
|
||||||
setFirstName(user.getFirstName());
|
setFirstName(user.getFirstName());
|
||||||
|
|
|
@ -27,7 +27,7 @@ import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
|
||||||
import org.keycloak.testsuite.console.page.AdminConsoleRealm;
|
import org.keycloak.testsuite.console.page.AdminConsoleRealm;
|
||||||
import org.keycloak.testsuite.console.page.fragment.DataTable;
|
import org.keycloak.testsuite.console.page.fragment.DataTable;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import static org.openqa.selenium.By.*;
|
import static org.openqa.selenium.By.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,7 +73,7 @@ public class Users extends AdminConsoleRealm {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clickUser(String username) {
|
public void clickUser(String username) {
|
||||||
waitAjaxForElement(body());
|
waitUntilElement(body()).is().present();
|
||||||
body().findElement(linkText(username)).click();
|
body().findElement(linkText(username)).click();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
package org.keycloak.testsuite.page;
|
||||||
|
|
||||||
|
import com.google.common.base.Predicate;
|
||||||
|
import static org.jboss.arquillian.graphene.Graphene.waitModel;
|
||||||
|
import org.jboss.arquillian.graphene.fragment.Root;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
|
import org.openqa.selenium.WebDriver;
|
||||||
|
import org.openqa.selenium.WebElement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author tkyjovsk
|
||||||
|
*/
|
||||||
|
public abstract class AbstractAlert {
|
||||||
|
|
||||||
|
protected final Logger log = Logger.getLogger(this.getClass());
|
||||||
|
|
||||||
|
@Root
|
||||||
|
protected WebElement root;
|
||||||
|
|
||||||
|
public void waitUntilPresent() {
|
||||||
|
waitUntilElement(root, "Flash message should be present.").is().present();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void waitUntilPresentAndClassSet() {
|
||||||
|
waitUntilPresent();
|
||||||
|
waitModel().until(new Predicate<WebDriver>() {
|
||||||
|
@Override
|
||||||
|
public boolean apply(WebDriver input) {
|
||||||
|
return !getAttributeClass().endsWith("alert-");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return root.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttributeClass() {
|
||||||
|
String attrClass = root.getAttribute("class");
|
||||||
|
log.debug("Alert @class = '" + attrClass + "'");
|
||||||
|
return attrClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
log.debug("Alert.isSuccess()");
|
||||||
|
return getAttributeClass().contains("alert-success");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -3,7 +3,7 @@ package org.keycloak.testsuite.page;
|
||||||
import org.jboss.arquillian.drone.api.annotation.Drone;
|
import org.jboss.arquillian.drone.api.annotation.Drone;
|
||||||
import static org.jboss.arquillian.graphene.Graphene.guardAjax;
|
import static org.jboss.arquillian.graphene.Graphene.guardAjax;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import static org.keycloak.testsuite.util.WaitUtils.waitAjaxForElement;
|
import static org.keycloak.testsuite.util.WaitUtils.waitUntilElement;
|
||||||
import org.openqa.selenium.WebDriver;
|
import org.openqa.selenium.WebDriver;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
import org.openqa.selenium.support.FindBy;
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
@ -36,14 +36,14 @@ public class Form {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getInputValue(WebElement input) {
|
public static String getInputValue(WebElement input) {
|
||||||
waitAjaxForElement(input);
|
waitUntilElement(input).is().present();
|
||||||
return input.getAttribute(VALUE);
|
return input.getAttribute(VALUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String VALUE = "value";
|
public static final String VALUE = "value";
|
||||||
|
|
||||||
public static void setInputValue(WebElement input, String value) {
|
public static void setInputValue(WebElement input, String value) {
|
||||||
waitAjaxForElement(input);
|
waitUntilElement(input).is().present();
|
||||||
if (input.isEnabled()) {
|
if (input.isEnabled()) {
|
||||||
input.clear();
|
input.clear();
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
|
|
|
@ -17,11 +17,10 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.testsuite.util;
|
package org.keycloak.testsuite.util;
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import static org.jboss.arquillian.graphene.Graphene.waitAjax;
|
|
||||||
import static org.jboss.arquillian.graphene.Graphene.waitGui;
|
import static org.jboss.arquillian.graphene.Graphene.waitGui;
|
||||||
|
import org.jboss.arquillian.graphene.wait.ElementBuilder;
|
||||||
import org.openqa.selenium.By;
|
import org.openqa.selenium.By;
|
||||||
import org.openqa.selenium.WebElement;
|
import org.openqa.selenium.WebElement;
|
||||||
|
|
||||||
|
@ -33,52 +32,19 @@ import org.openqa.selenium.WebElement;
|
||||||
public final class WaitUtils {
|
public final class WaitUtils {
|
||||||
|
|
||||||
public static final String PAGELOAD_TIMEOUT_PROP = "pageload.timeout";
|
public static final String PAGELOAD_TIMEOUT_PROP = "pageload.timeout";
|
||||||
public static final String IMPLICIT_TIMEOUT_PROP = "implicit.timeout";
|
|
||||||
public static final String SCRIPT_TIMEOUT_PROP = "script.timeout";
|
|
||||||
public static final String POLLING_INTERVAL_PROP = "polling.interval";
|
|
||||||
|
|
||||||
public static final Integer PAGELOAD_TIMEOUT = Integer.parseInt(System.getProperty(PAGELOAD_TIMEOUT_PROP, "5000"));
|
public static final Integer PAGELOAD_TIMEOUT = Integer.parseInt(System.getProperty(PAGELOAD_TIMEOUT_PROP, "60000"));
|
||||||
public static final Integer IMPLICIT_TIMEOUT = Integer.parseInt(System.getProperty(IMPLICIT_TIMEOUT_PROP, "3000"));
|
|
||||||
public static final Integer SCRIPT_TIMEOUT = Integer.parseInt(System.getProperty(SCRIPT_TIMEOUT_PROP, "3000"));
|
|
||||||
|
|
||||||
public static final Integer POLLING_INTERVAL = Integer.parseInt(System.getProperty(POLLING_INTERVAL_PROP, "1000"));
|
public static ElementBuilder<Void> waitUntilElement(By by) {
|
||||||
|
return waitGui().until().element(by);
|
||||||
public static void waitAjaxForElement(WebElement element) {
|
|
||||||
waitAjax().withTimeout(SCRIPT_TIMEOUT, TimeUnit.MILLISECONDS).pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
|
|
||||||
.until().element(element).is().present();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void waitAjaxForElementNotPresent(WebElement element) {
|
public static ElementBuilder<Void> waitUntilElement(WebElement element) {
|
||||||
waitAjax().withTimeout(SCRIPT_TIMEOUT, TimeUnit.MILLISECONDS).pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
|
return waitGui().until().element(element);
|
||||||
.until().element(element).is().not().present();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void waitAjaxForElementNotVisible(WebElement element) {
|
public static ElementBuilder<Void> waitUntilElement(WebElement element, String failMessage) {
|
||||||
waitAjax().withTimeout(SCRIPT_TIMEOUT, TimeUnit.MILLISECONDS).pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
|
return waitGui().until(failMessage).element(element);
|
||||||
.until().element(element).is().not().visible();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void waitGuiForElement(By element, String message) {
|
|
||||||
waitGui().withTimeout(IMPLICIT_TIMEOUT, TimeUnit.MILLISECONDS).pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
|
|
||||||
.until(message).element(element).is().present();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void waitGuiForElement(By element) {
|
|
||||||
waitGuiForElement(element, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void waitGuiForElement(WebElement element) {
|
|
||||||
waitGuiForElementPresent(element, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void waitGuiForElementPresent(WebElement element, String message) {
|
|
||||||
waitGui().withTimeout(IMPLICIT_TIMEOUT, TimeUnit.MILLISECONDS).pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
|
|
||||||
.until(message).element(element).is().present();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void waitGuiForElementNotPresent(WebElement element) {
|
|
||||||
waitGui().withTimeout(IMPLICIT_TIMEOUT, TimeUnit.MILLISECONDS).pollingEvery(POLLING_INTERVAL, TimeUnit.MILLISECONDS)
|
|
||||||
.until().element(element).is().not().present();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void pause(long millis) {
|
public static void pause(long millis) {
|
||||||
|
|
|
@ -19,9 +19,7 @@ package org.keycloak.testsuite;
|
||||||
|
|
||||||
import java.text.MessageFormat;
|
import java.text.MessageFormat;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
|
||||||
import org.jboss.arquillian.graphene.page.Page;
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.keycloak.admin.client.resource.RealmResource;
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
import static org.keycloak.representations.idm.CredentialRepresentation.PASSWORD;
|
import static org.keycloak.representations.idm.CredentialRepresentation.PASSWORD;
|
||||||
|
@ -32,7 +30,6 @@ import static org.keycloak.testsuite.admin.Users.setPasswordFor;
|
||||||
import org.keycloak.testsuite.auth.page.AuthRealm;
|
import org.keycloak.testsuite.auth.page.AuthRealm;
|
||||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||||
import org.keycloak.testsuite.auth.page.login.OIDCLogin;
|
import org.keycloak.testsuite.auth.page.login.OIDCLogin;
|
||||||
import org.keycloak.testsuite.console.page.fragment.FlashMessage;
|
|
||||||
import org.openqa.selenium.Cookie;
|
import org.openqa.selenium.Cookie;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -48,9 +45,6 @@ public abstract class AbstractAuthTest extends AbstractKeycloakTest {
|
||||||
|
|
||||||
protected UserRepresentation testUser;
|
protected UserRepresentation testUser;
|
||||||
|
|
||||||
@FindByJQuery(".alert")
|
|
||||||
protected FlashMessage flashMessage;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
public void addTestRealms(List<RealmRepresentation> testRealms) {
|
||||||
RealmRepresentation testRealmRep = new RealmRepresentation();
|
RealmRepresentation testRealmRep = new RealmRepresentation();
|
||||||
|
@ -101,21 +95,6 @@ public abstract class AbstractAuthTest extends AbstractKeycloakTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertFlashMessageSuccess() {
|
|
||||||
flashMessage.waitUntilPresent();
|
|
||||||
assertTrue(flashMessage.getText(), flashMessage.isSuccess());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void assertFlashMessageDanger() {
|
|
||||||
flashMessage.waitUntilPresent();
|
|
||||||
assertTrue(flashMessage.getText(), flashMessage.isDanger());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void assertFlashMessageError() {
|
|
||||||
flashMessage.waitUntilPresent();
|
|
||||||
assertTrue(flashMessage.getText(), flashMessage.isError());
|
|
||||||
}
|
|
||||||
|
|
||||||
public RealmResource testRealmResource() {
|
public RealmResource testRealmResource() {
|
||||||
return adminClient.realm(testRealmPage.getAuthRealm());
|
return adminClient.realm(testRealmPage.getAuthRealm());
|
||||||
}
|
}
|
||||||
|
|
|
@ -118,8 +118,6 @@ public abstract class AbstractKeycloakTest {
|
||||||
|
|
||||||
protected void driverSettings() {
|
protected void driverSettings() {
|
||||||
driver.manage().timeouts().pageLoadTimeout(WaitUtils.PAGELOAD_TIMEOUT, TimeUnit.MILLISECONDS);
|
driver.manage().timeouts().pageLoadTimeout(WaitUtils.PAGELOAD_TIMEOUT, TimeUnit.MILLISECONDS);
|
||||||
driver.manage().timeouts().implicitlyWait(WaitUtils.IMPLICIT_TIMEOUT, TimeUnit.MILLISECONDS);
|
|
||||||
driver.manage().timeouts().setScriptTimeout(WaitUtils.SCRIPT_TIMEOUT, TimeUnit.MILLISECONDS);
|
|
||||||
driver.manage().window().maximize();
|
driver.manage().window().maximize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,13 @@
|
||||||
package org.keycloak.testsuite.account;
|
package org.keycloak.testsuite.account;
|
||||||
|
|
||||||
import org.jboss.arquillian.graphene.page.Page;
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.keycloak.testsuite.AbstractAuthTest;
|
import org.keycloak.testsuite.AbstractAuthTest;
|
||||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||||
import org.keycloak.testsuite.auth.page.account.AccountManagement;
|
import org.keycloak.testsuite.auth.page.account.AccountManagement;
|
||||||
|
import org.keycloak.testsuite.auth.page.account.fragment.AccountManagementAlert;
|
||||||
|
import org.openqa.selenium.support.FindBy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -15,6 +18,9 @@ public abstract class AbstractAccountManagementTest extends AbstractAuthTest {
|
||||||
@Page
|
@Page
|
||||||
protected AccountManagement testRealmAccountManagementPage;
|
protected AccountManagement testRealmAccountManagementPage;
|
||||||
|
|
||||||
|
@FindBy(className = "alert")
|
||||||
|
protected AccountManagementAlert alert;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setDefaultPageUriParameters() {
|
public void setDefaultPageUriParameters() {
|
||||||
super.setDefaultPageUriParameters();
|
super.setDefaultPageUriParameters();
|
||||||
|
@ -28,4 +34,14 @@ public abstract class AbstractAccountManagementTest extends AbstractAuthTest {
|
||||||
createTestUserWithAdminClient();
|
createTestUserWithAdminClient();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void assertAlertSuccess() {
|
||||||
|
alert.waitUntilPresentAndClassSet();
|
||||||
|
assertTrue(alert.isSuccess());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertAlertError() {
|
||||||
|
alert.waitUntilPresentAndClassSet();
|
||||||
|
assertTrue(alert.isError());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,7 @@ public class AccountTest extends AbstractAccountManagementTest {
|
||||||
testRealmAccountPage.setFirstName(NEW_FIRST_NAME);
|
testRealmAccountPage.setFirstName(NEW_FIRST_NAME);
|
||||||
testRealmAccountPage.setLastName(NEW_LAST_NAME);
|
testRealmAccountPage.setLastName(NEW_LAST_NAME);
|
||||||
testRealmAccountPage.save();
|
testRealmAccountPage.save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
testRealmAccountManagementPage.signOut();
|
testRealmAccountManagementPage.signOut();
|
||||||
testRealmLoginPage.form().login(testUser);
|
testRealmLoginPage.form().login(testUser);
|
||||||
|
|
|
@ -38,20 +38,20 @@ public class ChangePasswordTest extends AbstractAccountManagementTest {
|
||||||
@Test
|
@Test
|
||||||
public void invalidChangeAttempts() {
|
public void invalidChangeAttempts() {
|
||||||
testRealmChangePasswordPage.save();
|
testRealmChangePasswordPage.save();
|
||||||
assertFlashMessageError();
|
assertAlertError();
|
||||||
|
|
||||||
testRealmChangePasswordPage.changePasswords(WRONG_PASSWORD, NEW_PASSWORD, NEW_PASSWORD);
|
testRealmChangePasswordPage.changePasswords(WRONG_PASSWORD, NEW_PASSWORD, NEW_PASSWORD);
|
||||||
assertFlashMessageError();
|
assertAlertError();
|
||||||
|
|
||||||
testRealmChangePasswordPage.changePasswords(correctPassword, NEW_PASSWORD, NEW_PASSWORD + "-mismatch");
|
testRealmChangePasswordPage.changePasswords(correctPassword, NEW_PASSWORD, NEW_PASSWORD + "-mismatch");
|
||||||
assertFlashMessageError();
|
assertAlertError();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void successfulChangeAttempts() {
|
public void successfulChangeAttempts() {
|
||||||
// change password successfully
|
// change password successfully
|
||||||
testRealmChangePasswordPage.changePasswords(correctPassword, NEW_PASSWORD, NEW_PASSWORD);
|
testRealmChangePasswordPage.changePasswords(correctPassword, NEW_PASSWORD, NEW_PASSWORD);
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
// login using new password
|
// login using new password
|
||||||
testRealmAccountManagementPage.signOut();
|
testRealmAccountManagementPage.signOut();
|
||||||
|
@ -61,7 +61,7 @@ public class ChangePasswordTest extends AbstractAccountManagementTest {
|
||||||
// change password back
|
// change password back
|
||||||
testRealmAccountManagementPage.password();
|
testRealmAccountManagementPage.password();
|
||||||
testRealmChangePasswordPage.changePasswords(NEW_PASSWORD, correctPassword, correctPassword);
|
testRealmChangePasswordPage.changePasswords(NEW_PASSWORD, correctPassword, correctPassword);
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.testsuite.console;
|
package org.keycloak.testsuite.console;
|
||||||
|
|
||||||
|
import org.jboss.arquillian.graphene.findby.FindByJQuery;
|
||||||
import org.jboss.arquillian.graphene.page.Page;
|
import org.jboss.arquillian.graphene.page.Page;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
import org.keycloak.testsuite.AbstractAuthTest;
|
import org.keycloak.testsuite.AbstractAuthTest;
|
||||||
|
@ -27,6 +29,7 @@ import org.keycloak.testsuite.console.page.AdminConsoleRealm.ConfigureMenu;
|
||||||
import org.keycloak.testsuite.console.page.AdminConsoleRealm.ManageMenu;
|
import org.keycloak.testsuite.console.page.AdminConsoleRealm.ManageMenu;
|
||||||
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
import static org.keycloak.testsuite.auth.page.AuthRealm.TEST;
|
||||||
import org.keycloak.testsuite.auth.page.login.Login;
|
import org.keycloak.testsuite.auth.page.login.Login;
|
||||||
|
import org.keycloak.testsuite.console.page.fragment.AdminConsoleAlert;
|
||||||
import org.keycloak.testsuite.console.page.fragment.ModalDialog;
|
import org.keycloak.testsuite.console.page.fragment.ModalDialog;
|
||||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
|
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWithLoginUrlOf;
|
||||||
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
import static org.keycloak.testsuite.util.URLAssert.assertCurrentUrlStartsWith;
|
||||||
|
@ -50,6 +53,9 @@ public abstract class AbstractConsoleTest extends AbstractAuthTest {
|
||||||
@FindBy(xpath = "//div[@class='modal-dialog']")
|
@FindBy(xpath = "//div[@class='modal-dialog']")
|
||||||
protected ModalDialog modalDialog;
|
protected ModalDialog modalDialog;
|
||||||
|
|
||||||
|
@FindBy(className = "alert")
|
||||||
|
protected AdminConsoleAlert alert;
|
||||||
|
|
||||||
protected boolean adminLoggedIn = false;
|
protected boolean adminLoggedIn = false;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -100,6 +106,18 @@ public abstract class AbstractConsoleTest extends AbstractAuthTest {
|
||||||
assertCurrentUrlStartsWithLoginUrlOf(adminConsole);
|
assertCurrentUrlStartsWithLoginUrlOf(adminConsole);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void assertAlertSuccess() {
|
||||||
|
alert.waitUntilPresentAndClassSet();
|
||||||
|
assertTrue(alert.isSuccess());
|
||||||
|
alert.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void assertAlertDanger() {
|
||||||
|
alert.waitUntilPresentAndClassSet();
|
||||||
|
assertTrue(alert.isDanger());
|
||||||
|
alert.close();
|
||||||
|
}
|
||||||
|
|
||||||
public ConfigureMenu configure() {
|
public ConfigureMenu configure() {
|
||||||
return adminConsoleRealmPage.configure();
|
return adminConsoleRealmPage.configure();
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,18 +50,18 @@ public class PasswordPolicyTest extends AbstractConsoleTest {
|
||||||
passwordPolicyPage.navigateTo();
|
passwordPolicyPage.navigateTo();
|
||||||
passwordPolicyPage.addPolicy(HASH_ITERATIONS, 5);
|
passwordPolicyPage.addPolicy(HASH_ITERATIONS, 5);
|
||||||
passwordPolicyPage.removePolicy(HASH_ITERATIONS);
|
passwordPolicyPage.removePolicy(HASH_ITERATIONS);
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testInvalidPolicyValues() {
|
public void testInvalidPolicyValues() {
|
||||||
passwordPolicyPage.navigateTo();
|
passwordPolicyPage.navigateTo();
|
||||||
passwordPolicyPage.addPolicy(HASH_ITERATIONS, "asd");
|
passwordPolicyPage.addPolicy(HASH_ITERATIONS, "asd");
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
passwordPolicyPage.removePolicy(HASH_ITERATIONS);
|
passwordPolicyPage.removePolicy(HASH_ITERATIONS);
|
||||||
|
|
||||||
passwordPolicyPage.addPolicy(REGEX_PATTERN, "([");
|
passwordPolicyPage.addPolicy(REGEX_PATTERN, "([");
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -72,10 +72,10 @@ public class PasswordPolicyTest extends AbstractConsoleTest {
|
||||||
|
|
||||||
testUserCredentialsPage.navigateTo();
|
testUserCredentialsPage.navigateTo();
|
||||||
testUserCredentialsPage.resetPassword("1234567");
|
testUserCredentialsPage.resetPassword("1234567");
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
|
|
||||||
testUserCredentialsPage.resetPassword("12345678");
|
testUserCredentialsPage.resetPassword("12345678");
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -86,10 +86,10 @@ public class PasswordPolicyTest extends AbstractConsoleTest {
|
||||||
|
|
||||||
testUserCredentialsPage.navigateTo();
|
testUserCredentialsPage.navigateTo();
|
||||||
testUserCredentialsPage.resetPassword("invalidPassword1");
|
testUserCredentialsPage.resetPassword("invalidPassword1");
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
|
|
||||||
testUserCredentialsPage.resetPassword("validPassword12");
|
testUserCredentialsPage.resetPassword("validPassword12");
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -100,10 +100,10 @@ public class PasswordPolicyTest extends AbstractConsoleTest {
|
||||||
|
|
||||||
testUserCredentialsPage.navigateTo();
|
testUserCredentialsPage.navigateTo();
|
||||||
testUserCredentialsPage.resetPassword("iNVALIDPASSWORD");
|
testUserCredentialsPage.resetPassword("iNVALIDPASSWORD");
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
|
|
||||||
testUserCredentialsPage.resetPassword("vaLIDPASSWORD");
|
testUserCredentialsPage.resetPassword("vaLIDPASSWORD");
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -114,10 +114,10 @@ public class PasswordPolicyTest extends AbstractConsoleTest {
|
||||||
|
|
||||||
testUserCredentialsPage.navigateTo();
|
testUserCredentialsPage.navigateTo();
|
||||||
testUserCredentialsPage.resetPassword("Invalidpassword");
|
testUserCredentialsPage.resetPassword("Invalidpassword");
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
|
|
||||||
testUserCredentialsPage.resetPassword("VAlidpassword");
|
testUserCredentialsPage.resetPassword("VAlidpassword");
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -128,10 +128,10 @@ public class PasswordPolicyTest extends AbstractConsoleTest {
|
||||||
|
|
||||||
testUserCredentialsPage.navigateTo();
|
testUserCredentialsPage.navigateTo();
|
||||||
testUserCredentialsPage.resetPassword("invalidPassword*");
|
testUserCredentialsPage.resetPassword("invalidPassword*");
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
|
|
||||||
testUserCredentialsPage.resetPassword("validPassword*#");
|
testUserCredentialsPage.resetPassword("validPassword*#");
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -142,10 +142,10 @@ public class PasswordPolicyTest extends AbstractConsoleTest {
|
||||||
|
|
||||||
testUserCredentialsPage.navigateTo();
|
testUserCredentialsPage.navigateTo();
|
||||||
testUserCredentialsPage.resetPassword(testUser.getUsername());
|
testUserCredentialsPage.resetPassword(testUser.getUsername());
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
|
|
||||||
testUserCredentialsPage.resetPassword("validpassword");
|
testUserCredentialsPage.resetPassword("validpassword");
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -156,10 +156,10 @@ public class PasswordPolicyTest extends AbstractConsoleTest {
|
||||||
|
|
||||||
testUserCredentialsPage.navigateTo();
|
testUserCredentialsPage.navigateTo();
|
||||||
testUserCredentialsPage.resetPassword("invalidPassword");
|
testUserCredentialsPage.resetPassword("invalidPassword");
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
|
|
||||||
testUserCredentialsPage.resetPassword("VALID#password");
|
testUserCredentialsPage.resetPassword("VALID#password");
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -170,13 +170,13 @@ public class PasswordPolicyTest extends AbstractConsoleTest {
|
||||||
|
|
||||||
testUserCredentialsPage.navigateTo();
|
testUserCredentialsPage.navigateTo();
|
||||||
testUserCredentialsPage.resetPassword("firstPassword");
|
testUserCredentialsPage.resetPassword("firstPassword");
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
testUserCredentialsPage.resetPassword("secondPassword");
|
testUserCredentialsPage.resetPassword("secondPassword");
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
testUserCredentialsPage.resetPassword("firstPassword");
|
testUserCredentialsPage.resetPassword("firstPassword");
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ public class RequiredActionsTest extends AbstractConsoleTest {
|
||||||
public void termsAndConditionsDefaultActionTest() {
|
public void termsAndConditionsDefaultActionTest() {
|
||||||
requiredActionsPage.setTermsAndConditionEnabled(true);
|
requiredActionsPage.setTermsAndConditionEnabled(true);
|
||||||
requiredActionsPage.setTermsAndConditionDefaultAction(true);
|
requiredActionsPage.setTermsAndConditionDefaultAction(true);
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
allowTestRealmUserRegistration();
|
allowTestRealmUserRegistration();
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ public class RequiredActionsTest extends AbstractConsoleTest {
|
||||||
@Test
|
@Test
|
||||||
public void configureTotpDefaultActionTest() {
|
public void configureTotpDefaultActionTest() {
|
||||||
requiredActionsPage.setConfigureTotpDefaultAction(true);
|
requiredActionsPage.setConfigureTotpDefaultAction(true);
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
allowTestRealmUserRegistration();
|
allowTestRealmUserRegistration();
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ public class ClientRolesTest extends AbstractClientTest {
|
||||||
// assertCurrentUrl(createClientRole); // can't do this, need client id to build uri
|
// assertCurrentUrl(createClientRole); // can't do this, need client id to build uri
|
||||||
createClientRolePage.form().setBasicAttributes(roleRep);
|
createClientRolePage.form().setBasicAttributes(roleRep);
|
||||||
createClientRolePage.form().save();
|
createClientRolePage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
createClientRolePage.form().setCompositeRoles(roleRep);
|
createClientRolePage.form().setCompositeRoles(roleRep);
|
||||||
// TODO add verification of notification message when KEYCLOAK-1497 gets resolved
|
// TODO add verification of notification message when KEYCLOAK-1497 gets resolved
|
||||||
}
|
}
|
||||||
|
@ -47,11 +47,10 @@ public class ClientRolesTest extends AbstractClientTest {
|
||||||
RoleRepresentation newRole = new RoleRepresentation("client-role", "", false);
|
RoleRepresentation newRole = new RoleRepresentation("client-role", "", false);
|
||||||
|
|
||||||
createClient(newClient);
|
createClient(newClient);
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
clientPage.tabs().roles();
|
clientPage.tabs().roles();
|
||||||
addClientRole(newRole);
|
addClientRole(newRole);
|
||||||
assertFlashMessageSuccess();
|
|
||||||
|
|
||||||
clientRolePage.backToClientRolesViaBreadcrumb();
|
clientRolePage.backToClientRolesViaBreadcrumb();
|
||||||
assertFalse(clientRolesPage.roles().getRolesFromTableRows().isEmpty());
|
assertFalse(clientRolesPage.roles().getRolesFromTableRows().isEmpty());
|
||||||
|
@ -60,7 +59,7 @@ public class ClientRolesTest extends AbstractClientTest {
|
||||||
clientsPage.table().search(newClient.getClientId());
|
clientsPage.table().search(newClient.getClientId());
|
||||||
clientsPage.table().deleteClient(newClient.getClientId());
|
clientsPage.table().deleteClient(newClient.getClientId());
|
||||||
modalDialog.confirmDeletion();
|
modalDialog.confirmDeletion();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
assertNull(clientsPage.table().findClient(newClient.getClientId()));
|
assertNull(clientsPage.table().findClient(newClient.getClientId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ public class ClientSettingsTest extends AbstractClientTest {
|
||||||
public void crudOIDCConfidential() {
|
public void crudOIDCConfidential() {
|
||||||
newClient = createClientRepresentation("oidc-confidential", "http://example.test/app/*");
|
newClient = createClientRepresentation("oidc-confidential", "http://example.test/app/*");
|
||||||
createClient(newClient);
|
createClient(newClient);
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
clientPage.backToClientsViaBreadcrumb();
|
clientPage.backToClientsViaBreadcrumb();
|
||||||
assertCurrentUrlEquals(clientsPage);
|
assertCurrentUrlEquals(clientsPage);
|
||||||
|
@ -70,7 +70,7 @@ public class ClientSettingsTest extends AbstractClientTest {
|
||||||
newClient = createClientRepresentation("oidc-public", "http://example.test/app/*");
|
newClient = createClientRepresentation("oidc-public", "http://example.test/app/*");
|
||||||
newClient.setPublicClient(true);
|
newClient.setPublicClient(true);
|
||||||
createClient(newClient);
|
createClient(newClient);
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
clientPage.backToClientsViaBreadcrumb();
|
clientPage.backToClientsViaBreadcrumb();
|
||||||
assertCurrentUrlEquals(clientsPage);
|
assertCurrentUrlEquals(clientsPage);
|
||||||
|
@ -81,7 +81,7 @@ public class ClientSettingsTest extends AbstractClientTest {
|
||||||
newClient = createClientRepresentation("oidc-bearer-only", "http://example.test/app/*");
|
newClient = createClientRepresentation("oidc-bearer-only", "http://example.test/app/*");
|
||||||
newClient.setBearerOnly(true);
|
newClient.setBearerOnly(true);
|
||||||
createClient(newClient);
|
createClient(newClient);
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
clientPage.backToClientsViaBreadcrumb();
|
clientPage.backToClientsViaBreadcrumb();
|
||||||
assertCurrentUrlEquals(clientsPage);
|
assertCurrentUrlEquals(clientsPage);
|
||||||
|
@ -99,11 +99,11 @@ public class ClientSettingsTest extends AbstractClientTest {
|
||||||
public void invalidSettings() {
|
public void invalidSettings() {
|
||||||
clientsPage.table().createClient();
|
clientsPage.table().createClient();
|
||||||
createClientPage.form().save();
|
createClientPage.form().save();
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
|
|
||||||
createClientPage.form().setClientId("test-client");
|
createClientPage.form().setClientId("test-client");
|
||||||
createClientPage.form().save();
|
createClientPage.form().save();
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void assertClientSettingsEqual(ClientRepresentation c1, ClientRepresentation c2) {
|
public void assertClientSettingsEqual(ClientRepresentation c1, ClientRepresentation c2) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class ConfigTest extends AbstractConsoleTest {
|
||||||
configPage.form().removeSaveType("LOGIN");
|
configPage.form().removeSaveType("LOGIN");
|
||||||
configPage.form().setExpiration("50", "Days");
|
configPage.form().setExpiration("50", "Days");
|
||||||
configPage.form().save();
|
configPage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||||
assertTrue(realm.isEventsEnabled());
|
assertTrue(realm.isEventsEnabled());
|
||||||
|
@ -44,7 +44,7 @@ public class ConfigTest extends AbstractConsoleTest {
|
||||||
configPage.form().setSaveAdminEvents(true);
|
configPage.form().setSaveAdminEvents(true);
|
||||||
configPage.form().setIncludeRepresentation(true);
|
configPage.form().setIncludeRepresentation(true);
|
||||||
configPage.form().save();
|
configPage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||||
assertTrue(realm.isAdminEventsEnabled());
|
assertTrue(realm.isAdminEventsEnabled());
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class KerberosUserFederationTest extends AbstractConsoleTest {
|
||||||
createKerberosUserProvider.form().selectEditMode(READ_ONLY);
|
createKerberosUserProvider.form().selectEditMode(READ_ONLY);
|
||||||
createKerberosUserProvider.form().setUpdateProfileFirstLogin(true);
|
createKerberosUserProvider.form().setUpdateProfileFirstLogin(true);
|
||||||
createKerberosUserProvider.form().save();
|
createKerberosUserProvider.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||||
UserFederationProviderRepresentation ufpr = realm.getUserFederationProviders().get(0);
|
UserFederationProviderRepresentation ufpr = realm.getUserFederationProviders().get(0);
|
||||||
assertKerberosSetings(ufpr, "KEYCLOAK.ORG", "HTTP/localhost@KEYCLOAK.ORG", "http.keytab", "true", "true", "true");
|
assertKerberosSetings(ufpr, "KEYCLOAK.ORG", "HTTP/localhost@KEYCLOAK.ORG", "http.keytab", "true", "true", "true");
|
||||||
|
@ -50,18 +50,18 @@ public class KerberosUserFederationTest extends AbstractConsoleTest {
|
||||||
createKerberosUserProvider.form().selectEditMode(UNSYNCED);
|
createKerberosUserProvider.form().selectEditMode(UNSYNCED);
|
||||||
createKerberosUserProvider.form().setUpdateProfileFirstLogin(true);
|
createKerberosUserProvider.form().setUpdateProfileFirstLogin(true);
|
||||||
createKerberosUserProvider.form().save();
|
createKerberosUserProvider.form().save();
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
createKerberosUserProvider.form().setServerPrincipalInput("");
|
createKerberosUserProvider.form().setServerPrincipalInput("");
|
||||||
createKerberosUserProvider.form().setKerberosRealmInput("KEYCLOAK.ORG");;
|
createKerberosUserProvider.form().setKerberosRealmInput("KEYCLOAK.ORG");;
|
||||||
createKerberosUserProvider.form().save();
|
createKerberosUserProvider.form().save();
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
createKerberosUserProvider.form().setServerPrincipalInput("HTTP/localhost@KEYCLOAK.ORG");;
|
createKerberosUserProvider.form().setServerPrincipalInput("HTTP/localhost@KEYCLOAK.ORG");;
|
||||||
createKerberosUserProvider.form().setKeyTabInput("");
|
createKerberosUserProvider.form().setKeyTabInput("");
|
||||||
createKerberosUserProvider.form().save();
|
createKerberosUserProvider.form().save();
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
createKerberosUserProvider.form().setKeyTabInput("http.keytab");;
|
createKerberosUserProvider.form().setKeyTabInput("http.keytab");;
|
||||||
createKerberosUserProvider.form().save();
|
createKerberosUserProvider.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertKerberosSetings(UserFederationProviderRepresentation ufpr, String kerberosRealm, String serverPrincipal, String keyTab, String debug, String useKerberosForPasswordAuthentication, String updateProfileFirstLogin) {
|
private void assertKerberosSetings(UserFederationProviderRepresentation ufpr, String kerberosRealm, String serverPrincipal, String keyTab, String debug, String useKerberosForPasswordAuthentication, String updateProfileFirstLogin) {
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class LdapUserFederationTest extends AbstractConsoleTest {
|
||||||
createLdapUserProvider.form().setKeyTabInput("http.keytab");
|
createLdapUserProvider.form().setKeyTabInput("http.keytab");
|
||||||
createLdapUserProvider.form().setDebugEnabled(true);
|
createLdapUserProvider.form().setDebugEnabled(true);
|
||||||
createLdapUserProvider.form().save();
|
createLdapUserProvider.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||||
UserFederationProviderRepresentation ufpr = realm.getUserFederationProviders().get(0);
|
UserFederationProviderRepresentation ufpr = realm.getUserFederationProviders().get(0);
|
||||||
|
@ -71,7 +71,7 @@ public class LdapUserFederationTest extends AbstractConsoleTest {
|
||||||
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
|
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
|
||||||
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
||||||
createLdapUserProvider.form().save();
|
createLdapUserProvider.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
RealmRepresentation realm = testRealmResource().toRepresentation();
|
RealmRepresentation realm = testRealmResource().toRepresentation();
|
||||||
UserFederationProviderRepresentation ufpr = realm.getUserFederationProviders().get(0);
|
UserFederationProviderRepresentation ufpr = realm.getUserFederationProviders().get(0);
|
||||||
|
@ -92,22 +92,22 @@ public class LdapUserFederationTest extends AbstractConsoleTest {
|
||||||
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
|
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
|
||||||
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
||||||
createLdapUserProvider.form().save();
|
createLdapUserProvider.form().save();
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
createLdapUserProvider.form().setLdapUserDnInput("");
|
createLdapUserProvider.form().setLdapUserDnInput("");
|
||||||
createLdapUserProvider.form().setLdapConnectionUrlInput("ldap://localhost:389");
|
createLdapUserProvider.form().setLdapConnectionUrlInput("ldap://localhost:389");
|
||||||
createLdapUserProvider.form().save();
|
createLdapUserProvider.form().save();
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
|
createLdapUserProvider.form().setLdapUserDnInput("ou=People,dc=keycloak,dc=org");
|
||||||
createLdapUserProvider.form().setLdapBindDnInput("");
|
createLdapUserProvider.form().setLdapBindDnInput("");
|
||||||
createLdapUserProvider.form().save();
|
createLdapUserProvider.form().save();
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
createLdapUserProvider.form().setLdapBindDnInput("uid=admin,ou=system");
|
createLdapUserProvider.form().setLdapBindDnInput("uid=admin,ou=system");
|
||||||
createLdapUserProvider.form().setLdapBindCredentialInput("");
|
createLdapUserProvider.form().setLdapBindCredentialInput("");
|
||||||
createLdapUserProvider.form().save();
|
createLdapUserProvider.form().save();
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
||||||
createLdapUserProvider.form().save();
|
createLdapUserProvider.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -122,19 +122,19 @@ public class LdapUserFederationTest extends AbstractConsoleTest {
|
||||||
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
createLdapUserProvider.form().setLdapBindCredentialInput("secret");
|
||||||
createLdapUserProvider.form().setAccountAfterPasswordUpdateEnabled(true);
|
createLdapUserProvider.form().setAccountAfterPasswordUpdateEnabled(true);
|
||||||
createLdapUserProvider.form().save();
|
createLdapUserProvider.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
LDAPEmbeddedServer ldapServer = null;
|
LDAPEmbeddedServer ldapServer = null;
|
||||||
try {
|
try {
|
||||||
ldapServer = startEmbeddedLdapServer();
|
ldapServer = startEmbeddedLdapServer();
|
||||||
createLdapUserProvider.form().testConnection();
|
createLdapUserProvider.form().testConnection();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
createLdapUserProvider.form().testAuthentication();
|
createLdapUserProvider.form().testAuthentication();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
createLdapUserProvider.form().synchronizeAllUsers();
|
createLdapUserProvider.form().synchronizeAllUsers();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
createLdapUserProvider.form().setLdapBindCredentialInput("secret1");
|
createLdapUserProvider.form().setLdapBindCredentialInput("secret1");
|
||||||
createLdapUserProvider.form().testAuthentication();
|
createLdapUserProvider.form().testAuthentication();
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
} finally {
|
} finally {
|
||||||
if (ldapServer != null) {
|
if (ldapServer != null) {
|
||||||
ldapServer.stop();
|
ldapServer.stop();
|
||||||
|
|
|
@ -38,8 +38,7 @@ public class IdentityProviderTest extends AbstractConsoleTest {
|
||||||
// @Test
|
// @Test
|
||||||
public void testAddNewProvider() {
|
public void testAddNewProvider() {
|
||||||
idpSettingsPage.addNewProvider(new Provider(SocialProvider.FACEBOOK, "klic", "secret"));
|
idpSettingsPage.addNewProvider(new Provider(SocialProvider.FACEBOOK, "klic", "secret"));
|
||||||
flashMessage.waitUntilPresent();
|
assertAlertSuccess();
|
||||||
assertTrue("Success message should be displayed", flashMessage.isSuccess());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Test(expected = NoSuchElementException.class)
|
// @Test(expected = NoSuchElementException.class)
|
||||||
|
|
|
@ -74,7 +74,7 @@ public class SecurityDefensesTest extends AbstractRealmTest {
|
||||||
bruteForceDetectionPage.form().setWaitIncrementSelect(BruteForceDetection.TimeSelectValues.SECONDS);
|
bruteForceDetectionPage.form().setWaitIncrementSelect(BruteForceDetection.TimeSelectValues.SECONDS);
|
||||||
bruteForceDetectionPage.form().setWaitIncrementInput(String.valueOf(secondsToWait));
|
bruteForceDetectionPage.form().setWaitIncrementInput(String.valueOf(secondsToWait));
|
||||||
bruteForceDetectionPage.form().save();
|
bruteForceDetectionPage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
testRealmAccountPage.navigateTo();
|
testRealmAccountPage.navigateTo();
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ public class SecurityDefensesTest extends AbstractRealmTest {
|
||||||
bruteForceDetectionPage.form().setMinQuickLoginWaitSelect(BruteForceDetection.TimeSelectValues.SECONDS);
|
bruteForceDetectionPage.form().setMinQuickLoginWaitSelect(BruteForceDetection.TimeSelectValues.SECONDS);
|
||||||
bruteForceDetectionPage.form().setMinQuickLoginWaitInput(String.valueOf(secondsToWait));
|
bruteForceDetectionPage.form().setMinQuickLoginWaitInput(String.valueOf(secondsToWait));
|
||||||
bruteForceDetectionPage.form().save();
|
bruteForceDetectionPage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
testRealmAccountPage.navigateTo();
|
testRealmAccountPage.navigateTo();
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ public class SecurityDefensesTest extends AbstractRealmTest {
|
||||||
bruteForceDetectionPage.form().setFailureResetTimeSelect(BruteForceDetection.TimeSelectValues.SECONDS);
|
bruteForceDetectionPage.form().setFailureResetTimeSelect(BruteForceDetection.TimeSelectValues.SECONDS);
|
||||||
bruteForceDetectionPage.form().setFailureResetTimeInput(String.valueOf(secondsToWait));
|
bruteForceDetectionPage.form().setFailureResetTimeInput(String.valueOf(secondsToWait));
|
||||||
bruteForceDetectionPage.form().save();
|
bruteForceDetectionPage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
testRealmAccountPage.navigateTo();
|
testRealmAccountPage.navigateTo();
|
||||||
|
|
||||||
|
@ -228,7 +228,7 @@ public class SecurityDefensesTest extends AbstractRealmTest {
|
||||||
bruteForceDetectionPage.form().setWaitIncrementSelect(BruteForceDetection.TimeSelectValues.MINUTES);
|
bruteForceDetectionPage.form().setWaitIncrementSelect(BruteForceDetection.TimeSelectValues.MINUTES);
|
||||||
bruteForceDetectionPage.form().setWaitIncrementInput("10");
|
bruteForceDetectionPage.form().setWaitIncrementInput("10");
|
||||||
bruteForceDetectionPage.form().save();
|
bruteForceDetectionPage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
testRealmAccountPage.navigateTo();
|
testRealmAccountPage.navigateTo();
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ public class DefaultRolesTest extends AbstractRolesTest {
|
||||||
String defaultRoleName = defaultRoleRep.getName();
|
String defaultRoleName = defaultRoleRep.getName();
|
||||||
|
|
||||||
defaultRolesPage.form().addAvailableRole(defaultRoleName);
|
defaultRolesPage.form().addAvailableRole(defaultRoleName);
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
UserRepresentation newUser = new UserRepresentation();
|
UserRepresentation newUser = new UserRepresentation();
|
||||||
newUser.setUsername("new_user");
|
newUser.setUsername("new_user");
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class RealmRolesTest extends AbstractRolesTest {
|
||||||
assertCurrentUrlEquals(createRolePage);
|
assertCurrentUrlEquals(createRolePage);
|
||||||
createRolePage.form().setBasicAttributes(roleRep);
|
createRolePage.form().setBasicAttributes(roleRep);
|
||||||
createRolePage.form().save();
|
createRolePage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
createRolePage.form().setCompositeRoles(roleRep);
|
createRolePage.form().setCompositeRoles(roleRep);
|
||||||
// TODO add verification of notification message when KEYCLOAK-1497 gets resolved
|
// TODO add verification of notification message when KEYCLOAK-1497 gets resolved
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public class RealmRolesTest extends AbstractRolesTest {
|
||||||
// assertCurrentUrl(role); // can't do this, role id needed as uri param
|
// assertCurrentUrl(role); // can't do this, role id needed as uri param
|
||||||
rolePage.form().setBasicAttributes(roleRep);
|
rolePage.form().setBasicAttributes(roleRep);
|
||||||
rolePage.form().save();
|
rolePage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
rolePage.form().setCompositeRoles(roleRep);
|
rolePage.form().setCompositeRoles(roleRep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ public class RealmRolesTest extends AbstractRolesTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@Ignore
|
||||||
public void crudRole() {
|
public void crudRole() {
|
||||||
addRole(testRole);
|
addRole(testRole);
|
||||||
|
|
||||||
|
@ -77,7 +78,7 @@ public class RealmRolesTest extends AbstractRolesTest {
|
||||||
testRole.setDescription("updated role description");
|
testRole.setDescription("updated role description");
|
||||||
rolePage.form().setDescription(testRole.getDescription());
|
rolePage.form().setDescription(testRole.getDescription());
|
||||||
rolePage.form().save();
|
rolePage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
configure().roles();
|
configure().roles();
|
||||||
foundRole = realmRolesPage.table().findRole(testRole.getName()); // search & get role from table
|
foundRole = realmRolesPage.table().findRole(testRole.getName()); // search & get role from table
|
||||||
|
@ -111,13 +112,12 @@ public class RealmRolesTest extends AbstractRolesTest {
|
||||||
@Test
|
@Test
|
||||||
public void testAddExistingRole() {
|
public void testAddExistingRole() {
|
||||||
addRole(testRole);
|
addRole(testRole);
|
||||||
assertFlashMessageSuccess();
|
|
||||||
|
|
||||||
configure().roles();
|
configure().roles();
|
||||||
realmRolesPage.table().addRole();
|
realmRolesPage.table().addRole();
|
||||||
createRolePage.form().setBasicAttributes(testRole);
|
createRolePage.form().setBasicAttributes(testRole);
|
||||||
createRolePage.form().save();
|
createRolePage.form().save();
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createTestRoles(String namePrefix, int count) {
|
public void createTestRoles(String namePrefix, int count) {
|
||||||
|
|
|
@ -67,7 +67,7 @@ public class RequiredUserActionsTest extends AbstractUserTest {
|
||||||
public void updatePassword() {
|
public void updatePassword() {
|
||||||
userAttributesPage.form().addRequiredAction(UPDATE_PASSWORD.getActionName());
|
userAttributesPage.form().addRequiredAction(UPDATE_PASSWORD.getActionName());
|
||||||
userAttributesPage.form().save();
|
userAttributesPage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
testRealmAccountPage.navigateTo();
|
testRealmAccountPage.navigateTo();
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ public class RequiredUserActionsTest extends AbstractUserTest {
|
||||||
public void updateProfile() {
|
public void updateProfile() {
|
||||||
userAttributesPage.form().addRequiredAction(UPDATE_PROFILE.getActionName());
|
userAttributesPage.form().addRequiredAction(UPDATE_PROFILE.getActionName());
|
||||||
userAttributesPage.form().save();
|
userAttributesPage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
testRealmAccountPage.navigateTo();
|
testRealmAccountPage.navigateTo();
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ public class RequiredUserActionsTest extends AbstractUserTest {
|
||||||
|
|
||||||
userAttributesPage.form().addRequiredAction(TERMS_AND_CONDITIONS.getActionName());
|
userAttributesPage.form().addRequiredAction(TERMS_AND_CONDITIONS.getActionName());
|
||||||
userAttributesPage.form().save();
|
userAttributesPage.form().save();
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
testRealmAccountPage.navigateTo();
|
testRealmAccountPage.navigateTo();
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ public class UserAttributesTest extends AbstractUserTest {
|
||||||
setPasswordFor(newTestRealmUser, "pass");
|
setPasswordFor(newTestRealmUser, "pass");
|
||||||
newTestRealmUser.setEmail(invalidEmail);
|
newTestRealmUser.setEmail(invalidEmail);
|
||||||
createUser(newTestRealmUser);
|
createUser(newTestRealmUser);
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
|
|
||||||
userAttributesPage.backToUsersViaBreadcrumb();
|
userAttributesPage.backToUsersViaBreadcrumb();
|
||||||
assertNull(usersPage.table().findUser(testUsername));
|
assertNull(usersPage.table().findUser(testUsername));
|
||||||
|
@ -58,7 +58,7 @@ public class UserAttributesTest extends AbstractUserTest {
|
||||||
@Test
|
@Test
|
||||||
public void noUsername() {
|
public void noUsername() {
|
||||||
createUser(newTestRealmUser);
|
createUser(newTestRealmUser);
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -66,7 +66,7 @@ public class UserAttributesTest extends AbstractUserTest {
|
||||||
String testUsername = "test_duplicated_user";
|
String testUsername = "test_duplicated_user";
|
||||||
newTestRealmUser.setUsername(testUsername);
|
newTestRealmUser.setUsername(testUsername);
|
||||||
createUser(newTestRealmUser);
|
createUser(newTestRealmUser);
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
|
|
||||||
userAttributesPage.backToUsersViaBreadcrumb();
|
userAttributesPage.backToUsersViaBreadcrumb();
|
||||||
assertNotNull(usersPage.table().findUser(testUsername));
|
assertNotNull(usersPage.table().findUser(testUsername));
|
||||||
|
@ -74,7 +74,7 @@ public class UserAttributesTest extends AbstractUserTest {
|
||||||
UserRepresentation testUser2 = new UserRepresentation();
|
UserRepresentation testUser2 = new UserRepresentation();
|
||||||
testUser2.setUsername(testUsername);
|
testUser2.setUsername(testUsername);
|
||||||
createUser(testUser2);
|
createUser(testUser2);
|
||||||
assertFlashMessageDanger();
|
assertAlertDanger();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -83,7 +83,7 @@ public class UserAttributesTest extends AbstractUserTest {
|
||||||
disabledUser.setEnabled(false);
|
disabledUser.setEnabled(false);
|
||||||
disabledUser.setUsername("disabled_user");
|
disabledUser.setUsername("disabled_user");
|
||||||
createUser(disabledUser);
|
createUser(disabledUser);
|
||||||
assertFlashMessageSuccess();
|
assertAlertSuccess();
|
||||||
// TODO try to log in
|
// TODO try to log in
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,13 @@
|
||||||
<property name="browser">${browser}</property>
|
<property name="browser">${browser}</property>
|
||||||
</extension>
|
</extension>
|
||||||
|
|
||||||
|
<extension qualifier="graphene">
|
||||||
|
<property name="waitGuiInterval">5</property>
|
||||||
|
<property name="waitAjaxInterval">5</property>
|
||||||
|
<property name="waitModelInterval">10</property>
|
||||||
|
<property name="waitGuardInterval">5</property>
|
||||||
|
</extension>
|
||||||
|
|
||||||
<extension qualifier="graphene-secondbrowser">
|
<extension qualifier="graphene-secondbrowser">
|
||||||
<property name="browser">${browser}</property>
|
<property name="browser">${browser}</property>
|
||||||
</extension>
|
</extension>
|
||||||
|
|
|
@ -609,6 +609,7 @@
|
||||||
</pluginManagement>
|
</pluginManagement>
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
package org.keycloak.testsuite.adduser;
|
package org.keycloak.testsuite.adduser;
|
||||||
|
|
||||||
import org.codehaus.jackson.type.TypeReference;
|
import org.codehaus.jackson.type.TypeReference;
|
||||||
import org.junit.*;
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
import org.junit.rules.TemporaryFolder;
|
import org.junit.rules.TemporaryFolder;
|
||||||
import org.keycloak.admin.client.Keycloak;
|
import org.keycloak.admin.client.Keycloak;
|
||||||
import org.keycloak.admin.client.resource.RealmResource;
|
import org.keycloak.admin.client.resource.RealmResource;
|
||||||
import org.keycloak.admin.client.resource.RoleMappingResource;
|
|
||||||
import org.keycloak.admin.client.resource.RoleScopeResource;
|
|
||||||
import org.keycloak.admin.client.resource.UserResource;
|
import org.keycloak.admin.client.resource.UserResource;
|
||||||
import org.keycloak.common.util.Base64Url;
|
import org.keycloak.common.util.Base64;
|
||||||
|
import org.keycloak.hash.Pbkdf2PasswordHashProvider;
|
||||||
import org.keycloak.models.Constants;
|
import org.keycloak.models.Constants;
|
||||||
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
|
||||||
import org.keycloak.representations.idm.*;
|
import org.keycloak.representations.idm.*;
|
||||||
import org.keycloak.testsuite.KeycloakServer;
|
import org.keycloak.testsuite.KeycloakServer;
|
||||||
import org.keycloak.util.JsonSerialization;
|
import org.keycloak.util.JsonSerialization;
|
||||||
|
@ -19,7 +20,6 @@ import org.keycloak.wildfly.adduser.AddUser;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
@ -59,7 +59,11 @@ public class AddUserTest {
|
||||||
UserRepresentation user = realms.get(0).getUsers().get(0);
|
UserRepresentation user = realms.get(0).getUsers().get(0);
|
||||||
assertEquals(new Integer(100000), user.getCredentials().get(0).getHashIterations());
|
assertEquals(new Integer(100000), user.getCredentials().get(0).getHashIterations());
|
||||||
assertNull(user.getCredentials().get(0).getValue());
|
assertNull(user.getCredentials().get(0).getValue());
|
||||||
assertEquals(new Pbkdf2PasswordEncoder(Base64Url.decode(user.getCredentials().get(0).getSalt()), 100000).encode("password"), user.getCredentials().get(0).getHashedSaltedValue());
|
|
||||||
|
CredentialRepresentation credentials = user.getCredentials().get(0);
|
||||||
|
|
||||||
|
assertEquals(Pbkdf2PasswordHashProvider.ID, credentials.getAlgorithm());
|
||||||
|
assertEquals(new Integer(100000), credentials.getHashIterations());
|
||||||
|
|
||||||
KeycloakServer server = new KeycloakServer();
|
KeycloakServer server = new KeycloakServer();
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -322,7 +322,12 @@ public class ExportImportTest {
|
||||||
Assert.fail("user " + username + " not found");
|
Assert.fail("user " + username + " not found");
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.assertTrue(userProvider.validCredentials(realm, user, UserCredentialModel.password(password)));
|
KeycloakSession session = keycloakRule.startSession();
|
||||||
|
try {
|
||||||
|
Assert.assertTrue(userProvider.validCredentials(session, realm, user, UserCredentialModel.password(password)));
|
||||||
|
} finally {
|
||||||
|
keycloakRule.stopSession(session, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertNotAuthenticated(UserProvider userProvider, RealmProvider realmProvider, String realmName, String username, String password) {
|
private void assertNotAuthenticated(UserProvider userProvider, RealmProvider realmProvider, String realmName, String username, String password) {
|
||||||
|
@ -336,7 +341,12 @@ public class ExportImportTest {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Assert.assertFalse(userProvider.validCredentials(realm, user, UserCredentialModel.password(password)));
|
KeycloakSession session = keycloakRule.startSession();
|
||||||
|
try {
|
||||||
|
Assert.assertFalse(userProvider.validCredentials(session, realm, user, UserCredentialModel.password(password)));
|
||||||
|
} finally {
|
||||||
|
keycloakRule.stopSession(session, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void addUser(UserProvider userProvider, RealmModel appRealm, String username, String password) {
|
private static void addUser(UserProvider userProvider, RealmModel appRealm, String username, String password) {
|
||||||
|
|
|
@ -678,7 +678,7 @@ public class FederationProvidersIntegrationTest {
|
||||||
user.updateCredential(cred);
|
user.updateCredential(cred);
|
||||||
UserCredentialValueModel userCredentialValueModel = user.getCredentialsDirectly().get(0);
|
UserCredentialValueModel userCredentialValueModel = user.getCredentialsDirectly().get(0);
|
||||||
Assert.assertEquals(UserCredentialModel.PASSWORD, userCredentialValueModel.getType());
|
Assert.assertEquals(UserCredentialModel.PASSWORD, userCredentialValueModel.getType());
|
||||||
Assert.assertTrue(session.users().validCredentials(appRealm, user, cred));
|
Assert.assertTrue(session.users().validCredentials(session, appRealm, user, cred));
|
||||||
|
|
||||||
// LDAP password is still unchanged
|
// LDAP password is still unchanged
|
||||||
LDAPFederationProvider ldapProvider = FederationTestUtils.getLdapProvider(session, model);
|
LDAPFederationProvider ldapProvider = FederationTestUtils.getLdapProvider(session, model);
|
||||||
|
|
|
@ -144,11 +144,11 @@ public class AdapterTest extends AbstractModelTest {
|
||||||
cred.setType(CredentialRepresentation.PASSWORD);
|
cred.setType(CredentialRepresentation.PASSWORD);
|
||||||
cred.setValue("geheim");
|
cred.setValue("geheim");
|
||||||
user.updateCredential(cred);
|
user.updateCredential(cred);
|
||||||
Assert.assertTrue(userProvider.validCredentials(realmModel, user, UserCredentialModel.password("geheim")));
|
Assert.assertTrue(userProvider.validCredentials(session, realmModel, user, UserCredentialModel.password("geheim")));
|
||||||
List<UserCredentialValueModel> creds = user.getCredentialsDirectly();
|
List<UserCredentialValueModel> creds = user.getCredentialsDirectly();
|
||||||
Assert.assertEquals(creds.get(0).getHashIterations(), 1);
|
Assert.assertEquals(creds.get(0).getHashIterations(), 1);
|
||||||
realmModel.setPasswordPolicy(new PasswordPolicy("hashIterations(200)"));
|
realmModel.setPasswordPolicy(new PasswordPolicy("hashIterations(200)"));
|
||||||
Assert.assertTrue(userProvider.validCredentials(realmModel, user, UserCredentialModel.password("geheim")));
|
Assert.assertTrue(userProvider.validCredentials(session, realmModel, user, UserCredentialModel.password("geheim")));
|
||||||
creds = user.getCredentialsDirectly();
|
creds = user.getCredentialsDirectly();
|
||||||
Assert.assertEquals(creds.get(0).getHashIterations(), 200);
|
Assert.assertEquals(creds.get(0).getHashIterations(), 200);
|
||||||
realmModel.setPasswordPolicy(new PasswordPolicy("hashIterations(1)"));
|
realmModel.setPasswordPolicy(new PasswordPolicy("hashIterations(1)"));
|
||||||
|
|
|
@ -39,10 +39,10 @@ public class MultipleRealmsTest extends AbstractModelTest {
|
||||||
r1user1.updateCredential(UserCredentialModel.password("pass1"));
|
r1user1.updateCredential(UserCredentialModel.password("pass1"));
|
||||||
r2user1.updateCredential(UserCredentialModel.password("pass2"));
|
r2user1.updateCredential(UserCredentialModel.password("pass2"));
|
||||||
|
|
||||||
Assert.assertTrue(session.users().validCredentials(realm1, r1user1, UserCredentialModel.password("pass1")));
|
Assert.assertTrue(session.users().validCredentials(session, realm1, r1user1, UserCredentialModel.password("pass1")));
|
||||||
Assert.assertFalse(session.users().validCredentials(realm1, r1user1, UserCredentialModel.password("pass2")));
|
Assert.assertFalse(session.users().validCredentials(session, realm1, r1user1, UserCredentialModel.password("pass2")));
|
||||||
Assert.assertFalse(session.users().validCredentials(realm2, r2user1, UserCredentialModel.password("pass1")));
|
Assert.assertFalse(session.users().validCredentials(session, realm2, r2user1, UserCredentialModel.password("pass1")));
|
||||||
Assert.assertTrue(session.users().validCredentials(realm2, r2user1, UserCredentialModel.password("pass2")));
|
Assert.assertTrue(session.users().validCredentials(session, realm2, r2user1, UserCredentialModel.password("pass2")));
|
||||||
|
|
||||||
// Test searching
|
// Test searching
|
||||||
Assert.assertEquals(2, session.users().searchForUser("user", realm1).size());
|
Assert.assertEquals(2, session.users().searchForUser("user", realm1).size());
|
||||||
|
|
|
@ -102,7 +102,7 @@ public class ReadUsersWorker implements Worker {
|
||||||
|
|
||||||
// Validate password (shoould be same as username)
|
// Validate password (shoould be same as username)
|
||||||
if (readPassword) {
|
if (readPassword) {
|
||||||
session.users().validCredentials(realm, user, UserCredentialModel.password(username));
|
session.users().validCredentials(session, realm, user, UserCredentialModel.password(username));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read federatedIdentities of user
|
// Read federatedIdentities of user
|
||||||
|
|
|
@ -12,8 +12,8 @@ import org.jboss.aesh.console.command.invocation.CommandInvocation;
|
||||||
import org.jboss.aesh.console.command.registry.AeshCommandRegistryBuilder;
|
import org.jboss.aesh.console.command.registry.AeshCommandRegistryBuilder;
|
||||||
import org.jboss.aesh.console.command.registry.CommandRegistry;
|
import org.jboss.aesh.console.command.registry.CommandRegistry;
|
||||||
import org.keycloak.common.util.Base64;
|
import org.keycloak.common.util.Base64;
|
||||||
import org.keycloak.models.Constants;
|
import org.keycloak.hash.Pbkdf2PasswordHashProvider;
|
||||||
import org.keycloak.models.utils.Pbkdf2PasswordEncoder;
|
import org.keycloak.models.UserCredentialValueModel;
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
import org.keycloak.representations.idm.UserRepresentation;
|
import org.keycloak.representations.idm.UserRepresentation;
|
||||||
|
@ -138,14 +138,14 @@ public class AddUser {
|
||||||
user.setUsername(userName);
|
user.setUsername(userName);
|
||||||
user.setCredentials(new LinkedList<CredentialRepresentation>());
|
user.setCredentials(new LinkedList<CredentialRepresentation>());
|
||||||
|
|
||||||
byte[] salt = Pbkdf2PasswordEncoder.getSalt();
|
UserCredentialValueModel credentialValueModel = new Pbkdf2PasswordHashProvider().encode(password, iterations > 0 ? iterations : DEFAULT_HASH_ITERATIONS);
|
||||||
iterations = iterations > 0 ? iterations : DEFAULT_HASH_ITERATIONS;
|
|
||||||
|
|
||||||
CredentialRepresentation credentials = new CredentialRepresentation();
|
CredentialRepresentation credentials = new CredentialRepresentation();
|
||||||
credentials.setType(CredentialRepresentation.PASSWORD);
|
credentials.setType(credentialValueModel.getType());
|
||||||
credentials.setHashIterations(iterations);
|
credentials.setAlgorithm(credentialValueModel.getAlgorithm());
|
||||||
credentials.setSalt(Base64.encodeBytes(salt));
|
credentials.setHashIterations(credentialValueModel.getHashIterations());
|
||||||
credentials.setHashedSaltedValue(new Pbkdf2PasswordEncoder(salt).encode(password, iterations));
|
credentials.setSalt(Base64.encodeBytes(credentialValueModel.getSalt()));
|
||||||
|
credentials.setHashedSaltedValue(credentialValueModel.getValue());
|
||||||
|
|
||||||
user.getCredentials().add(credentials);
|
user.getCredentials().add(credentials);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue