Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Bill Burke 2016-10-18 10:14:00 -04:00
commit 2199df71bf
277 changed files with 2148 additions and 48917 deletions

View file

@ -165,6 +165,9 @@ public final class KeycloakAdapterConfigService {
protected boolean isDeploymentConfigured(DeploymentUnit deploymentUnit) { protected boolean isDeploymentConfigured(DeploymentUnit deploymentUnit) {
ModelNode deployment = getSecureDeployment(deploymentUnit); ModelNode deployment = getSecureDeployment(deploymentUnit);
if (! deployment.isDefined()) {
return false;
}
ModelNode resource = deployment.get(SecureDeploymentDefinition.RESOURCE.getName()); ModelNode resource = deployment.get(SecureDeploymentDefinition.RESOURCE.getName());
return resource.isDefined(); return resource.isDefined();
} }
@ -202,7 +205,9 @@ public final class KeycloakAdapterConfigService {
private ModelNode getSecureDeployment(DeploymentUnit deploymentUnit) { private ModelNode getSecureDeployment(DeploymentUnit deploymentUnit) {
String deploymentName = preferredDeploymentName(deploymentUnit); String deploymentName = preferredDeploymentName(deploymentUnit);
return this.secureDeployments.get(deploymentName); return this.secureDeployments.containsKey(deploymentName)
? this.secureDeployments.get(deploymentName)
: new ModelNode();
} }
// KEYCLOAK-3273: prefer module name if available // KEYCLOAK-3273: prefer module name if available

View file

@ -164,6 +164,9 @@ public final class KeycloakAdapterConfigService {
protected boolean isDeploymentConfigured(DeploymentUnit deploymentUnit) { protected boolean isDeploymentConfigured(DeploymentUnit deploymentUnit) {
ModelNode deployment = getSecureDeployment(deploymentUnit); ModelNode deployment = getSecureDeployment(deploymentUnit);
if (! deployment.isDefined()) {
return false;
}
ModelNode resource = deployment.get(SecureDeploymentDefinition.RESOURCE.getName()); ModelNode resource = deployment.get(SecureDeploymentDefinition.RESOURCE.getName());
return resource.isDefined(); return resource.isDefined();
} }
@ -201,7 +204,9 @@ public final class KeycloakAdapterConfigService {
private ModelNode getSecureDeployment(DeploymentUnit deploymentUnit) { private ModelNode getSecureDeployment(DeploymentUnit deploymentUnit) {
String deploymentName = preferredDeploymentName(deploymentUnit); String deploymentName = preferredDeploymentName(deploymentUnit);
return this.secureDeployments.get(deploymentName); return this.secureDeployments.containsKey(deploymentName)
? this.secureDeployments.get(deploymentName)
: new ModelNode();
} }
// KEYCLOAK-3273: prefer module name if available // KEYCLOAK-3273: prefer module name if available

View file

@ -164,6 +164,9 @@ public final class KeycloakAdapterConfigService {
protected boolean isDeploymentConfigured(DeploymentUnit deploymentUnit) { protected boolean isDeploymentConfigured(DeploymentUnit deploymentUnit) {
ModelNode deployment = getSecureDeployment(deploymentUnit); ModelNode deployment = getSecureDeployment(deploymentUnit);
if (! deployment.isDefined()) {
return false;
}
ModelNode resource = deployment.get(SecureDeploymentDefinition.RESOURCE.getName()); ModelNode resource = deployment.get(SecureDeploymentDefinition.RESOURCE.getName());
return resource.isDefined(); return resource.isDefined();
} }
@ -201,7 +204,9 @@ public final class KeycloakAdapterConfigService {
private ModelNode getSecureDeployment(DeploymentUnit deploymentUnit) { private ModelNode getSecureDeployment(DeploymentUnit deploymentUnit) {
String deploymentName = preferredDeploymentName(deploymentUnit); String deploymentName = preferredDeploymentName(deploymentUnit);
return this.secureDeployments.get(deploymentName); return this.secureDeployments.containsKey(deploymentName)
? this.secureDeployments.get(deploymentName)
: new ModelNode();
} }
// KEYCLOAK-3273: prefer module name if available // KEYCLOAK-3273: prefer module name if available

View file

@ -85,11 +85,6 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
def.parseAndSetParameter(reader.getElementText(), addRealm, reader); def.parseAndSetParameter(reader.getElementText(), addRealm, reader);
} }
if (!SharedAttributeDefinitons.validateTruststoreSetIfRequired(addRealm)) {
//TODO: externalize the message
throw new XMLStreamException("truststore and truststore-password must be set if ssl-required is not none and disable-trust-maanger is false.");
}
list.add(addRealm); list.add(addRealm);
} }
@ -113,15 +108,6 @@ class KeycloakSubsystemParser implements XMLStreamConstants, XMLElementReader<Li
def.parseAndSetParameter(reader.getElementText(), addSecureDeployment, reader); def.parseAndSetParameter(reader.getElementText(), addSecureDeployment, reader);
} }
/**
* TODO need to check realm-ref first.
if (!SharedAttributeDefinitons.validateTruststoreSetIfRequired(addSecureDeployment)) {
//TODO: externalize the message
throw new XMLStreamException("truststore and truststore-password must be set if ssl-required is not none and disable-trust-maanger is false.");
}
*/
// Must add credentials after the deployment is added. // Must add credentials after the deployment is added.
resourcesToAdd.add(addSecureDeployment); resourcesToAdd.add(addSecureDeployment);
resourcesToAdd.addAll(credentialsToAdd); resourcesToAdd.addAll(credentialsToAdd);

View file

@ -48,10 +48,6 @@ public final class RealmAddHandler extends AbstractAddStepHandler {
attrib.validateAndSet(operation, model); attrib.validateAndSet(operation, model);
} }
if (!SharedAttributeDefinitons.validateTruststoreSetIfRequired(model.clone())) {
//TODO: externalize message
throw new OperationFailedException("truststore and truststore-password must be set if ssl-required is not none and disable-trust-maanger is false.");
}
} }
@Override @Override

View file

@ -195,25 +195,6 @@ public class SharedAttributeDefinitons {
ATTRIBUTES.add(PRINCIPAL_ATTRIBUTE); ATTRIBUTES.add(PRINCIPAL_ATTRIBUTE);
} }
/**
* truststore and truststore-password must be set if ssl-required is not none and disable-trust-manager is false.
*
* @param attributes The full set of attributes.
*
* @return <code>true</code> if the attributes are valid, <code>false</code> otherwise.
*/
public static boolean validateTruststoreSetIfRequired(ModelNode attributes) {
if (isSet(attributes, DISABLE_TRUST_MANAGER)) {
return true;
}
if (isSet(attributes, SSL_REQUIRED) && attributes.get(SSL_REQUIRED.getName()).asString().equals("none")) {
return true;
}
return isSet(attributes, TRUSTSTORE) && isSet(attributes, TRUSTSTORE_PASSWORD);
}
private static boolean isSet(ModelNode attributes, SimpleAttributeDefinition def) { private static boolean isSet(ModelNode attributes, SimpleAttributeDefinition def) {
ModelNode attribute = attributes.get(def.getName()); ModelNode attribute = attributes.get(def.getName());

View file

@ -1,86 +0,0 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.subsystem.adapter.extension;
import org.jboss.dmr.ModelNode;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
*
* @author Stan Silvert ssilvert@redhat.com (C) 2013 Red Hat Inc.
*/
public class RealmDefinitionTestCase {
private ModelNode model;
@Before
public void setUp() {
model = new ModelNode();
model.get("realm").set("demo");
model.get("resource").set("customer-portal");
model.get("realm-public-key").set("MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCrVrCuTtArbgaZzL1hvh0xtL5mc7o0NqPVnYXkLvgcwiC3BjLGw1tGEGoJaXDuSaRllobm53JBhjx33UNv+5z/UMG4kytBWxheNVKnL6GgqlNabMaFfPLPCF8kAgKnsi79NMo+n6KnSY8YeUmec/p2vjO2NjsSAVcWEQMVhJ31LwIDAQAB");
model.get("auth-url").set("http://localhost:8080/auth-server/rest/realms/demo/protocol/openid-connect/login");
model.get("code-url").set("http://localhost:8080/auth-server/rest/realms/demo/protocol/openid-connect/access/codes");
model.get("expose-token").set(true);
ModelNode credential = new ModelNode();
credential.get("password").set("password");
model.get("credentials").set(credential);
}
@Test
public void testIsTruststoreSetIfRequired() throws Exception {
model.get("ssl-required").set("none");
model.get("disable-trust-manager").set(true);
Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model));
model.get("ssl-required").set("none");
model.get("disable-trust-manager").set(false);
Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model));
model.get("ssl-required").set("all");
model.get("disable-trust-manager").set(true);
Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model));
model.get("ssl-required").set("all");
model.get("disable-trust-manager").set(false);
Assert.assertFalse(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model));
model.get("ssl-required").set("external");
model.get("disable-trust-manager").set(false);
Assert.assertFalse(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model));
model.get("ssl-required").set("all");
model.get("disable-trust-manager").set(false);
model.get("truststore").set("foo");
Assert.assertFalse(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model));
model.get("ssl-required").set("all");
model.get("disable-trust-manager").set(false);
model.get("truststore").set("foo");
model.get("truststore-password").set("password");
Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model));
model.get("ssl-required").set("external");
model.get("disable-trust-manager").set(false);
model.get("truststore").set("foo");
model.get("truststore-password").set("password");
Assert.assertTrue(SharedAttributeDefinitons.validateTruststoreSetIfRequired(model));
}
}

View file

@ -31,12 +31,6 @@
<description/> <description/>
<dependencies> <dependencies>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>${jboss.logging.version}</version>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-saml-core</artifactId> <artifactId>keycloak-saml-core</artifactId>

View file

@ -17,6 +17,8 @@
package org.keycloak.representations.idm; package org.keycloak.representations.idm;
import java.util.List;
/** /**
* @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 $
@ -27,6 +29,7 @@ public class ConfigPropertyRepresentation {
protected String helpText; protected String helpText;
protected String type; protected String type;
protected Object defaultValue; protected Object defaultValue;
protected List<String> options;
protected boolean secret; protected boolean secret;
public String getName() { public String getName() {
@ -69,6 +72,14 @@ public class ConfigPropertyRepresentation {
this.helpText = helpText; this.helpText = helpText;
} }
public List<String> getOptions() {
return options;
}
public void setOptions(List<String> options) {
this.options = options;
}
public boolean isSecret() { public boolean isSecret() {
return secret; return secret;
} }

View file

@ -35,6 +35,10 @@ public class UserConsentRepresentation {
// Key is clientId, Value is list of granted roles of this client // Key is clientId, Value is list of granted roles of this client
protected Map<String, List<String>> grantedClientRoles; protected Map<String, List<String>> grantedClientRoles;
private Long createdDate;
private Long lastUpdatedDate;
public String getClientId() { public String getClientId() {
return clientId; return clientId;
} }
@ -66,4 +70,20 @@ public class UserConsentRepresentation {
public void setGrantedClientRoles(Map<String, List<String>> grantedClientRoles) { public void setGrantedClientRoles(Map<String, List<String>> grantedClientRoles) {
this.grantedClientRoles = grantedClientRoles; this.grantedClientRoles = grantedClientRoles;
} }
public void setCreatedDate(Long createdDate) {
this.createdDate = createdDate;
}
public Long getCreatedDate() {
return createdDate;
}
public void setLastUpdatedDate(Long lastUpdatedDate) {
this.lastUpdatedDate = lastUpdatedDate;
}
public Long getLastUpdatedDate() {
return lastUpdatedDate;
}
} }

View file

@ -31,29 +31,17 @@
<name>Keycloak Dependencies Server All</name> <name>Keycloak Dependencies Server All</name>
<description /> <description />
<properties> <dependencyManagement>
<!-- Drools dependencies versions --> <dependencies>
<version.org.eclipse.sisu>0.3.0.M1</version.org.eclipse.sisu> <dependency>
<version.org.eclipse.aether>1.0.0.v20140518</version.org.eclipse.aether> <groupId>org.jboss.integration-platform</groupId>
<version.org.apache.ant>1.8.3</version.org.apache.ant> <artifactId>jboss-integration-platform-bom</artifactId>
<version.org.antlr>3.5</version.org.antlr> <type>pom</type>
<version.aopalliance>1.0</version.aopalliance> <scope>import</scope>
<version.org.apache.maven>3.2.5</version.org.apache.maven> <version>${version.jboss-integration-platform}</version>
<version.org.mvel>2.2.8.Final</version.org.mvel> </dependency>
<version.org.sonatype.plexus.plexus-cipher>1.7</version.org.sonatype.plexus.plexus-cipher> </dependencies>
<version.org.codehaus.plexus.plexus-classworlds>2.5.2</version.org.codehaus.plexus.plexus-classworlds> </dependencyManagement>
<version.org.codehaus.plexus.plexus-component-annotations>1.5.5</version.org.codehaus.plexus.plexus-component-annotations>
<version.org.codehaus.plexus.plexus-interpolation>1.21</version.org.codehaus.plexus.plexus-interpolation>
<version.org.codehaus.plexus.plexus-sec-dispatcher>1.3</version.org.codehaus.plexus.plexus-sec-dispatcher>
<version.org.codehaus.plexus.plexus-utils>3.0.20</version.org.codehaus.plexus.plexus-utils>
<version.org.apache.maven.wagon>2.6</version.org.apache.maven.wagon>
<version.com.thoughtworks.xstream>1.4.7</version.com.thoughtworks.xstream>
<version.com.google.guava>13.0.1</version.com.google.guava>
<version.org.eclipse.jdt.core.compiler>4.4.2</version.org.eclipse.jdt.core.compiler>
<version.com.lowagie>2.1.2</version.com.lowagie>
<version.org.sonatype.sisu>3.2.3</version.org.sonatype.sisu>
<version.com.google.inject.extensions.guice-servlet>3.0</version.com.google.inject.extensions.guice-servlet>
</properties>
<dependencies> <dependencies>
<dependency> <dependency>
@ -158,122 +146,98 @@
<dependency> <dependency>
<groupId>org.eclipse.aether</groupId> <groupId>org.eclipse.aether</groupId>
<artifactId>aether-api</artifactId> <artifactId>aether-api</artifactId>
<version>${version.org.eclipse.aether}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.aether</groupId> <groupId>org.eclipse.aether</groupId>
<artifactId>aether-connector-basic</artifactId> <artifactId>aether-connector-basic</artifactId>
<version>${version.org.eclipse.aether}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.aether</groupId> <groupId>org.eclipse.aether</groupId>
<artifactId>aether-spi</artifactId> <artifactId>aether-spi</artifactId>
<version>${version.org.eclipse.aether}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.aether</groupId> <groupId>org.eclipse.aether</groupId>
<artifactId>aether-impl</artifactId> <artifactId>aether-impl</artifactId>
<version>${version.org.eclipse.aether}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.aether</groupId> <groupId>org.eclipse.aether</groupId>
<artifactId>aether-transport-file</artifactId> <artifactId>aether-transport-file</artifactId>
<version>${version.org.eclipse.aether}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.aether</groupId> <groupId>org.eclipse.aether</groupId>
<artifactId>aether-transport-http</artifactId> <artifactId>aether-transport-http</artifactId>
<version>${version.org.eclipse.aether}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.aether</groupId> <groupId>org.eclipse.aether</groupId>
<artifactId>aether-transport-wagon</artifactId> <artifactId>aether-transport-wagon</artifactId>
<version>${version.org.eclipse.aether}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.aether</groupId> <groupId>org.eclipse.aether</groupId>
<artifactId>aether-util</artifactId> <artifactId>aether-util</artifactId>
<version>${version.org.eclipse.aether}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.ant</groupId> <groupId>org.apache.ant</groupId>
<artifactId>ant</artifactId> <artifactId>ant</artifactId>
<version>${version.org.apache.ant}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.ant</groupId> <groupId>org.apache.ant</groupId>
<artifactId>ant-launcher</artifactId> <artifactId>ant-launcher</artifactId>
<version>${version.org.apache.ant}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.antlr</groupId> <groupId>org.antlr</groupId>
<artifactId>antlr-runtime</artifactId> <artifactId>antlr-runtime</artifactId>
<version>${version.org.antlr}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>aopalliance</groupId> <groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId> <artifactId>aopalliance</artifactId>
<version>${version.aopalliance}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-aether-provider</artifactId> <artifactId>maven-aether-provider</artifactId>
<version>${version.org.apache.maven}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-artifact</artifactId> <artifactId>maven-artifact</artifactId>
<version>${version.org.apache.maven}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-compat</artifactId> <artifactId>maven-compat</artifactId>
<version>${version.org.apache.maven}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId> <artifactId>maven-core</artifactId>
<version>${version.org.apache.maven}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-model</artifactId> <artifactId>maven-model</artifactId>
<version>${version.org.apache.maven}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-model-builder</artifactId> <artifactId>maven-model-builder</artifactId>
<version>${version.org.apache.maven}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId> <artifactId>maven-plugin-api</artifactId>
<version>${version.org.apache.maven}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-repository-metadata</artifactId> <artifactId>maven-repository-metadata</artifactId>
<version>${version.org.apache.maven}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-settings</artifactId> <artifactId>maven-settings</artifactId>
<version>${version.org.apache.maven}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven</groupId> <groupId>org.apache.maven</groupId>
<artifactId>maven-settings-builder</artifactId> <artifactId>maven-settings-builder</artifactId>
<version>${version.org.apache.maven}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.mvel</groupId> <groupId>org.mvel</groupId>
<artifactId>mvel2</artifactId> <artifactId>mvel2</artifactId>
<version>${version.org.mvel}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.sisu</groupId> <groupId>org.eclipse.sisu</groupId>
<artifactId>org.eclipse.sisu.inject</artifactId> <artifactId>org.eclipse.sisu.inject</artifactId>
<version>${version.org.eclipse.sisu}</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>com.google.inject</groupId> <groupId>com.google.inject</groupId>
@ -281,15 +245,9 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-servlet</artifactId>
<version>${version.com.google.inject.extensions.guice-servlet}</version>
</dependency>
<dependency> <dependency>
<groupId>org.eclipse.sisu</groupId> <groupId>org.eclipse.sisu</groupId>
<artifactId>org.eclipse.sisu.plexus</artifactId> <artifactId>org.eclipse.sisu.plexus</artifactId>
<version>${version.org.eclipse.sisu}</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>org.sonatype.sisu</groupId> <groupId>org.sonatype.sisu</groupId>
@ -300,62 +258,50 @@
<dependency> <dependency>
<groupId>org.sonatype.plexus</groupId> <groupId>org.sonatype.plexus</groupId>
<artifactId>plexus-cipher</artifactId> <artifactId>plexus-cipher</artifactId>
<version>${version.org.sonatype.plexus.plexus-cipher}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-classworlds</artifactId> <artifactId>plexus-classworlds</artifactId>
<version>${version.org.codehaus.plexus.plexus-classworlds}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-component-annotations</artifactId> <artifactId>plexus-component-annotations</artifactId>
<version>${version.org.codehaus.plexus.plexus-component-annotations}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-interpolation</artifactId> <artifactId>plexus-interpolation</artifactId>
<version>${version.org.codehaus.plexus.plexus-interpolation}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.sonatype.plexus</groupId> <groupId>org.sonatype.plexus</groupId>
<artifactId>plexus-sec-dispatcher</artifactId> <artifactId>plexus-sec-dispatcher</artifactId>
<version>${version.org.codehaus.plexus.plexus-sec-dispatcher}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.codehaus.plexus</groupId> <groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-utils</artifactId> <artifactId>plexus-utils</artifactId>
<version>${version.org.codehaus.plexus.plexus-utils}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven.wagon</groupId> <groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-http</artifactId> <artifactId>wagon-http</artifactId>
<version>${version.org.apache.maven.wagon}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven.wagon</groupId> <groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-http-shared</artifactId> <artifactId>wagon-http-shared</artifactId>
<version>${version.org.apache.maven.wagon}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.maven.wagon</groupId> <groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-provider-api</artifactId> <artifactId>wagon-provider-api</artifactId>
<version>${version.org.apache.maven.wagon}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.thoughtworks.xstream</groupId> <groupId>com.thoughtworks.xstream</groupId>
<artifactId>xstream</artifactId> <artifactId>xstream</artifactId>
<version>${version.com.thoughtworks.xstream}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.google.guava</groupId> <groupId>com.google.guava</groupId>
<artifactId>guava</artifactId> <artifactId>guava</artifactId>
<version>${version.com.google.guava}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.eclipse.jdt.core.compiler</groupId> <groupId>org.eclipse.jdt.core.compiler</groupId>
<artifactId>ecj</artifactId> <artifactId>ecj</artifactId>
<version>${version.org.eclipse.jdt.core.compiler}</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.httpcomponents</groupId> <groupId>org.apache.httpcomponents</groupId>
@ -368,7 +314,6 @@
<dependency> <dependency>
<groupId>com.lowagie</groupId> <groupId>com.lowagie</groupId>
<artifactId>itext</artifactId> <artifactId>itext</artifactId>
<version>${version.com.lowagie}</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>bouncycastle</groupId> <groupId>bouncycastle</groupId>
@ -387,7 +332,6 @@
<dependency> <dependency>
<groupId>org.sonatype.sisu</groupId> <groupId>org.sonatype.sisu</groupId>
<artifactId>sisu-guice</artifactId> <artifactId>sisu-guice</artifactId>
<version>${version.org.sonatype.sisu}</version>
<classifier>no_aop</classifier> <classifier>no_aop</classifier>
</dependency> </dependency>
</dependencies> </dependencies>

View file

@ -151,6 +151,24 @@
</artifactItems> </artifactItems>
</configuration> </configuration>
</execution> </execution>
<execution>
<id>unpack</id>
<phase>compile</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-wildfly-server-subsystem</artifactId>
<version>${project.version}</version>
<type>jar</type>
<includes>default-config/*.xml</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions> </executions>
</plugin> </plugin>
@ -203,30 +221,6 @@
</executions> </executions>
</plugin> </plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack</id>
<phase>compile</phase>
<goals>
<goal>unpack</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-wildfly-server-subsystem</artifactId>
<version>${project.version}</version>
<type>jar</type>
<includes>default-config/*.xml</includes>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
</plugins> </plugins>
</build> </build>

View file

@ -27,11 +27,6 @@
<dependencies> <dependencies>
<module name="org.keycloak.keycloak-common" services="import"/> <module name="org.keycloak.keycloak-common" services="import"/>
<module name="org.keycloak.keycloak-core" services="import"/> <module name="org.keycloak.keycloak-core" services="import"/>
<module name="org.keycloak.keycloak-themes">
<imports>
<include path="META-INF"/>
</imports>
</module>
<module name="org.keycloak.keycloak-js-adapter" services="import"/> <module name="org.keycloak.keycloak-js-adapter" services="import"/>
<module name="org.keycloak.keycloak-kerberos-federation" services="import"/> <module name="org.keycloak.keycloak-kerberos-federation" services="import"/>
<module name="org.keycloak.keycloak-ldap-federation" services="import"/> <module name="org.keycloak.keycloak-ldap-federation" services="import"/>

View file

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ Copyright 2016 Red Hat, Inc. and/or its affiliates
~ and other contributors as indicated by the @author tags.
~
~ Licensed under the Apache License, Version 2.0 (the "License");
~ you may not use this file except in compliance with the License.
~ You may obtain a copy of the License at
~
~ http://www.apache.org/licenses/LICENSE-2.0
~
~ Unless required by applicable law or agreed to in writing, software
~ distributed under the License is distributed on an "AS IS" BASIS,
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
<module xmlns="urn:jboss:module:1.3" name="org.keycloak.keycloak-themes">
<properties>
<property name="jboss.api" value="private"/>
</properties>
<resources>
<artifact name="${org.keycloak:keycloak-themes}"/>
</resources>
<dependencies>
<module name="org.keycloak.keycloak-common"/>
<module name="org.keycloak.keycloak-server-spi"/>
<module name="org.keycloak.keycloak-core"/>
<module name="javax.ws.rs.api"/>
<module name="org.jboss.logging"/>
<module name="org.freemarker"/>
<module name="javax.api"/>
</dependencies>
</module>

View file

@ -29,7 +29,6 @@
<module name="org.keycloak.keycloak-core"/> <module name="org.keycloak.keycloak-core"/>
<module name="org.keycloak.keycloak-server-spi"/> <module name="org.keycloak.keycloak-server-spi"/>
<module name="org.keycloak.keycloak-services"/> <module name="org.keycloak.keycloak-services"/>
<module name="org.keycloak.keycloak-themes"/>
<module name="org.jboss.modules"/> <module name="org.jboss.modules"/>
</dependencies> </dependencies>
</module> </module>

View file

@ -20,7 +20,6 @@
<property name="jboss.api" value="private"/> <property name="jboss.api" value="private"/>
</properties> </properties>
<resources> <resources>
<artifact name="${com.google.inject.extensions:guice-servlet}"/>
<artifact name="${org.sonatype.sisu:sisu-guice::no_aop}"/> <artifact name="${org.sonatype.sisu:sisu-guice::no_aop}"/>
</resources> </resources>
<dependencies> <dependencies>

View file

@ -79,10 +79,6 @@
<groupId>org.keycloak</groupId> <groupId>org.keycloak</groupId>
<artifactId>keycloak-tomcat-adapter-spi</artifactId> <artifactId>keycloak-tomcat-adapter-spi</artifactId>
</dependency> </dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-jboss-adapter-core</artifactId>
</dependency>
<dependency> <dependency>
<groupId>org.bouncycastle</groupId> <groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId> <artifactId>bcprov-jdk15on</artifactId>

View file

@ -46,6 +46,7 @@
<exclude>appclient/**</exclude> <exclude>appclient/**</exclude>
<exclude>copyright.txt</exclude> <exclude>copyright.txt</exclude>
<exclude>README.txt</exclude> <exclude>README.txt</exclude>
<exclude>themes/**</exclude>
</excludes> </excludes>
</fileSet> </fileSet>
<fileSet> <fileSet>
@ -56,6 +57,14 @@
</includes> </includes>
<fileMode>0755</fileMode> <fileMode>0755</fileMode>
</fileSet> </fileSet>
<fileSet>
<directory>target/${project.build.finalName}</directory>
<outputDirectory/>
<includes>
<include>themes/**</include>
</includes>
<fileMode>0444</fileMode>
</fileSet>
<fileSet> <fileSet>
<directory>src/main/welcome-content</directory> <directory>src/main/welcome-content</directory>
<outputDirectory>welcome-content</outputDirectory> <outputDirectory>welcome-content</outputDirectory>

View file

@ -39,27 +39,9 @@ export class AppComponent {
} }
reloadData() { reloadData() {
//angular dont have http interceptor yet this.http.get('/database/products')
this.kc.getToken()
.then(token => {
let headers = new Headers({
'Accept': 'application/json',
'Authorization': 'Bearer ' + token
});
let options = new RequestOptions({ headers });
this.http.get('/database/products', options)
.map(res => res.json()) .map(res => res.json())
.subscribe(prods => this.products = prods, .subscribe(prods => this.products = prods,
error => console.log(error)); error => console.log(error));
})
.catch(error => console.log(error));
}
private handleError(error: Response) {
console.error(error);
return Observable.throw(error.json().error || 'Server error');
} }
} }

View file

@ -1,8 +1,9 @@
import {NgModule} from "@angular/core"; import {NgModule} from "@angular/core";
import {BrowserModule} from "@angular/platform-browser"; import {BrowserModule} from "@angular/platform-browser";
import {HttpModule} from "@angular/http"; import {HttpModule, Http, XHRBackend, RequestOptions} from '@angular/http';
import {KeycloakService} from "./keycloak.service"; import {KeycloakService} from "./keycloak.service";
import {AppComponent} from "./app.component"; import {AppComponent} from "./app.component";
import {KeycloakHttp} from "./keycloak.http";
@NgModule({ @NgModule({
imports: [ imports: [
@ -14,6 +15,17 @@ import {AppComponent} from "./app.component";
], ],
providers: [ providers: [
KeycloakService, KeycloakService,
{
provide: Http,
useFactory:
(
backend: XHRBackend,
defaultOptions: RequestOptions,
keycloakService: KeycloakService
) => new KeycloakHttp(backend, defaultOptions, keycloakService),
deps: [XHRBackend, RequestOptions, KeycloakService]
}
], ],
bootstrap: [ AppComponent ] bootstrap: [ AppComponent ]
}) })

View file

@ -0,0 +1,116 @@
import {Injectable} from "@angular/core";
import {Http, Request, ConnectionBackend, RequestOptions, RequestOptionsArgs, Response, Headers} from "@angular/http";
import {KeycloakService} from "./keycloak.service";
import {Observable} from 'rxjs/Rx';
/**
* This provides a wrapper over the ng2 Http class that insures tokens are refreshed on each request.
*/
@Injectable()
export class KeycloakHttp extends Http {
constructor(_backend: ConnectionBackend, _defaultOptions: RequestOptions, private _keycloakService:KeycloakService) {
super(_backend, _defaultOptions);
}
private setToken(options: RequestOptionsArgs) {
if (options == null || KeycloakService.auth == null || KeycloakService.auth.authz == null || KeycloakService.auth.authz.token == null) {
console.log("Need a token, but no token is available, not setting bearer token.");
return;
}
options.headers.set('Authorization', 'Bearer ' + KeycloakService.auth.authz.token);
}
private configureRequest(f:Function, url:string | Request, options:RequestOptionsArgs, body?: any):Observable<Response> {
let tokenPromise:Promise<string> = this._keycloakService.getToken();
let tokenObservable:Observable<string> = Observable.fromPromise(tokenPromise);
let tokenUpdateObservable:Observable<any> = Observable.create((observer) => {
if (options == null) {
let headers = new Headers();
options = new RequestOptions({ headers: headers });
}
this.setToken(options);
observer.next();
observer.complete();
});
let requestObservable:Observable<Response> = Observable.create((observer) => {
let result;
if (body) {
result = f.apply(this, [url, body, options]);
} else {
result = f.apply(this, [url, options]);
}
result.subscribe((response) => {
observer.next(response);
observer.complete();
});
});
return <Observable<Response>>Observable
.merge(tokenObservable, tokenUpdateObservable, requestObservable, 1) // Insure no concurrency in the merged Observables
.filter((response) => response instanceof Response);
}
/**
* Performs any type of http request. First argument is required, and can either be a url or
* a {@link Request} instance. If the first argument is a url, an optional {@link RequestOptions}
* object can be provided as the 2nd argument. The options object will be merged with the values
* of {@link BaseRequestOptions} before performing the request.
*/
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
return this.configureRequest(super.request, url, options);
}
/**
* Performs a request with `get` http method.
*/
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.configureRequest(super.get, url, options);
}
/**
* Performs a request with `post` http method.
*/
post(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
return this.configureRequest(super.post, url, options, body);
}
/**
* Performs a request with `put` http method.
*/
put(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
return this.configureRequest(super.put, url, options, body);
}
/**
* Performs a request with `delete` http method.
*/
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.configureRequest(super.delete, url, options);
}
/**
* Performs a request with `patch` http method.
*/
patch(url: string, body: any, options?: RequestOptionsArgs): Observable<Response> {
return this.configureRequest(super.patch, url, options, body);
}
/**
* Performs a request with `head` http method.
*/
head(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.configureRequest(super.head, url, options);
}
/**
* Performs a request with `options` http method.
*/
options(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.configureRequest(super.options, url, options);
}
}

View file

@ -17,6 +17,8 @@
package org.keycloak.federation.ldap.mappers; package org.keycloak.federation.ldap.mappers;
import java.util.List;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.federation.ldap.LDAPFederationProvider; import org.keycloak.federation.ldap.LDAPFederationProvider;
import org.keycloak.federation.ldap.LDAPFederationProviderFactory; import org.keycloak.federation.ldap.LDAPFederationProviderFactory;
@ -75,13 +77,13 @@ public abstract class AbstractLDAPFederationMapperFactory implements UserFederat
public void close() { public void close() {
} }
public static ProviderConfigProperty createConfigProperty(String name, String label, String helpText, String type, Object defaultValue) { public static ProviderConfigProperty createConfigProperty(String name, String label, String helpText, String type, List<String> options) {
ProviderConfigProperty configProperty = new ProviderConfigProperty(); ProviderConfigProperty configProperty = new ProviderConfigProperty();
configProperty.setName(name); configProperty.setName(name);
configProperty.setLabel(label); configProperty.setLabel(label);
configProperty.setHelpText(helpText); configProperty.setHelpText(helpText);
configProperty.setType(type); configProperty.setType(type);
configProperty.setDefaultValue(defaultValue); configProperty.setOptions(options);
return configProperty; return configProperty;
} }

View file

@ -48,6 +48,7 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.keycloak.models.RoleModel;
/** /**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
@ -560,6 +561,11 @@ public class GroupLDAPFederationMapper extends AbstractLDAPFederationMapper impl
this.ldapUser = ldapUser; this.ldapUser = ldapUser;
} }
@Override
public boolean hasRole(RoleModel role) {
return super.hasRole(role) || KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
}
@Override @Override
public Set<GroupModel> getGroups() { public Set<GroupModel> getGroups() {
Set<GroupModel> ldapGroupMappings = getLDAPGroupMappingsConverted(); Set<GroupModel> ldapGroupMappings = getLDAPGroupMappingsConverted();

View file

@ -348,7 +348,8 @@ public class RoleLDAPFederationMapper extends AbstractLDAPFederationMapper imple
@Override @Override
public boolean hasRole(RoleModel role) { public boolean hasRole(RoleModel role) {
Set<RoleModel> roles = getRoleMappings(); Set<RoleModel> roles = getRoleMappings();
return KeycloakModelUtils.hasRole(roles, role); return KeycloakModelUtils.hasRole(roles, role)
|| KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
} }
@Override @Override

View file

@ -301,7 +301,7 @@ public class UserAdapter implements CachedUserModel {
for (RoleModel mapping: mappings) { for (RoleModel mapping: mappings) {
if (mapping.hasRole(role)) return true; if (mapping.hasRole(role)) return true;
} }
return false; return KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
} }
@Override @Override

View file

@ -555,6 +555,8 @@ public class UserCacheSession implements UserCache {
} }
UserConsentModel consentModel = new UserConsentModel(client); UserConsentModel consentModel = new UserConsentModel(client);
consentModel.setCreatedDate(cachedConsent.getCreatedDate());
consentModel.setLastUpdatedDate(cachedConsent.getLastUpdatedDate());
for (String roleId : cachedConsent.getRoleIds()) { for (String roleId : cachedConsent.getRoleIds()) {
RoleModel role = session.realms().getRoleById(roleId, realm); RoleModel role = session.realms().getRoleById(roleId, realm);

View file

@ -32,6 +32,8 @@ public class CachedUserConsent {
private final String clientDbId; private final String clientDbId;
private final Set<ProtocolMapperModel> protocolMappers = new HashSet<>(); private final Set<ProtocolMapperModel> protocolMappers = new HashSet<>();
private final Set<String> roleIds = new HashSet<>(); private final Set<String> roleIds = new HashSet<>();
private final Long createdDate;
private final Long lastUpdatedDate;
public CachedUserConsent(UserConsentModel consentModel) { public CachedUserConsent(UserConsentModel consentModel) {
this.clientDbId = consentModel.getClient().getId(); this.clientDbId = consentModel.getClient().getId();
@ -39,6 +41,8 @@ public class CachedUserConsent {
for (RoleModel role : consentModel.getGrantedRoles()) { for (RoleModel role : consentModel.getGrantedRoles()) {
this.roleIds.add(role.getId()); this.roleIds.add(role.getId());
} }
this.createdDate = consentModel.getCreatedDate();
this.lastUpdatedDate = consentModel.getLastUpdatedDate();
} }
public String getClientDbId() { public String getClientDbId() {
@ -52,4 +56,12 @@ public class CachedUserConsent {
public Set<String> getRoleIds() { public Set<String> getRoleIds() {
return roleIds; return roleIds;
} }
public Long getCreatedDate() {
return createdDate;
}
public Long getLastUpdatedDate() {
return lastUpdatedDate;
}
} }

View file

@ -33,11 +33,19 @@ import org.keycloak.models.KeycloakSession;
import java.io.File; import java.io.File;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.io.Writer;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.sql.Connection; import java.sql.Connection;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import liquibase.LabelExpression; import liquibase.LabelExpression;
import liquibase.database.Database;
import liquibase.exception.DatabaseException;
import liquibase.executor.Executor;
import liquibase.executor.ExecutorService;
import liquibase.executor.LoggingExecutor;
import liquibase.statement.core.CreateDatabaseChangeLogTableStatement;
import liquibase.util.StreamUtil;
/** /**
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
@ -96,7 +104,7 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
protected void updateChangeSet(Liquibase liquibase, String changelog, File exportFile) throws LiquibaseException, IOException { protected void updateChangeSet(Liquibase liquibase, String changelog, File exportFile) throws LiquibaseException, IOException {
List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null, new LabelExpression()); List<ChangeSet> changeSets = getChangeSets(liquibase);
if (!changeSets.isEmpty()) { if (!changeSets.isEmpty()) {
List<RanChangeSet> ranChangeSets = liquibase.getDatabase().getRanChangeSetList(); List<RanChangeSet> ranChangeSets = liquibase.getDatabase().getRanChangeSetList();
if (ranChangeSets.isEmpty()) { if (ranChangeSets.isEmpty()) {
@ -110,7 +118,12 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
} }
if (exportFile != null) { if (exportFile != null) {
liquibase.update((Contexts) null, new FileWriter(exportFile)); try (Writer exportWriter = new FileWriter(exportFile)) {
if (ranChangeSets.isEmpty()) {
outputChangeLogTableCreationScript(liquibase, exportWriter);
}
liquibase.update((Contexts) null, new LabelExpression(), exportWriter, false);
}
} else { } else {
liquibase.update((Contexts) null); liquibase.update((Contexts) null);
} }
@ -125,6 +138,27 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
} }
} }
private void outputChangeLogTableCreationScript(Liquibase liquibase, final Writer exportWriter) throws DatabaseException {
Database database = liquibase.getDatabase();
Executor oldTemplate = ExecutorService.getInstance().getExecutor(database);
LoggingExecutor executor = new LoggingExecutor(ExecutorService.getInstance().getExecutor(database), exportWriter, database);
ExecutorService.getInstance().setExecutor(database, executor);
executor.comment("*********************************************************************");
executor.comment("* Keycloak database creation script - apply this script to empty DB *");
executor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
executor.execute(new CreateDatabaseChangeLogTableStatement());
// DatabaseChangeLogLockTable is created before this code is executed and recreated if it does not exist automatically
// in org.keycloak.connections.jpa.updater.liquibase.lock.CustomLockService.init() called indirectly from
// KeycloakApplication constructor (search for waitForLock() call). Hence it is not included in the creation script.
executor.comment("*********************************************************************" + StreamUtil.getLineSeparator());
ExecutorService.getInstance().setExecutor(database, oldTemplate);
}
@Override @Override
public Status validate(Connection connection, String defaultSchema) { public Status validate(Connection connection, String defaultSchema) {
logger.debug("Validating if database is updated"); logger.debug("Validating if database is updated");
@ -160,7 +194,8 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
} }
protected Status validateChangeSet(Liquibase liquibase, String changelog) throws LiquibaseException { protected Status validateChangeSet(Liquibase liquibase, String changelog) throws LiquibaseException {
List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null, new LabelExpression()); List<ChangeSet> changeSets = getChangeSets(liquibase);
if (!changeSets.isEmpty()) { if (!changeSets.isEmpty()) {
if (changeSets.size() == liquibase.getDatabaseChangeLog().getChangeSets().size()) { if (changeSets.size() == liquibase.getDatabaseChangeLog().getChangeSets().size()) {
return Status.EMPTY; return Status.EMPTY;
@ -174,6 +209,15 @@ public class LiquibaseJpaUpdaterProvider implements JpaUpdaterProvider {
} }
} }
@SuppressWarnings("unchecked")
private List<ChangeSet> getChangeSets(Liquibase liquibase) {
// TODO tracked as: https://issues.jboss.org/browse/KEYCLOAK-3730
// TODO: When https://liquibase.jira.com/browse/CORE-2919 is resolved, replace the following two lines with:
// List<ChangeSet> changeSets = liquibase.listUnrunChangeSets((Contexts) null, new LabelExpression(), false);
Method listUnrunChangeSets = Reflections.findDeclaredMethod(Liquibase.class, "listUnrunChangeSets", Contexts.class, LabelExpression.class, boolean.class);
return Reflections.invokeMethod(true, listUnrunChangeSets, List.class, liquibase, (Contexts) null, new LabelExpression(), false);
}
private Liquibase getLiquibaseForKeycloakUpdate(Connection connection, String defaultSchema) throws LiquibaseException { private Liquibase getLiquibaseForKeycloakUpdate(Connection connection, String defaultSchema) throws LiquibaseException {
LiquibaseConnectionProvider liquibaseProvider = session.getProvider(LiquibaseConnectionProvider.class); LiquibaseConnectionProvider liquibaseProvider = session.getProvider(LiquibaseConnectionProvider.class);
return liquibaseProvider.getLiquibase(connection, defaultSchema); return liquibaseProvider.getLiquibase(connection, defaultSchema);

View file

@ -18,6 +18,7 @@
package org.keycloak.models.jpa; package org.keycloak.models.jpa;
import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.common.util.Time;
import org.keycloak.component.ComponentModel; import org.keycloak.component.ComponentModel;
import org.keycloak.credential.CredentialModel; import org.keycloak.credential.CredentialModel;
import org.keycloak.credential.UserCredentialStore; import org.keycloak.credential.UserCredentialStore;
@ -201,10 +202,14 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + userId + "]"); throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + userId + "]");
} }
long currentTime = Time.currentTimeMillis();
consentEntity = new UserConsentEntity(); consentEntity = new UserConsentEntity();
consentEntity.setId(KeycloakModelUtils.generateId()); consentEntity.setId(KeycloakModelUtils.generateId());
consentEntity.setUser(em.getReference(UserEntity.class, userId)); consentEntity.setUser(em.getReference(UserEntity.class, userId));
consentEntity.setClientId(clientId); consentEntity.setClientId(clientId);
consentEntity.setCreatedDate(currentTime);
consentEntity.setLastUpdatedDate(currentTime);
em.persist(consentEntity); em.persist(consentEntity);
em.flush(); em.flush();
@ -277,6 +282,8 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
throw new ModelException("Client with id " + entity.getClientId() + " is not available"); throw new ModelException("Client with id " + entity.getClientId() + " is not available");
} }
UserConsentModel model = new UserConsentModel(client); UserConsentModel model = new UserConsentModel(client);
model.setCreatedDate(entity.getCreatedDate());
model.setLastUpdatedDate(entity.getLastUpdatedDate());
Collection<UserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles(); Collection<UserConsentRoleEntity> grantedRoleEntities = entity.getGrantedRoles();
if (grantedRoleEntities != null) { if (grantedRoleEntities != null) {
@ -346,6 +353,8 @@ public class JpaUserProvider implements UserProvider, UserCredentialStore {
em.remove(toRemove); em.remove(toRemove);
} }
consentEntity.setLastUpdatedDate(Time.currentTimeMillis());
em.flush(); em.flush();
} }

View file

@ -352,7 +352,8 @@ public class UserAdapter implements UserModel, JpaModel<UserEntity> {
@Override @Override
public boolean hasRole(RoleModel role) { public boolean hasRole(RoleModel role) {
Set<RoleModel> roles = getRoleMappings(); Set<RoleModel> roles = getRoleMappings();
return KeycloakModelUtils.hasRole(roles, role); return KeycloakModelUtils.hasRole(roles, role)
|| KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
} }
protected TypedQuery<UserRoleMappingEntity> getUserRoleMappingEntityTypedQuery(RoleModel role) { protected TypedQuery<UserRoleMappingEntity> getUserRoleMappingEntityTypedQuery(RoleModel role) {

View file

@ -68,6 +68,12 @@ public class UserConsentEntity {
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "userConsent") @OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true, mappedBy = "userConsent")
Collection<UserConsentProtocolMapperEntity> grantedProtocolMappers = new ArrayList<UserConsentProtocolMapperEntity>(); Collection<UserConsentProtocolMapperEntity> grantedProtocolMappers = new ArrayList<UserConsentProtocolMapperEntity>();
@Column(name = "CREATED_DATE")
private Long createdDate;
@Column(name = "LAST_UPDATED_DATE")
private Long lastUpdatedDate;
public String getId() { public String getId() {
return id; return id;
} }
@ -108,6 +114,22 @@ public class UserConsentEntity {
this.grantedProtocolMappers = grantedProtocolMappers; this.grantedProtocolMappers = grantedProtocolMappers;
} }
public Long getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Long createdDate) {
this.createdDate = createdDate;
}
public Long getLastUpdatedDate() {
return lastUpdatedDate;
}
public void setLastUpdatedDate(Long lastUpdatedDate) {
this.lastUpdatedDate = lastUpdatedDate;
}
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (this == o) return true; if (this == o) return true;
@ -125,5 +147,4 @@ public class UserConsentEntity {
public int hashCode() { public int hashCode() {
return id.hashCode(); return id.hashCode();
} }
} }

View file

@ -36,4 +36,5 @@
<include file="META-INF/jpa-changelog-authz-master.xml"/> <include file="META-INF/jpa-changelog-authz-master.xml"/>
<include file="META-INF/jpa-changelog-2.1.0.xml"/> <include file="META-INF/jpa-changelog-2.1.0.xml"/>
<include file="META-INF/jpa-changelog-2.2.0.xml"/> <include file="META-INF/jpa-changelog-2.2.0.xml"/>
<include file="META-INF/jpa-changelog-2.3.0.xml"/>
</databaseChangeLog> </databaseChangeLog>

View file

@ -31,6 +31,7 @@
</createTable> </createTable>
<addPrimaryKey columnNames="ID" constraintName="CONSTR_FEDERATED_USER" tableName="FEDERATED_USER"/> <addPrimaryKey columnNames="ID" constraintName="CONSTR_FEDERATED_USER" tableName="FEDERATED_USER"/>
<dropDefaultValue tableName="USER_ENTITY" columnName="TOTP" />
<dropColumn tableName="USER_ENTITY" columnName="TOTP" /> <dropColumn tableName="USER_ENTITY" columnName="TOTP" />
<addColumn tableName="IDENTITY_PROVIDER"> <addColumn tableName="IDENTITY_PROVIDER">
@ -47,7 +48,11 @@
<dropColumn tableName="REALM" columnName="PUBLIC_KEY" /> <dropColumn tableName="REALM" columnName="PUBLIC_KEY" />
<dropColumn tableName="REALM" columnName="CERTIFICATE" /> <dropColumn tableName="REALM" columnName="CERTIFICATE" />
<addColumn tableName="USER_CONSENT">
<column name="CREATED_DATE" type="BIGINT"/>
<column name="LAST_UPDATED_DATE" type="BIGINT"/>
</addColumn>
</changeSet> </changeSet>
</databaseChangeLog> </databaseChangeLog>

View file

@ -21,6 +21,7 @@ import com.mongodb.BasicDBObject;
import com.mongodb.DBObject; import com.mongodb.DBObject;
import com.mongodb.QueryBuilder; import com.mongodb.QueryBuilder;
import org.keycloak.common.util.MultivaluedHashMap; import org.keycloak.common.util.MultivaluedHashMap;
import org.keycloak.common.util.Time;
import org.keycloak.component.ComponentModel; import org.keycloak.component.ComponentModel;
import org.keycloak.connections.mongo.api.MongoStore; import org.keycloak.connections.mongo.api.MongoStore;
import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext; import org.keycloak.connections.mongo.api.context.MongoStoreInvocationContext;
@ -524,9 +525,13 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + userId + "]"); throw new ModelDuplicateException("Consent already exists for client [" + clientId + "] and user [" + userId + "]");
} }
long currentTime = Time.currentTimeMillis();
MongoUserConsentEntity consentEntity = new MongoUserConsentEntity(); MongoUserConsentEntity consentEntity = new MongoUserConsentEntity();
consentEntity.setUserId(userId); consentEntity.setUserId(userId);
consentEntity.setClientId(clientId); consentEntity.setClientId(clientId);
consentEntity.setCreatedDate(currentTime);
consentEntity.setLastUpdatedDate(currentTime);
fillEntityFromModel(consent, consentEntity); fillEntityFromModel(consent, consentEntity);
getMongoStore().insertEntity(consentEntity, invocationContext); getMongoStore().insertEntity(consentEntity, invocationContext);
} }
@ -568,6 +573,8 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
throw new ModelException("Client with id " + entity.getClientId() + " is not available"); throw new ModelException("Client with id " + entity.getClientId() + " is not available");
} }
UserConsentModel model = new UserConsentModel(client); UserConsentModel model = new UserConsentModel(client);
model.setCreatedDate(entity.getCreatedDate());
model.setLastUpdatedDate(entity.getLastUpdatedDate());
for (String roleId : entity.getGrantedRoles()) { for (String roleId : entity.getGrantedRoles()) {
RoleModel roleModel = realm.getRoleById(roleId); RoleModel roleModel = realm.getRoleById(roleId);
@ -596,6 +603,7 @@ public class MongoUserProvider implements UserProvider, UserCredentialStore {
protMapperIds.add(protMapperModel.getId()); protMapperIds.add(protMapperModel.getId());
} }
consentEntity.setGrantedProtocolMappers(protMapperIds); consentEntity.setGrantedProtocolMappers(protMapperIds);
consentEntity.setLastUpdatedDate(Time.currentTimeMillis());
} }
@Override @Override

View file

@ -268,7 +268,8 @@ public class UserAdapter extends AbstractMongoAdapter<MongoUserEntity> implement
@Override @Override
public boolean hasRole(RoleModel role) { public boolean hasRole(RoleModel role) {
Set<RoleModel> roles = getRoleMappings(); Set<RoleModel> roles = getRoleMappings();
return KeycloakModelUtils.hasRole(roles, role); return KeycloakModelUtils.hasRole(roles, role)
|| KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
} }
@Override @Override

View file

@ -29,6 +29,8 @@ public class UserConsentEntity extends AbstractIdentifiableEntity {
private String clientId; private String clientId;
private List<String> grantedRoles = new ArrayList<String>(); private List<String> grantedRoles = new ArrayList<String>();
private List<String> grantedProtocolMappers = new ArrayList<String>(); private List<String> grantedProtocolMappers = new ArrayList<String>();
private Long createdDate;
private Long lastUpdatedDate;
public String getUserId() { public String getUserId() {
return userId; return userId;
@ -61,4 +63,20 @@ public class UserConsentEntity extends AbstractIdentifiableEntity {
public void setGrantedProtocolMappers(List<String> grantedProtocolMappers) { public void setGrantedProtocolMappers(List<String> grantedProtocolMappers) {
this.grantedProtocolMappers = grantedProtocolMappers; this.grantedProtocolMappers = grantedProtocolMappers;
} }
public Long getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Long createdDate) {
this.createdDate = createdDate;
}
public Long getLastUpdatedDate() {
return lastUpdatedDate;
}
public void setLastUpdatedDate(Long lastUpdatedDate) {
this.lastUpdatedDate = lastUpdatedDate;
}
} }

View file

@ -80,6 +80,7 @@
<!-- Authorization Drools Policy Provider --> <!-- Authorization Drools Policy Provider -->
<version.org.drools>6.4.0.Final</version.org.drools> <version.org.drools>6.4.0.Final</version.org.drools>
<version.jboss-integration-platform>6.0.6.Final</version.jboss-integration-platform>
<!-- Others --> <!-- Others -->
<apacheds.version>2.0.0-M17</apacheds.version> <apacheds.version>2.0.0-M17</apacheds.version>

View file

@ -30,6 +30,7 @@ import org.keycloak.migration.migrators.MigrateTo1_9_2;
import org.keycloak.migration.migrators.MigrateTo2_0_0; import org.keycloak.migration.migrators.MigrateTo2_0_0;
import org.keycloak.migration.migrators.MigrateTo2_1_0; import org.keycloak.migration.migrators.MigrateTo2_1_0;
import org.keycloak.migration.migrators.MigrateTo2_2_0; import org.keycloak.migration.migrators.MigrateTo2_2_0;
import org.keycloak.migration.migrators.MigrateTo2_3_0;
import org.keycloak.migration.migrators.Migration; import org.keycloak.migration.migrators.Migration;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
@ -53,6 +54,7 @@ public class MigrationModelManager {
new MigrateTo2_0_0(), new MigrateTo2_0_0(),
new MigrateTo2_1_0(), new MigrateTo2_1_0(),
new MigrateTo2_2_0(), new MigrateTo2_2_0(),
new MigrateTo2_3_0(),
}; };
public static void migrate(KeycloakSession session) { public static void migrate(KeycloakSession session) {

View file

@ -0,0 +1,69 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.migration.migrators;
import java.util.LinkedList;
import java.util.List;
import org.keycloak.migration.ModelVersion;
import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientTemplateModel;
import org.keycloak.models.KeycloakSession;
import org.keycloak.models.ProtocolMapperContainerModel;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.RealmModel;
/**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/
public class MigrateTo2_3_0 implements Migration {
public static final ModelVersion VERSION = new ModelVersion("2.3.0");
@Override
public void migrate(KeycloakSession session) {
for (RealmModel realm : session.realms().getRealms()) {
for (ClientModel client : realm.getClients()) {
updateProtocolMappers(client);
}
for (ClientTemplateModel clientTemplate : realm.getClientTemplates()) {
updateProtocolMappers(clientTemplate);
}
}
}
private void updateProtocolMappers(ProtocolMapperContainerModel client) {
List<ProtocolMapperModel> toUpdate = new LinkedList<>();
for (ProtocolMapperModel mapper : client.getProtocolMappers()) {
if (!mapper.getConfig().containsKey("userinfo.token.claim") && mapper.getConfig().containsKey("id.token.claim")) {
mapper.getConfig().put("userinfo.token.claim", mapper.getConfig().get("id.token.claim"));
toUpdate.add(mapper);
}
}
for (ProtocolMapperModel mapper : toUpdate) {
client.updateProtocolMapper(mapper);
}
}
@Override
public ModelVersion getVersion() {
return VERSION;
}
}

View file

@ -73,6 +73,8 @@ public interface KeycloakSession {
<T extends Provider> Set<T> getAllProviders(Class<T> clazz); <T extends Provider> Set<T> getAllProviders(Class<T> clazz);
Class<? extends Provider> getProviderClass(String providerClassName);
Object getAttribute(String attribute); Object getAttribute(String attribute);
Object removeAttribute(String attribute); Object removeAttribute(String attribute);
void setAttribute(String name, Object value); void setAttribute(String name, Object value);

View file

@ -28,8 +28,24 @@ public interface RoleMapperModel {
Set<RoleModel> getClientRoleMappings(ClientModel app); Set<RoleModel> getClientRoleMappings(ClientModel app);
/**
* Returns {@code true} if this object is directly or indirectly assigned the given role, {@code false} otherwise.
* <p>
* For example, {@code true} is returned for hasRole(R) if:
* <ul>
* <li>R is directly assigned to this object</li>
* <li>R is not assigned to this object but this object belongs to a group G which is assigned the role R</li>
* <li>R is not assigned to this object but this object belongs to a group G, and G belongs to group H which is assigned the role R</li>
* </ul>
* @param role
* @return see description
*/
boolean hasRole(RoleModel role); boolean hasRole(RoleModel role);
/**
* Grants the given role to this object.
* @param role
*/
void grantRole(RoleModel role); void grantRole(RoleModel role);
Set<RoleModel> getRoleMappings(); Set<RoleModel> getRoleMappings();

View file

@ -28,6 +28,8 @@ public class UserConsentModel {
private final ClientModel client; private final ClientModel client;
private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>(); private Set<ProtocolMapperModel> protocolMappers = new HashSet<ProtocolMapperModel>();
private Set<RoleModel> roles = new HashSet<RoleModel>(); private Set<RoleModel> roles = new HashSet<RoleModel>();
private Long createdDate;
private Long lastUpdatedDate;
public UserConsentModel(ClientModel client) { public UserConsentModel(ClientModel client) {
this.client = client; this.client = client;
@ -67,4 +69,19 @@ public class UserConsentModel {
return false; return false;
} }
public Long getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Long createdDate) {
this.createdDate = createdDate;
}
public Long getLastUpdatedDate() {
return lastUpdatedDate;
}
public void setLastUpdatedDate(Long lastUpdatedDate) {
this.lastUpdatedDate = lastUpdatedDate;
}
} }

View file

@ -47,10 +47,8 @@ public class ComponentUtil {
} }
public static ComponentFactory getComponentFactory(KeycloakSession session, ComponentModel component) { public static ComponentFactory getComponentFactory(KeycloakSession session, ComponentModel component) {
Class<? extends Provider> provider; Class<? extends Provider> provider = session.getProviderClass(component.getProviderType());
try { if (provider == null) {
provider = (Class<? extends Provider>) Class.forName(component.getProviderType());
} catch (ClassNotFoundException e) {
throw new RuntimeException("Invalid provider type '" + component.getProviderType() + "'"); throw new RuntimeException("Invalid provider type '" + component.getProviderType() + "'");
} }

View file

@ -70,6 +70,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.StreamSupport;
/** /**
* Set of helper methods, which are useful in various model implementations. * Set of helper methods, which are useful in various model implementations.
@ -266,6 +267,43 @@ public final class KeycloakModelUtils {
return false; return false;
} }
/**
* Checks whether the {@code targetRole} is contained in the given group or its parents
* (if requested)
* @param group Group to check role for
* @param targetRole
* @param checkParentGroup When {@code true}, also parent group is recursively checked for role
* @return true if targetRole is in roles (directly or indirectly via composite role)
*/
public static boolean hasRoleFromGroup(GroupModel group, RoleModel targetRole, boolean checkParentGroup) {
if (group.hasRole(targetRole))
return true;
if (checkParentGroup) {
GroupModel parent = group.getParent();
return parent != null && hasRoleFromGroup(parent, targetRole, true);
}
return false;
}
/**
* Checks whether the {@code targetRole} is contained in any of the {@code groups} or their parents
* (if requested)
* @param groups
* @param targetRole
* @param checkParentGroup When {@code true}, also parent group is recursively checked for role
* @return true if targetRole is in roles (directly or indirectly via composite role)
*/
public static boolean hasRoleFromGroup(Iterable<GroupModel> groups, RoleModel targetRole, boolean checkParentGroup) {
if (groups == null) {
return false;
}
return StreamSupport.stream(groups.spliterator(), false)
.anyMatch(group -> hasRoleFromGroup(group, targetRole, checkParentGroup));
}
/** /**
* *
* @param groups * @param groups

View file

@ -710,6 +710,8 @@ public class ModelToRepresentation {
consentRep.setGrantedProtocolMappers(grantedProtocolMappers); consentRep.setGrantedProtocolMappers(grantedProtocolMappers);
consentRep.setGrantedRealmRoles(grantedRealmRoles); consentRep.setGrantedRealmRoles(grantedRealmRoles);
consentRep.setGrantedClientRoles(grantedClientRoles); consentRep.setGrantedClientRoles(grantedClientRoles);
consentRep.setCreatedDate(model.getCreatedDate());
consentRep.setLastUpdatedDate(model.getLastUpdatedDate());
return consentRep; return consentRep;
} }
@ -780,6 +782,7 @@ public class ModelToRepresentation {
propRep.setLabel(prop.getLabel()); propRep.setLabel(prop.getLabel());
propRep.setType(prop.getType()); propRep.setType(prop.getType());
propRep.setDefaultValue(prop.getDefaultValue()); propRep.setDefaultValue(prop.getDefaultValue());
propRep.setOptions(prop.getOptions());
propRep.setHelpText(prop.getHelpText()); propRep.setHelpText(prop.getHelpText());
propRep.setSecret(prop.isSecret()); propRep.setSecret(prop.isSecret());
return propRep; return propRep;

View file

@ -1605,6 +1605,8 @@ public class RepresentationToModel {
} }
UserConsentModel consentModel = new UserConsentModel(client); UserConsentModel consentModel = new UserConsentModel(client);
consentModel.setCreatedDate(consentRep.getCreatedDate());
consentModel.setLastUpdatedDate(consentRep.getLastUpdatedDate());
if (consentRep.getGrantedRealmRoles() != null) { if (consentRep.getGrantedRealmRoles() != null) {
for (String roleName : consentRep.getGrantedRealmRoles()) { for (String roleName : consentRep.getGrantedRealmRoles()) {

View file

@ -17,6 +17,8 @@
package org.keycloak.provider; package org.keycloak.provider;
import java.util.List;
/** /**
* @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 $
@ -46,6 +48,7 @@ public class ProviderConfigProperty {
protected String helpText; protected String helpText;
protected String type = STRING_TYPE; protected String type = STRING_TYPE;
protected Object defaultValue; protected Object defaultValue;
protected List<String> options;
protected boolean secret; protected boolean secret;
public ProviderConfigProperty() { public ProviderConfigProperty() {
@ -96,6 +99,14 @@ public class ProviderConfigProperty {
this.defaultValue = defaultValue; this.defaultValue = defaultValue;
} }
public List<String> getOptions() {
return options;
}
public void setOptions(List<String> options) {
this.options = options;
}
public String getHelpText() { public String getHelpText() {
return helpText; return helpText;
} }

View file

@ -17,6 +17,7 @@
package org.keycloak.provider; package org.keycloak.provider;
import java.util.Arrays;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
@ -43,14 +44,17 @@ public class ProviderConfigurationBuilder {
return this; return this;
} }
public ProviderConfigurationBuilder property(String name, String label, String helpText, String type, Object defaultValue, boolean secret) { public ProviderConfigurationBuilder property(String name, String label, String helpText, String type, Object defaultValue, List<String> options, boolean secret) {
ProviderConfigProperty property = new ProviderConfigProperty(name, label, helpText, type, defaultValue); ProviderConfigProperty property = new ProviderConfigProperty(name, label, helpText, type, defaultValue);
property.setOptions(options);
property.setSecret(secret); property.setSecret(secret);
properties.add(property); properties.add(property);
return this; return this;
} }
public ProviderConfigurationBuilder property(String name, String label, String helpText, String type, Object defaultValue) { public ProviderConfigurationBuilder property(String name, String label, String helpText, String type, Object defaultValue, List<String> options) {
properties.add(new ProviderConfigProperty(name, label, helpText, type, defaultValue)); ProviderConfigProperty property = new ProviderConfigProperty(name, label, helpText, type, defaultValue);
property.setOptions(options);
properties.add(property);
return this; return this;
} }
@ -65,6 +69,7 @@ public class ProviderConfigurationBuilder {
private String helpText; private String helpText;
private String type; private String type;
private Object defaultValue; private Object defaultValue;
private List<String> options;
private boolean secret; private boolean secret;
public ProviderConfigPropertyBuilder name(String name) { public ProviderConfigPropertyBuilder name(String name) {
@ -92,6 +97,11 @@ public class ProviderConfigurationBuilder {
return this; return this;
} }
public ProviderConfigPropertyBuilder options(String... options) {
this.options = Arrays.asList(options);
return this;
}
public ProviderConfigPropertyBuilder secret(boolean secret) { public ProviderConfigPropertyBuilder secret(boolean secret) {
this.secret = secret; this.secret = secret;
return this; return this;
@ -104,6 +114,7 @@ public class ProviderConfigurationBuilder {
property.setHelpText(helpText); property.setHelpText(helpText);
property.setType(type); property.setType(type);
property.setDefaultValue(defaultValue); property.setDefaultValue(defaultValue);
property.setOptions(options);
property.setSecret(secret); property.setSecret(secret);
ProviderConfigurationBuilder.this.properties.add(property); ProviderConfigurationBuilder.this.properties.add(property);
return ProviderConfigurationBuilder.this; return ProviderConfigurationBuilder.this;

View file

@ -172,7 +172,8 @@ public abstract class AbstractUserAdapter implements UserModel {
@Override @Override
public boolean hasRole(RoleModel role) { public boolean hasRole(RoleModel role) {
Set<RoleModel> roles = getRoleMappings(); Set<RoleModel> roles = getRoleMappings();
return KeycloakModelUtils.hasRole(roles, role); return KeycloakModelUtils.hasRole(roles, role)
|| KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
} }
@Override @Override

View file

@ -177,7 +177,8 @@ public abstract class AbstractUserAdapterFederatedStorage implements UserModel {
@Override @Override
public boolean hasRole(RoleModel role) { public boolean hasRole(RoleModel role) {
Set<RoleModel> roles = getRoleMappings(); Set<RoleModel> roles = getRoleMappings();
return KeycloakModelUtils.hasRole(roles, role); return KeycloakModelUtils.hasRole(roles, role)
|| KeycloakModelUtils.hasRoleFromGroup(getGroups(), role, true);
} }
@Override @Override

View file

@ -17,6 +17,7 @@
package org.keycloak.authentication; package org.keycloak.authentication;
import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
import org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator; import org.keycloak.authentication.authenticators.browser.AbstractUsernameFormAuthenticator;
@ -63,7 +64,7 @@ import java.util.Map;
*/ */
public class AuthenticationProcessor { public class AuthenticationProcessor {
public static final String CURRENT_AUTHENTICATION_EXECUTION = "current.authentication.execution"; public static final String CURRENT_AUTHENTICATION_EXECUTION = "current.authentication.execution";
protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER; protected static final Logger logger = Logger.getLogger(AuthenticationProcessor.class);
protected RealmModel realm; protected RealmModel realm;
protected UserSessionModel userSession; protected UserSessionModel userSession;
protected ClientSessionModel clientSession; protected ClientSessionModel clientSession;
@ -561,25 +562,25 @@ public class AuthenticationProcessor {
if (failure instanceof AuthenticationFlowException) { if (failure instanceof AuthenticationFlowException) {
AuthenticationFlowException e = (AuthenticationFlowException) failure; AuthenticationFlowException e = (AuthenticationFlowException) failure;
if (e.getError() == AuthenticationFlowError.INVALID_USER) { if (e.getError() == AuthenticationFlowError.INVALID_USER) {
logger.failedAuthentication(e); ServicesLogger.LOGGER.failedAuthentication(e);
event.error(Errors.USER_NOT_FOUND); event.error(Errors.USER_NOT_FOUND);
return ErrorPage.error(session, Messages.INVALID_USER); return ErrorPage.error(session, Messages.INVALID_USER);
} else if (e.getError() == AuthenticationFlowError.USER_DISABLED) { } else if (e.getError() == AuthenticationFlowError.USER_DISABLED) {
logger.failedAuthentication(e); ServicesLogger.LOGGER.failedAuthentication(e);
event.error(Errors.USER_DISABLED); event.error(Errors.USER_DISABLED);
return ErrorPage.error(session, Messages.ACCOUNT_DISABLED); return ErrorPage.error(session, Messages.ACCOUNT_DISABLED);
} else if (e.getError() == AuthenticationFlowError.USER_TEMPORARILY_DISABLED) { } else if (e.getError() == AuthenticationFlowError.USER_TEMPORARILY_DISABLED) {
logger.failedAuthentication(e); ServicesLogger.LOGGER.failedAuthentication(e);
event.error(Errors.USER_TEMPORARILY_DISABLED); event.error(Errors.USER_TEMPORARILY_DISABLED);
return ErrorPage.error(session, Messages.INVALID_USER); return ErrorPage.error(session, Messages.INVALID_USER);
} else if (e.getError() == AuthenticationFlowError.INVALID_CLIENT_SESSION) { } else if (e.getError() == AuthenticationFlowError.INVALID_CLIENT_SESSION) {
logger.failedAuthentication(e); ServicesLogger.LOGGER.failedAuthentication(e);
event.error(Errors.INVALID_CODE); event.error(Errors.INVALID_CODE);
return ErrorPage.error(session, Messages.INVALID_CODE); return ErrorPage.error(session, Messages.INVALID_CODE);
} else if (e.getError() == AuthenticationFlowError.EXPIRED_CODE) { } else if (e.getError() == AuthenticationFlowError.EXPIRED_CODE) {
logger.failedAuthentication(e); ServicesLogger.LOGGER.failedAuthentication(e);
event.error(Errors.EXPIRED_CODE); event.error(Errors.EXPIRED_CODE);
return ErrorPage.error(session, Messages.EXPIRED_CODE); return ErrorPage.error(session, Messages.EXPIRED_CODE);
@ -604,13 +605,13 @@ public class AuthenticationProcessor {
return processor.authenticate(); return processor.authenticate();
} else { } else {
logger.failedAuthentication(e); ServicesLogger.LOGGER.failedAuthentication(e);
event.error(Errors.INVALID_USER_CREDENTIALS); event.error(Errors.INVALID_USER_CREDENTIALS);
return ErrorPage.error(session, Messages.INVALID_USER); return ErrorPage.error(session, Messages.INVALID_USER);
} }
} else { } else {
logger.failedAuthentication(failure); ServicesLogger.LOGGER.failedAuthentication(failure);
event.error(Errors.INVALID_USER_CREDENTIALS); event.error(Errors.INVALID_USER_CREDENTIALS);
return ErrorPage.error(session, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST); return ErrorPage.error(session, Messages.UNEXPECTED_ERROR_HANDLING_REQUEST);
} }
@ -620,7 +621,7 @@ public class AuthenticationProcessor {
public Response handleClientAuthException(Exception failure) { public Response handleClientAuthException(Exception failure) {
if (failure instanceof AuthenticationFlowException) { if (failure instanceof AuthenticationFlowException) {
AuthenticationFlowException e = (AuthenticationFlowException) failure; AuthenticationFlowException e = (AuthenticationFlowException) failure;
logger.failedClientAuthentication(e); ServicesLogger.LOGGER.failedClientAuthentication(e);
if (e.getError() == AuthenticationFlowError.CLIENT_NOT_FOUND) { if (e.getError() == AuthenticationFlowError.CLIENT_NOT_FOUND) {
event.error(Errors.CLIENT_NOT_FOUND); event.error(Errors.CLIENT_NOT_FOUND);
return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "invalid_client", "Could not find client"); return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "invalid_client", "Could not find client");
@ -635,7 +636,7 @@ public class AuthenticationProcessor {
return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", e.getError().toString() + ": " + e.getMessage()); return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", e.getError().toString() + ": " + e.getMessage());
} }
} else { } else {
logger.errorAuthenticatingClient(failure); ServicesLogger.LOGGER.errorAuthenticatingClient(failure);
event.error(Errors.INVALID_CLIENT_CREDENTIALS); event.error(Errors.INVALID_CLIENT_CREDENTIALS);
return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Unexpected error when authenticating client: " + failure.getMessage()); return ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Unexpected error when authenticating client: " + failure.getMessage());
} }

View file

@ -17,6 +17,7 @@
package org.keycloak.authentication; package org.keycloak.authentication;
import org.jboss.logging.Logger;
import org.keycloak.events.Details; import org.keycloak.events.Details;
import org.keycloak.events.Errors; import org.keycloak.events.Errors;
import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.AuthenticationExecutionModel;
@ -35,7 +36,7 @@ import java.util.List;
*/ */
public class ClientAuthenticationFlow implements AuthenticationFlow { public class ClientAuthenticationFlow implements AuthenticationFlow {
protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(ClientAuthenticationFlow.class);
Response alternativeChallenge = null; Response alternativeChallenge = null;
AuthenticationProcessor processor; AuthenticationProcessor processor;
@ -73,7 +74,7 @@ public class ClientAuthenticationFlow implements AuthenticationFlow {
// Fallback to secret just in case (for backwards compatibility) // Fallback to secret just in case (for backwards compatibility)
if (expectedClientAuthType == null) { if (expectedClientAuthType == null) {
expectedClientAuthType = KeycloakModelUtils.getDefaultClientAuthenticatorType(); expectedClientAuthType = KeycloakModelUtils.getDefaultClientAuthenticatorType();
logger.authMethodFallback(client.getClientId(), expectedClientAuthType); ServicesLogger.LOGGER.authMethodFallback(client.getClientId(), expectedClientAuthType);
} }
// Check if client authentication matches // Check if client authentication matches
@ -154,7 +155,7 @@ public class ClientAuthenticationFlow implements AuthenticationFlow {
} else if (status == FlowStatus.FAILURE_CHALLENGE) { } else if (status == FlowStatus.FAILURE_CHALLENGE) {
return sendChallenge(result, execution); return sendChallenge(result, execution);
} else { } else {
logger.unknownResultStatus(); ServicesLogger.LOGGER.unknownResultStatus();
throw new AuthenticationFlowException(AuthenticationFlowError.INTERNAL_ERROR); throw new AuthenticationFlowException(AuthenticationFlowError.INTERNAL_ERROR);
} }
} }

View file

@ -17,6 +17,7 @@
package org.keycloak.authentication; package org.keycloak.authentication;
import org.jboss.logging.Logger;
import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.AuthenticationFlowModel; import org.keycloak.models.AuthenticationFlowModel;
import org.keycloak.models.ClientSessionModel; import org.keycloak.models.ClientSessionModel;
@ -32,7 +33,7 @@ import java.util.List;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class DefaultAuthenticationFlow implements AuthenticationFlow { public class DefaultAuthenticationFlow implements AuthenticationFlow {
protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(DefaultAuthenticationFlow.class);
Response alternativeChallenge = null; Response alternativeChallenge = null;
AuthenticationExecutionModel challengedAlternativeExecution = null; AuthenticationExecutionModel challengedAlternativeExecution = null;
boolean alternativeSuccessful = false; boolean alternativeSuccessful = false;
@ -247,7 +248,7 @@ public class DefaultAuthenticationFlow implements AuthenticationFlow {
return processor.authenticate(); return processor.authenticate();
default: default:
logger.debugv("authenticator INTERNAL_ERROR: {0}", execution.getAuthenticator()); logger.debugv("authenticator INTERNAL_ERROR: {0}", execution.getAuthenticator());
logger.unknownResultStatus(); ServicesLogger.LOGGER.unknownResultStatus();
throw new AuthenticationFlowException(AuthenticationFlowError.INTERNAL_ERROR); throw new AuthenticationFlowException(AuthenticationFlowError.INTERNAL_ERROR);
} }
} }

View file

@ -39,15 +39,13 @@ import javax.ws.rs.core.Response;
*/ */
public class IdpConfirmLinkAuthenticator extends AbstractIdpAuthenticator { public class IdpConfirmLinkAuthenticator extends AbstractIdpAuthenticator {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
@Override @Override
protected void authenticateImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext serializedCtx, BrokeredIdentityContext brokerContext) { protected void authenticateImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext serializedCtx, BrokeredIdentityContext brokerContext) {
ClientSessionModel clientSession = context.getClientSession(); ClientSessionModel clientSession = context.getClientSession();
String existingUserInfo = clientSession.getNote(EXISTING_USER_INFO); String existingUserInfo = clientSession.getNote(EXISTING_USER_INFO);
if (existingUserInfo == null) { if (existingUserInfo == null) {
logger.noDuplicationDetected(); ServicesLogger.LOGGER.noDuplicationDetected();
context.attempted(); context.attempted();
return; return;
} }

View file

@ -17,6 +17,7 @@
package org.keycloak.authentication.authenticators.broker; package org.keycloak.authentication.authenticators.broker;
import org.jboss.logging.Logger;
import org.keycloak.authentication.AuthenticationFlowContext; import org.keycloak.authentication.AuthenticationFlowContext;
import org.keycloak.authentication.authenticators.broker.util.ExistingUserInfo; import org.keycloak.authentication.authenticators.broker.util.ExistingUserInfo;
import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext; import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
@ -39,7 +40,7 @@ import java.util.Map;
*/ */
public class IdpCreateUserIfUniqueAuthenticator extends AbstractIdpAuthenticator { public class IdpCreateUserIfUniqueAuthenticator extends AbstractIdpAuthenticator {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static Logger logger = Logger.getLogger(IdpCreateUserIfUniqueAuthenticator.class);
@Override @Override
@ -59,7 +60,7 @@ public class IdpCreateUserIfUniqueAuthenticator extends AbstractIdpAuthenticator
String username = getUsername(context, serializedCtx, brokerContext); String username = getUsername(context, serializedCtx, brokerContext);
if (username == null) { if (username == null) {
logger.resetFlow(realm.isRegistrationEmailAsUsername() ? "Email" : "Username"); ServicesLogger.LOGGER.resetFlow(realm.isRegistrationEmailAsUsername() ? "Email" : "Username");
context.getClientSession().setNote(ENFORCE_UPDATE_PROFILE, "true"); context.getClientSession().setNote(ENFORCE_UPDATE_PROFILE, "true");
context.resetFlow(); context.resetFlow();
return; return;

View file

@ -17,6 +17,7 @@
package org.keycloak.authentication.authenticators.broker; package org.keycloak.authentication.authenticators.broker;
import org.jboss.logging.Logger;
import org.keycloak.authentication.AuthenticationFlowContext; import org.keycloak.authentication.AuthenticationFlowContext;
import org.keycloak.authentication.AuthenticationFlowError; import org.keycloak.authentication.AuthenticationFlowError;
import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext; import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
@ -48,7 +49,7 @@ import java.util.concurrent.TimeUnit;
*/ */
public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator { public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static Logger logger = Logger.getLogger(IdpEmailVerificationAuthenticator.class);
@Override @Override
protected void authenticateImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext serializedCtx, BrokeredIdentityContext brokerContext) { protected void authenticateImpl(AuthenticationFlowContext context, SerializedBrokeredIdentityContext serializedCtx, BrokeredIdentityContext brokerContext) {
@ -57,7 +58,7 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator
ClientSessionModel clientSession = context.getClientSession(); ClientSessionModel clientSession = context.getClientSession();
if (realm.getSmtpConfig().size() == 0) { if (realm.getSmtpConfig().size() == 0) {
logger.smtpNotConfigured(); ServicesLogger.LOGGER.smtpNotConfigured();
context.attempted(); context.attempted();
return; return;
} }
@ -94,7 +95,7 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator
} catch (EmailException e) { } catch (EmailException e) {
event.error(Errors.EMAIL_SEND_FAILED); event.error(Errors.EMAIL_SEND_FAILED);
logger.confirmBrokerEmailFailed(e); ServicesLogger.LOGGER.confirmBrokerEmailFailed(e);
Response challenge = context.form() Response challenge = context.form()
.setError(Messages.EMAIL_SENT_ERROR) .setError(Messages.EMAIL_SENT_ERROR)
.createErrorPage(); .createErrorPage();
@ -137,7 +138,7 @@ public class IdpEmailVerificationAuthenticator extends AbstractIdpAuthenticator
context.setUser(existingUser); context.setUser(existingUser);
context.success(); context.success();
} else { } else {
logger.keyParamDoesNotMatch(); ServicesLogger.LOGGER.keyParamDoesNotMatch();
Response challengeResponse = context.form() Response challengeResponse = context.form()
.setError(Messages.INVALID_ACCESS_CODE) .setError(Messages.INVALID_ACCESS_CODE)
.createErrorPage(); .createErrorPage();

View file

@ -17,6 +17,7 @@
package org.keycloak.authentication.authenticators.broker; package org.keycloak.authentication.authenticators.broker;
import org.jboss.logging.Logger;
import org.keycloak.authentication.AuthenticationFlowContext; import org.keycloak.authentication.AuthenticationFlowContext;
import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext; import org.keycloak.authentication.authenticators.broker.util.SerializedBrokeredIdentityContext;
import org.keycloak.broker.provider.BrokeredIdentityContext; import org.keycloak.broker.provider.BrokeredIdentityContext;
@ -45,7 +46,7 @@ import java.util.List;
*/ */
public class IdpReviewProfileAuthenticator extends AbstractIdpAuthenticator { public class IdpReviewProfileAuthenticator extends AbstractIdpAuthenticator {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(IdpReviewProfileAuthenticator.class);
@Override @Override
public boolean requiresUser() { public boolean requiresUser() {

View file

@ -108,7 +108,8 @@ public class IdpReviewProfileAuthenticatorFactory implements AuthenticatorFactor
property.setLabel("{{:: 'update-profile-on-first-login' | translate}}"); property.setLabel("{{:: 'update-profile-on-first-login' | translate}}");
property.setType(ProviderConfigProperty.LIST_TYPE); property.setType(ProviderConfigProperty.LIST_TYPE);
List<String> updateProfileValues = Arrays.asList(IdentityProviderRepresentation.UPFLM_ON, IdentityProviderRepresentation.UPFLM_MISSING, IdentityProviderRepresentation.UPFLM_OFF); List<String> updateProfileValues = Arrays.asList(IdentityProviderRepresentation.UPFLM_ON, IdentityProviderRepresentation.UPFLM_MISSING, IdentityProviderRepresentation.UPFLM_OFF);
property.setDefaultValue(updateProfileValues); property.setOptions(updateProfileValues);
property.setDefaultValue(IdentityProviderRepresentation.UPFLM_MISSING);
property.setHelpText("Define conditions under which a user has to review and update his profile after first-time login. Value 'On' means that" property.setHelpText("Define conditions under which a user has to review and update his profile after first-time login. Value 'On' means that"
+ " page for reviewing profile will be displayed and user can review and update his profile. Value 'off' means that page won't be displayed." + " page for reviewing profile will be displayed and user can review and update his profile. Value 'off' means that page won't be displayed."
+ " Value 'missing' means that page is displayed just when some required attribute is missing (wasn't downloaded from identity provider). Value 'missing' is the default one." + " Value 'missing' means that page is displayed just when some required attribute is missing (wasn't downloaded from identity provider). Value 'missing' is the default one."

View file

@ -17,6 +17,7 @@
package org.keycloak.authentication.authenticators.browser; package org.keycloak.authentication.authenticators.browser;
import org.jboss.logging.Logger;
import org.keycloak.authentication.AbstractFormAuthenticator; import org.keycloak.authentication.AbstractFormAuthenticator;
import org.keycloak.authentication.AuthenticationFlowContext; import org.keycloak.authentication.AuthenticationFlowContext;
import org.keycloak.authentication.AuthenticationFlowError; import org.keycloak.authentication.AuthenticationFlowError;
@ -43,7 +44,7 @@ import java.util.List;
*/ */
public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuthenticator { public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuthenticator {
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(AbstractUsernameFormAuthenticator.class);
public static final String REGISTRATION_FORM_ACTION = "registration_form"; public static final String REGISTRATION_FORM_ACTION = "registration_form";
public static final String ATTEMPTED_USERNAME = "ATTEMPTED_USERNAME"; public static final String ATTEMPTED_USERNAME = "ATTEMPTED_USERNAME";
@ -131,7 +132,7 @@ public abstract class AbstractUsernameFormAuthenticator extends AbstractFormAuth
try { try {
user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), username); user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), username);
} catch (ModelDuplicateException mde) { } catch (ModelDuplicateException mde) {
logger.modelDuplicateException(mde); ServicesLogger.LOGGER.modelDuplicateException(mde);
// Could happen during federation import // Could happen during federation import
if (mde.getDuplicateFieldName() != null && mde.getDuplicateFieldName().equals(UserModel.EMAIL)) { if (mde.getDuplicateFieldName() != null && mde.getDuplicateFieldName().equals(UserModel.EMAIL)) {

View file

@ -156,7 +156,7 @@ public class ConditionalOtpFormAuthenticatorFactory implements AuthenticatorFact
defaultOutcome.setType(LIST_TYPE); defaultOutcome.setType(LIST_TYPE);
defaultOutcome.setName(DEFAULT_OTP_OUTCOME); defaultOutcome.setName(DEFAULT_OTP_OUTCOME);
defaultOutcome.setLabel("Fallback OTP handling"); defaultOutcome.setLabel("Fallback OTP handling");
defaultOutcome.setDefaultValue(asList(SKIP, FORCE)); defaultOutcome.setOptions(asList(SKIP, FORCE));
defaultOutcome.setHelpText("What to do in case of every check abstains. Defaults to force OTP authentication."); defaultOutcome.setHelpText("What to do in case of every check abstains. Defaults to force OTP authentication.");
return asList(forceOtpUserAttribute, skipOtpRole, forceOtpRole, skipOtpForHttpHeader, forceOtpForHttpHeader, defaultOutcome); return asList(forceOtpUserAttribute, skipOtpRole, forceOtpRole, skipOtpForHttpHeader, forceOtpForHttpHeader, defaultOutcome);

View file

@ -20,10 +20,12 @@ import org.jboss.logging.Logger;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.authentication.Authenticator; import org.keycloak.authentication.Authenticator;
import org.keycloak.authentication.AuthenticatorFactory; import org.keycloak.authentication.AuthenticatorFactory;
import org.keycloak.common.Profile;
import org.keycloak.common.util.StreamUtil; import org.keycloak.common.util.StreamUtil;
import org.keycloak.models.AuthenticationExecutionModel; import org.keycloak.models.AuthenticationExecutionModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.provider.EnvironmentDependentProviderFactory;
import org.keycloak.provider.ProviderConfigProperty; import org.keycloak.provider.ProviderConfigProperty;
import java.io.IOException; import java.io.IOException;
@ -41,7 +43,7 @@ import static org.keycloak.provider.ProviderConfigProperty.STRING_TYPE;
* *
* @author <a href="mailto:thomas.darimont@gmail.com">Thomas Darimont</a> * @author <a href="mailto:thomas.darimont@gmail.com">Thomas Darimont</a>
*/ */
public class ScriptBasedAuthenticatorFactory implements AuthenticatorFactory { public class ScriptBasedAuthenticatorFactory implements AuthenticatorFactory, EnvironmentDependentProviderFactory {
private static final Logger LOGGER = Logger.getLogger(ScriptBasedAuthenticatorFactory.class); private static final Logger LOGGER = Logger.getLogger(ScriptBasedAuthenticatorFactory.class);
@ -148,4 +150,9 @@ public class ScriptBasedAuthenticatorFactory implements AuthenticatorFactory {
return asList(name, description, script); return asList(name, description, script);
} }
@Override
public boolean isSupported() {
return Profile.isPreviewEnabled();
}
} }

View file

@ -17,6 +17,7 @@
package org.keycloak.authentication.authenticators.browser; package org.keycloak.authentication.authenticators.browser;
import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.authentication.AuthenticationFlowContext; import org.keycloak.authentication.AuthenticationFlowContext;
import org.keycloak.authentication.AuthenticationFlowError; import org.keycloak.authentication.AuthenticationFlowError;
@ -44,7 +45,7 @@ import java.util.Map;
*/ */
public class SpnegoAuthenticator extends AbstractUsernameFormAuthenticator implements Authenticator{ public class SpnegoAuthenticator extends AbstractUsernameFormAuthenticator implements Authenticator{
public static final String KERBEROS_DISABLED = "kerberos_disabled"; public static final String KERBEROS_DISABLED = "kerberos_disabled";
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(SpnegoAuthenticator.class);
@Override @Override
public boolean requiresUser() { public boolean requiresUser() {

View file

@ -37,7 +37,7 @@ import javax.ws.rs.core.Response;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class UsernamePasswordForm extends AbstractUsernameFormAuthenticator implements Authenticator { public class UsernamePasswordForm extends AbstractUsernameFormAuthenticator implements Authenticator {
protected static ServicesLogger log = ServicesLogger.ROOT_LOGGER; protected static ServicesLogger log = ServicesLogger.LOGGER;
@Override @Override
public void action(AuthenticationFlowContext context) { public void action(AuthenticationFlowContext context) {

View file

@ -25,7 +25,6 @@ import org.keycloak.models.ClientModel;
import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.provider.ProviderConfigProperty; import org.keycloak.provider.ProviderConfigProperty;
import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.services.ServicesLogger;
import org.keycloak.util.BasicAuthHelper; import org.keycloak.util.BasicAuthHelper;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
@ -49,8 +48,6 @@ import java.util.Set;
*/ */
public class ClientIdAndSecretAuthenticator extends AbstractClientAuthenticator { public class ClientIdAndSecretAuthenticator extends AbstractClientAuthenticator {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
public static final String PROVIDER_ID = "client-secret"; public static final String PROVIDER_ID = "client-secret";
public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = { public static final AuthenticationExecutionModel.Requirement[] REQUIREMENT_CHOICES = {

View file

@ -59,8 +59,6 @@ import org.keycloak.services.Urls;
*/ */
public class JWTClientAuthenticator extends AbstractClientAuthenticator { public class JWTClientAuthenticator extends AbstractClientAuthenticator {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
public static final String PROVIDER_ID = "client-jwt"; public static final String PROVIDER_ID = "client-jwt";
public static final String ATTR_PREFIX = "jwt.credential"; public static final String ATTR_PREFIX = "jwt.credential";
public static final String CERTIFICATE_ATTR = "jwt.credential.certificate"; public static final String CERTIFICATE_ATTR = "jwt.credential.certificate";
@ -156,7 +154,7 @@ public class JWTClientAuthenticator extends AbstractClientAuthenticator {
context.success(); context.success();
} catch (Exception e) { } catch (Exception e) {
logger.errorValidatingAssertion(e); ServicesLogger.LOGGER.errorValidatingAssertion(e);
Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Client authentication with signed JWT failed: " + e.getMessage()); Response challengeResponse = ClientAuthUtil.errorResponse(Response.Status.BAD_REQUEST.getStatusCode(), "unauthorized_client", "Client authentication with signed JWT failed: " + e.getMessage());
context.failure(AuthenticationFlowError.INVALID_CLIENT_CREDENTIALS, challengeResponse); context.failure(AuthenticationFlowError.INVALID_CLIENT_CREDENTIALS, challengeResponse);
} }

View file

@ -43,7 +43,6 @@ import java.util.List;
*/ */
public class ValidateUsername extends AbstractDirectGrantAuthenticator { public class ValidateUsername extends AbstractDirectGrantAuthenticator {
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
public static final String PROVIDER_ID = "direct-grant-validate-username"; public static final String PROVIDER_ID = "direct-grant-validate-username";
@Override @Override
@ -63,7 +62,7 @@ public class ValidateUsername extends AbstractDirectGrantAuthenticator {
try { try {
user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), username); user = KeycloakModelUtils.findUserByNameOrEmail(context.getSession(), context.getRealm(), username);
} catch (ModelDuplicateException mde) { } catch (ModelDuplicateException mde) {
logger.modelDuplicateException(mde); ServicesLogger.LOGGER.modelDuplicateException(mde);
Response challengeResponse = errorResponse(Response.Status.UNAUTHORIZED.getStatusCode(), "invalid_request", "Invalid user credentials"); Response challengeResponse = errorResponse(Response.Status.UNAUTHORIZED.getStatusCode(), "invalid_request", "Invalid user credentials");
context.failure(AuthenticationFlowError.INVALID_USER, challengeResponse); context.failure(AuthenticationFlowError.INVALID_USER, challengeResponse);
return; return;

View file

@ -17,6 +17,7 @@
package org.keycloak.authentication.authenticators.resetcred; package org.keycloak.authentication.authenticators.resetcred;
import org.jboss.logging.Logger;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.authentication.AuthenticationFlowContext; import org.keycloak.authentication.AuthenticationFlowContext;
import org.keycloak.authentication.AuthenticationFlowError; import org.keycloak.authentication.AuthenticationFlowError;
@ -46,7 +47,7 @@ import java.util.List;
*/ */
public class ResetCredentialChooseUser implements Authenticator, AuthenticatorFactory { public class ResetCredentialChooseUser implements Authenticator, AuthenticatorFactory {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(ResetCredentialChooseUser.class);
public static final String PROVIDER_ID = "reset-credentials-choose-user"; public static final String PROVIDER_ID = "reset-credentials-choose-user";

View file

@ -17,6 +17,7 @@
package org.keycloak.authentication.authenticators.resetcred; package org.keycloak.authentication.authenticators.resetcred;
import org.jboss.logging.Logger;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.authentication.AuthenticationFlowContext; import org.keycloak.authentication.AuthenticationFlowContext;
import org.keycloak.authentication.AuthenticationFlowError; import org.keycloak.authentication.AuthenticationFlowError;
@ -53,7 +54,7 @@ import java.util.concurrent.TimeUnit;
public class ResetCredentialEmail implements Authenticator, AuthenticatorFactory { public class ResetCredentialEmail implements Authenticator, AuthenticatorFactory {
public static final String RESET_CREDENTIAL_SECRET = "RESET_CREDENTIAL_SECRET"; public static final String RESET_CREDENTIAL_SECRET = "RESET_CREDENTIAL_SECRET";
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(ResetCredentialEmail.class);
public static final String PROVIDER_ID = "reset-credential-email"; public static final String PROVIDER_ID = "reset-credential-email";
@ -100,7 +101,7 @@ public class ResetCredentialEmail implements Authenticator, AuthenticatorFactory
.detail(Details.USERNAME, username) .detail(Details.USERNAME, username)
.user(user) .user(user)
.error(Errors.EMAIL_SEND_FAILED); .error(Errors.EMAIL_SEND_FAILED);
logger.failedToSendPwdResetEmail(e); ServicesLogger.LOGGER.failedToSendPwdResetEmail(e);
Response challenge = context.form() Response challenge = context.form()
.setError(Messages.EMAIL_SENT_ERROR) .setError(Messages.EMAIL_SENT_ERROR)
.createErrorPage(); .createErrorPage();

View file

@ -23,6 +23,7 @@ import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair; import org.apache.http.message.BasicNameValuePair;
import org.jboss.logging.Logger;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.authentication.FormAction; import org.keycloak.authentication.FormAction;
import org.keycloak.authentication.FormActionFactory; import org.keycloak.authentication.FormActionFactory;
@ -62,7 +63,7 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory, Con
public static final String RECAPTCHA_REFERENCE_CATEGORY = "recaptcha"; public static final String RECAPTCHA_REFERENCE_CATEGORY = "recaptcha";
public static final String SITE_KEY = "site.key"; public static final String SITE_KEY = "site.key";
public static final String SITE_SECRET = "secret"; public static final String SITE_SECRET = "secret";
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(RegistrationRecaptcha.class);
public static final String PROVIDER_ID = "registration-recaptcha-action"; public static final String PROVIDER_ID = "registration-recaptcha-action";
@ -152,7 +153,7 @@ public class RegistrationRecaptcha implements FormAction, FormActionFactory, Con
content.close(); content.close();
} }
} catch (Exception e) { } catch (Exception e) {
logger.recaptchaFailed(e); ServicesLogger.LOGGER.recaptchaFailed(e);
} }
return success; return success;
} }

View file

@ -17,6 +17,7 @@
package org.keycloak.authentication.requiredactions; package org.keycloak.authentication.requiredactions;
import org.jboss.logging.Logger;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.authentication.RequiredActionContext; import org.keycloak.authentication.RequiredActionContext;
import org.keycloak.authentication.RequiredActionFactory; import org.keycloak.authentication.RequiredActionFactory;
@ -35,7 +36,6 @@ import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.ModelException; import org.keycloak.models.ModelException;
import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.messages.Messages; import org.keycloak.services.messages.Messages;
import org.keycloak.services.validation.Validation; import org.keycloak.services.validation.Validation;
@ -48,7 +48,7 @@ import java.util.concurrent.TimeUnit;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class UpdatePassword implements RequiredActionProvider, RequiredActionFactory { public class UpdatePassword implements RequiredActionProvider, RequiredActionFactory {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(UpdatePassword.class);
@Override @Override
public void evaluateTriggers(RequiredActionContext context) { public void evaluateTriggers(RequiredActionContext context) {
int daysToExpirePassword = context.getRealm().getPasswordPolicy().getDaysToExpirePassword(); int daysToExpirePassword = context.getRealm().getPasswordPolicy().getDaysToExpirePassword();

View file

@ -29,7 +29,6 @@ import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.models.utils.FormMessage; import org.keycloak.models.utils.FormMessage;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.messages.Messages; import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.AttributeFormDataProcessor; import org.keycloak.services.resources.AttributeFormDataProcessor;
import org.keycloak.services.validation.Validation; import org.keycloak.services.validation.Validation;
@ -43,7 +42,6 @@ import java.util.List;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class UpdateProfile implements RequiredActionProvider, RequiredActionFactory { public class UpdateProfile implements RequiredActionProvider, RequiredActionFactory {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
@Override @Override
public void evaluateTriggers(RequiredActionContext context) { public void evaluateTriggers(RequiredActionContext context) {
} }

View file

@ -28,7 +28,6 @@ import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.UserCredentialModel; import org.keycloak.models.UserCredentialModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
import org.keycloak.models.utils.CredentialValidation; import org.keycloak.models.utils.CredentialValidation;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.messages.Messages; import org.keycloak.services.messages.Messages;
import org.keycloak.services.validation.Validation; import org.keycloak.services.validation.Validation;
@ -40,7 +39,6 @@ import javax.ws.rs.core.Response;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class UpdateTotp implements RequiredActionProvider, RequiredActionFactory { public class UpdateTotp implements RequiredActionProvider, RequiredActionFactory {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
@Override @Override
public void evaluateTriggers(RequiredActionContext context) { public void evaluateTriggers(RequiredActionContext context) {
} }

View file

@ -17,6 +17,7 @@
package org.keycloak.authentication.requiredactions; package org.keycloak.authentication.requiredactions;
import org.jboss.logging.Logger;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.authentication.RequiredActionContext; import org.keycloak.authentication.RequiredActionContext;
import org.keycloak.authentication.RequiredActionFactory; import org.keycloak.authentication.RequiredActionFactory;
@ -41,7 +42,7 @@ import javax.ws.rs.core.Response;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class VerifyEmail implements RequiredActionProvider, RequiredActionFactory { public class VerifyEmail implements RequiredActionProvider, RequiredActionFactory {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(VerifyEmail.class);
@Override @Override
public void evaluateTriggers(RequiredActionContext context) { public void evaluateTriggers(RequiredActionContext context) {
if (context.getRealm().isVerifyEmail() && !context.getUser().isEmailVerified()) { if (context.getRealm().isVerifyEmail() && !context.getUser().isEmailVerified()) {

View file

@ -17,21 +17,13 @@
package org.keycloak.broker.oidc; package org.keycloak.broker.oidc;
import org.keycloak.broker.provider.AbstractIdentityProviderFactory; import org.keycloak.broker.provider.AbstractIdentityProviderFactory;
import org.keycloak.jose.jwk.JSONWebKeySet;
import org.keycloak.jose.jwk.JWK;
import org.keycloak.jose.jwk.JWKParser;
import org.keycloak.models.IdentityProviderModel; import org.keycloak.models.IdentityProviderModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.utils.KeycloakModelUtils;
import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation; import org.keycloak.protocol.oidc.representations.OIDCConfigurationRepresentation;
import org.keycloak.protocol.oidc.utils.JWKSHttpUtils;
import org.keycloak.services.ServicesLogger;
import org.keycloak.util.JWKSUtils;
import org.keycloak.util.JsonSerialization; import org.keycloak.util.JsonSerialization;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.PublicKey;
import java.util.Map; import java.util.Map;
/** /**
@ -39,8 +31,6 @@ import java.util.Map;
*/ */
public class OIDCIdentityProviderFactory extends AbstractIdentityProviderFactory<OIDCIdentityProvider> { public class OIDCIdentityProviderFactory extends AbstractIdentityProviderFactory<OIDCIdentityProvider> {
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
public static final String PROVIDER_ID = "oidc"; public static final String PROVIDER_ID = "oidc";
@Override @Override

View file

@ -17,6 +17,7 @@
package org.keycloak.email; package org.keycloak.email;
import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.models.UserModel; import org.keycloak.models.UserModel;
@ -44,7 +45,7 @@ import java.util.Properties;
*/ */
public class DefaultEmailSenderProvider implements EmailSenderProvider { public class DefaultEmailSenderProvider implements EmailSenderProvider {
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(DefaultEmailSenderProvider.class);
private final KeycloakSession session; private final KeycloakSession session;
@ -123,7 +124,7 @@ public class DefaultEmailSenderProvider implements EmailSenderProvider {
} }
transport.sendMessage(msg, new InternetAddress[]{new InternetAddress(address)}); transport.sendMessage(msg, new InternetAddress[]{new InternetAddress(address)});
} catch (Exception e) { } catch (Exception e) {
logger.failedToSendEmail(e); ServicesLogger.LOGGER.failedToSendEmail(e);
throw new EmailException(e); throw new EmailException(e);
} finally { } finally {
if (transport != null) { if (transport != null) {

View file

@ -18,6 +18,7 @@
package org.keycloak.exportimport; package org.keycloak.exportimport;
import org.jboss.logging.Logger;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.services.ServicesLogger; import org.keycloak.services.ServicesLogger;
@ -29,7 +30,7 @@ import java.io.IOException;
*/ */
public class ExportImportManager { public class ExportImportManager {
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(ExportImportManager.class);
private KeycloakSessionFactory sessionFactory; private KeycloakSessionFactory sessionFactory;
@ -82,13 +83,13 @@ public class ExportImportManager {
try { try {
Strategy strategy = ExportImportConfig.getStrategy(); Strategy strategy = ExportImportConfig.getStrategy();
if (realmName == null) { if (realmName == null) {
logger.fullModelImport(strategy.toString()); ServicesLogger.LOGGER.fullModelImport(strategy.toString());
importProvider.importModel(sessionFactory, strategy); importProvider.importModel(sessionFactory, strategy);
} else { } else {
logger.realmImportRequested(realmName, strategy.toString()); ServicesLogger.LOGGER.realmImportRequested(realmName, strategy.toString());
importProvider.importRealm(sessionFactory, realmName, strategy); importProvider.importRealm(sessionFactory, realmName, strategy);
} }
logger.importSuccess(); ServicesLogger.LOGGER.importSuccess();
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("Failed to run import", e); throw new RuntimeException("Failed to run import", e);
} }
@ -97,13 +98,13 @@ public class ExportImportManager {
public void runExport() { public void runExport() {
try { try {
if (realmName == null) { if (realmName == null) {
logger.fullModelExportRequested(); ServicesLogger.LOGGER.fullModelExportRequested();
exportProvider.exportModel(sessionFactory); exportProvider.exportModel(sessionFactory);
} else { } else {
logger.realmExportRequested(realmName); ServicesLogger.LOGGER.realmExportRequested(realmName);
exportProvider.exportRealm(sessionFactory, realmName); exportProvider.exportRealm(sessionFactory, realmName);
} }
logger.exportSuccess(); ServicesLogger.LOGGER.exportSuccess();
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("Failed to run export"); throw new RuntimeException("Failed to run export");
} }

View file

@ -43,10 +43,10 @@ public class JavaKeystoreKeyProviderFactory extends AbstractRsaKeyProviderFactor
public static ProviderConfigProperty KEYSTORE_PASSWORD_PROPERTY = new ProviderConfigProperty(KEYSTORE_PASSWORD_KEY, "Keystore Password", "Password for the keys", STRING_TYPE, null, true); public static ProviderConfigProperty KEYSTORE_PASSWORD_PROPERTY = new ProviderConfigProperty(KEYSTORE_PASSWORD_KEY, "Keystore Password", "Password for the keys", STRING_TYPE, null, true);
public static String KEY_ALIAS_KEY = "keyAlias"; public static String KEY_ALIAS_KEY = "keyAlias";
public static ProviderConfigProperty KEY_ALIAS_PROPERTY = new ProviderConfigProperty(KEY_ALIAS_KEY, "Private Key Alias", "Alias for the private key", STRING_TYPE, null); public static ProviderConfigProperty KEY_ALIAS_PROPERTY = new ProviderConfigProperty(KEY_ALIAS_KEY, "Key Alias", "Alias for the private key", STRING_TYPE, null);
public static String KEY_PASSWORD_KEY = "keyPassword"; public static String KEY_PASSWORD_KEY = "keyPassword";
public static ProviderConfigProperty KEY_PASSWORD_PROPERTY = new ProviderConfigProperty(KEY_PASSWORD_KEY, "Private Key password", "Password for the private key", STRING_TYPE, null, true); public static ProviderConfigProperty KEY_PASSWORD_PROPERTY = new ProviderConfigProperty(KEY_PASSWORD_KEY, "Key Password", "Password for the private key", STRING_TYPE, null, true);
private static final String HELP_TEXT = "Loads keys from a Java keys file"; private static final String HELP_TEXT = "Loads keys from a Java keys file";

View file

@ -22,6 +22,7 @@ import java.security.cert.X509Certificate;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import org.jboss.logging.Logger;
import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator; import org.keycloak.authentication.authenticators.client.JWTClientAuthenticator;
import org.keycloak.common.util.KeyUtils; import org.keycloak.common.util.KeyUtils;
import org.keycloak.jose.jwk.JSONWebKeySet; import org.keycloak.jose.jwk.JSONWebKeySet;
@ -44,7 +45,7 @@ import org.keycloak.util.JWKSUtils;
*/ */
public class ClientPublicKeyLoader implements PublicKeyLoader { public class ClientPublicKeyLoader implements PublicKeyLoader {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(ClientPublicKeyLoader.class);
private final KeycloakSession session; private final KeycloakSession session;
private final ClientModel client; private final ClientModel client;

View file

@ -17,10 +17,7 @@
package org.keycloak.keys.loader; package org.keycloak.keys.loader;
import java.security.PublicKey; import org.jboss.logging.Logger;
import java.util.Collections;
import java.util.Map;
import org.keycloak.broker.oidc.OIDCIdentityProviderConfig; import org.keycloak.broker.oidc.OIDCIdentityProviderConfig;
import org.keycloak.common.util.KeyUtils; import org.keycloak.common.util.KeyUtils;
import org.keycloak.common.util.PemUtils; import org.keycloak.common.util.PemUtils;
@ -29,15 +26,18 @@ import org.keycloak.jose.jwk.JWK;
import org.keycloak.keys.PublicKeyLoader; import org.keycloak.keys.PublicKeyLoader;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.protocol.oidc.utils.JWKSHttpUtils; import org.keycloak.protocol.oidc.utils.JWKSHttpUtils;
import org.keycloak.services.ServicesLogger;
import org.keycloak.util.JWKSUtils; import org.keycloak.util.JWKSUtils;
import java.security.PublicKey;
import java.util.Collections;
import java.util.Map;
/** /**
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a> * @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
*/ */
public class OIDCIdentityProviderPublicKeyLoader implements PublicKeyLoader { public class OIDCIdentityProviderPublicKeyLoader implements PublicKeyLoader {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(OIDCIdentityProviderPublicKeyLoader.class);
private final KeycloakSession session; private final KeycloakSession session;
private final OIDCIdentityProviderConfig config; private final OIDCIdentityProviderConfig config;

View file

@ -34,7 +34,6 @@ import java.util.Set;
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
*/ */
public abstract class AbstractPartialImport<T> implements PartialImport<T> { public abstract class AbstractPartialImport<T> implements PartialImport<T> {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
protected final Set<T> toOverwrite = new HashSet<>(); protected final Set<T> toOverwrite = new HashSet<>();
protected final Set<T> toSkip = new HashSet<>(); protected final Set<T> toSkip = new HashSet<>();
@ -100,7 +99,7 @@ public abstract class AbstractPartialImport<T> implements PartialImport<T> {
try { try {
create(realm, session, resourceRep); create(realm, session, resourceRep);
} catch (Exception e) { } catch (Exception e) {
logger.overwriteError(e, getName(resourceRep)); ServicesLogger.LOGGER.overwriteError(e, getName(resourceRep));
throw new ErrorResponseException(ErrorResponse.error(e.getMessage(), Response.Status.INTERNAL_SERVER_ERROR)); throw new ErrorResponseException(ErrorResponse.error(e.getMessage(), Response.Status.INTERNAL_SERVER_ERROR));
} }
@ -122,7 +121,7 @@ public abstract class AbstractPartialImport<T> implements PartialImport<T> {
String modelId = getModelId(realm, session, resourceRep); String modelId = getModelId(realm, session, resourceRep);
results.addResult(added(modelId, resourceRep)); results.addResult(added(modelId, resourceRep));
} catch (Exception e) { } catch (Exception e) {
logger.creationError(e, getName(resourceRep)); ServicesLogger.LOGGER.creationError(e, getName(resourceRep));
throw new ErrorResponseException(ErrorResponse.error(e.getMessage(), Response.Status.INTERNAL_SERVER_ERROR)); throw new ErrorResponseException(ErrorResponse.error(e.getMessage(), Response.Status.INTERNAL_SERVER_ERROR));
} }
} }

View file

@ -45,7 +45,6 @@ import java.util.Set;
* @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc.
*/ */
public class RolesPartialImport implements PartialImport<RolesRepresentation> { public class RolesPartialImport implements PartialImport<RolesRepresentation> {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
private Set<RoleRepresentation> realmRolesToOverwrite; private Set<RoleRepresentation> realmRolesToOverwrite;
private Set<RoleRepresentation> realmRolesToSkip; private Set<RoleRepresentation> realmRolesToSkip;
@ -98,7 +97,7 @@ public class RolesPartialImport implements PartialImport<RolesRepresentation> {
try { try {
RepresentationToModel.importRoles(rep.getRoles(), realm); RepresentationToModel.importRoles(rep.getRoles(), realm);
} catch (Exception e) { } catch (Exception e) {
logger.roleImportError(e); ServicesLogger.LOGGER.roleImportError(e);
throw new ErrorResponseException(ErrorResponse.error(e.getMessage(), Response.Status.INTERNAL_SERVER_ERROR)); throw new ErrorResponseException(ErrorResponse.error(e.getMessage(), Response.Status.INTERNAL_SERVER_ERROR));
} }

View file

@ -43,8 +43,6 @@ import javax.ws.rs.core.UriInfo;
*/ */
public abstract class AuthorizationEndpointBase { public abstract class AuthorizationEndpointBase {
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
protected RealmModel realm; protected RealmModel realm;
protected EventBuilder event; protected EventBuilder event;
protected AuthenticationManager authManager; protected AuthenticationManager authManager;

View file

@ -18,21 +18,19 @@
package org.keycloak.protocol; package org.keycloak.protocol;
import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonProperty;
import org.jboss.logging.Logger;
import org.keycloak.common.ClientConnection; import org.keycloak.common.ClientConnection;
import org.keycloak.jose.jws.JWSBuilder; import org.keycloak.jose.jws.JWSBuilder;
import org.keycloak.jose.jws.JWSInput; import org.keycloak.jose.jws.JWSInput;
import org.keycloak.jose.jws.crypto.HMACProvider;
import org.keycloak.jose.jws.crypto.RSAProvider; import org.keycloak.jose.jws.crypto.RSAProvider;
import org.keycloak.models.ClientModel; import org.keycloak.models.ClientModel;
import org.keycloak.models.ClientSessionModel; import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeyManager; import org.keycloak.models.KeyManager;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.util.CookieHelper; import org.keycloak.services.util.CookieHelper;
import javax.crypto.SecretKey;
import javax.ws.rs.core.Cookie; import javax.ws.rs.core.Cookie;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
import java.security.PublicKey; import java.security.PublicKey;
@ -47,7 +45,7 @@ import java.util.Map;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class RestartLoginCookie { public class RestartLoginCookie {
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(RestartLoginCookie.class);
public static final String KC_RESTART = "KC_RESTART"; public static final String KC_RESTART = "KC_RESTART";
@JsonProperty("cs") @JsonProperty("cs")
protected String clientSession; protected String clientSession;

View file

@ -16,6 +16,7 @@
*/ */
package org.keycloak.protocol.oidc; package org.keycloak.protocol.oidc;
import org.jboss.logging.Logger;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException; import org.keycloak.OAuthErrorException;
import org.keycloak.common.util.Time; import org.keycloak.common.util.Time;
@ -84,7 +85,7 @@ public class OIDCLoginProtocol implements LoginProtocol {
public static final String CLIENT_SECRET_JWT = "client_secret_jwt"; public static final String CLIENT_SECRET_JWT = "client_secret_jwt";
public static final String PRIVATE_KEY_JWT = "private_key_jwt"; public static final String PRIVATE_KEY_JWT = "private_key_jwt";
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(OIDCLoginProtocol.class);
protected KeycloakSession session; protected KeycloakSession session;
@ -233,7 +234,7 @@ public class OIDCLoginProtocol implements LoginProtocol {
case PASSIVE_LOGIN_REQUIRED: case PASSIVE_LOGIN_REQUIRED:
return OAuthErrorException.LOGIN_REQUIRED; return OAuthErrorException.LOGIN_REQUIRED;
default: default:
logger.untranslatedProtocol(error.name()); ServicesLogger.LOGGER.untranslatedProtocol(error.name());
return OAuthErrorException.SERVER_ERROR; return OAuthErrorException.SERVER_ERROR;
} }
} }

View file

@ -16,6 +16,7 @@
*/ */
package org.keycloak.protocol.oidc; package org.keycloak.protocol.oidc;
import org.jboss.logging.Logger;
import org.keycloak.common.constants.KerberosConstants; import org.keycloak.common.constants.KerberosConstants;
import org.keycloak.common.util.UriUtils; import org.keycloak.common.util.UriUtils;
import org.keycloak.events.EventBuilder; import org.keycloak.events.EventBuilder;
@ -48,7 +49,7 @@ import java.util.Set;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory { public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
private static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(OIDCLoginProtocolFactory.class);
public static final String USERNAME = "username"; public static final String USERNAME = "username";
public static final String EMAIL = "email"; public static final String EMAIL = "email";
@ -193,7 +194,7 @@ public class OIDCLoginProtocolFactory extends AbstractLoginProtocolFactory {
// Backwards compatibility only // Backwards compatibility only
if (rep.isDirectGrantsOnly() != null) { if (rep.isDirectGrantsOnly() != null) {
logger.usingDeprecatedDirectGrantsOnly(); ServicesLogger.LOGGER.usingDeprecatedDirectGrantsOnly();
newClient.setStandardFlowEnabled(!rep.isDirectGrantsOnly()); newClient.setStandardFlowEnabled(!rep.isDirectGrantsOnly());
newClient.setDirectAccessGrantsEnabled(rep.isDirectGrantsOnly()); newClient.setDirectAccessGrantsEnabled(rep.isDirectGrantsOnly());
} else { } else {

View file

@ -20,9 +20,10 @@ package org.keycloak.protocol.oidc;
import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.events.EventBuilder; import org.keycloak.events.EventBuilder;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.jose.jwk.JSONWebKeySet;
import org.keycloak.jose.jwk.JWK; import org.keycloak.jose.jwk.JWK;
import org.keycloak.jose.jwk.JWKBuilder; import org.keycloak.jose.jwk.JWKBuilder;
import org.keycloak.forms.login.LoginFormsProvider;
import org.keycloak.keys.KeyMetadata; import org.keycloak.keys.KeyMetadata;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.RealmModel; import org.keycloak.models.RealmModel;
@ -31,8 +32,6 @@ import org.keycloak.protocol.oidc.endpoints.LoginStatusIframeEndpoint;
import org.keycloak.protocol.oidc.endpoints.LogoutEndpoint; import org.keycloak.protocol.oidc.endpoints.LogoutEndpoint;
import org.keycloak.protocol.oidc.endpoints.TokenEndpoint; import org.keycloak.protocol.oidc.endpoints.TokenEndpoint;
import org.keycloak.protocol.oidc.endpoints.UserInfoEndpoint; import org.keycloak.protocol.oidc.endpoints.UserInfoEndpoint;
import org.keycloak.jose.jwk.JSONWebKeySet;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.resources.RealmsResource; import org.keycloak.services.resources.RealmsResource;
import javax.ws.rs.GET; import javax.ws.rs.GET;
@ -55,8 +54,6 @@ import java.util.List;
*/ */
public class OIDCLoginProtocolService { public class OIDCLoginProtocolService {
protected static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
private RealmModel realm; private RealmModel realm;
private TokenManager tokenManager; private TokenManager tokenManager;
private EventBuilder event; private EventBuilder event;

View file

@ -506,10 +506,11 @@ public class TokenManager {
for (ProtocolMapperModel mapping : mappings) { for (ProtocolMapperModel mapping : mappings) {
ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper()); ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
if (mapper == null || !(mapper instanceof OIDCAccessTokenMapper)) continue; if (mapper instanceof OIDCAccessTokenMapper) {
token = ((OIDCAccessTokenMapper) mapper).transformAccessToken(token, mapping, session, userSession, clientSession); token = ((OIDCAccessTokenMapper) mapper).transformAccessToken(token, mapping, session, userSession, clientSession);
} }
}
return token; return token;
} }
@ -520,16 +521,11 @@ public class TokenManager {
for (ProtocolMapperModel mapping : mappings) { for (ProtocolMapperModel mapping : mappings) {
ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper()); ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
if (mapper == null || !(mapper instanceof OIDCAccessTokenMapper)) continue;
if (mapper instanceof UserInfoTokenMapper) { if (mapper instanceof UserInfoTokenMapper) {
token = ((UserInfoTokenMapper) mapper).transformUserInfoToken(token, mapping, session, userSession, clientSession); token = ((UserInfoTokenMapper) mapper).transformUserInfoToken(token, mapping, session, userSession, clientSession);
continue; }
} }
token = ((OIDCAccessTokenMapper)mapper).transformAccessToken(token, mapping, session, userSession, clientSession);
}
return token; return token;
} }
@ -540,12 +536,11 @@ public class TokenManager {
for (ProtocolMapperModel mapping : mappings) { for (ProtocolMapperModel mapping : mappings) {
ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper()); ProtocolMapper mapper = (ProtocolMapper)sessionFactory.getProviderFactory(ProtocolMapper.class, mapping.getProtocolMapper());
if (mapper == null || !(mapper instanceof OIDCIDTokenMapper)) continue; if (mapper instanceof OIDCIDTokenMapper) {
token = ((OIDCIDTokenMapper) mapper).transformIDToken(token, mapping, session, userSession, clientSession); token = ((OIDCIDTokenMapper) mapper).transformIDToken(token, mapping, session, userSession, clientSession);
} }
} }
}
protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession, UriInfo uriInfo) { protected AccessToken initToken(RealmModel realm, ClientModel client, UserModel user, UserSessionModel session, ClientSessionModel clientSession, UriInfo uriInfo) {
AccessToken token = new AccessToken(); AccessToken token = new AccessToken();

View file

@ -17,6 +17,7 @@
package org.keycloak.protocol.oidc.endpoints; package org.keycloak.protocol.oidc.endpoints;
import org.jboss.logging.Logger;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
import org.keycloak.OAuthErrorException; import org.keycloak.OAuthErrorException;
import org.keycloak.authentication.AuthenticationProcessor; import org.keycloak.authentication.AuthenticationProcessor;
@ -54,7 +55,7 @@ import javax.ws.rs.core.Response;
*/ */
public class AuthorizationEndpoint extends AuthorizationEndpointBase { public class AuthorizationEndpoint extends AuthorizationEndpointBase {
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(AuthorizationEndpoint.class);
public static final String CODE_AUTH_TYPE = "code"; public static final String CODE_AUTH_TYPE = "code";
@ -104,7 +105,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
} }
if (!TokenUtil.isOIDCRequest(request.getScope())) { if (!TokenUtil.isOIDCRequest(request.getScope())) {
logger.oidcScopeMissing(); ServicesLogger.LOGGER.oidcScopeMissing();
} }
errorResponse = checkOIDCParams(); errorResponse = checkOIDCParams();
@ -194,7 +195,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
String responseType = request.getResponseType(); String responseType = request.getResponseType();
if (responseType == null) { if (responseType == null) {
logger.missingParameter(OAuth2Constants.RESPONSE_TYPE); ServicesLogger.LOGGER.missingParameter(OAuth2Constants.RESPONSE_TYPE);
event.error(Errors.INVALID_REQUEST); event.error(Errors.INVALID_REQUEST);
return redirectErrorToClient(OIDCResponseMode.QUERY, OAuthErrorException.INVALID_REQUEST, "Missing parameter: response_type"); return redirectErrorToClient(OIDCResponseMode.QUERY, OAuthErrorException.INVALID_REQUEST, "Missing parameter: response_type");
} }
@ -216,7 +217,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
try { try {
parsedResponseMode = OIDCResponseMode.parse(request.getResponseMode(), parsedResponseType); parsedResponseMode = OIDCResponseMode.parse(request.getResponseMode(), parsedResponseType);
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
logger.invalidParameter(OIDCLoginProtocol.RESPONSE_MODE_PARAM); ServicesLogger.LOGGER.invalidParameter(OIDCLoginProtocol.RESPONSE_MODE_PARAM);
event.error(Errors.INVALID_REQUEST); event.error(Errors.INVALID_REQUEST);
return redirectErrorToClient(OIDCResponseMode.QUERY, OAuthErrorException.INVALID_REQUEST, "Invalid parameter: response_mode"); return redirectErrorToClient(OIDCResponseMode.QUERY, OAuthErrorException.INVALID_REQUEST, "Invalid parameter: response_mode");
} }
@ -225,19 +226,19 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
// Disallowed by OIDC specs // Disallowed by OIDC specs
if (parsedResponseType.isImplicitOrHybridFlow() && parsedResponseMode == OIDCResponseMode.QUERY) { if (parsedResponseType.isImplicitOrHybridFlow() && parsedResponseMode == OIDCResponseMode.QUERY) {
logger.responseModeQueryNotAllowed(); ServicesLogger.LOGGER.responseModeQueryNotAllowed();
event.error(Errors.INVALID_REQUEST); event.error(Errors.INVALID_REQUEST);
return redirectErrorToClient(OIDCResponseMode.QUERY, OAuthErrorException.INVALID_REQUEST, "Response_mode 'query' not allowed for implicit or hybrid flow"); return redirectErrorToClient(OIDCResponseMode.QUERY, OAuthErrorException.INVALID_REQUEST, "Response_mode 'query' not allowed for implicit or hybrid flow");
} }
if ((parsedResponseType.hasResponseType(OIDCResponseType.CODE) || parsedResponseType.hasResponseType(OIDCResponseType.NONE)) && !client.isStandardFlowEnabled()) { if ((parsedResponseType.hasResponseType(OIDCResponseType.CODE) || parsedResponseType.hasResponseType(OIDCResponseType.NONE)) && !client.isStandardFlowEnabled()) {
logger.flowNotAllowed("Standard"); ServicesLogger.LOGGER.flowNotAllowed("Standard");
event.error(Errors.NOT_ALLOWED); event.error(Errors.NOT_ALLOWED);
return redirectErrorToClient(parsedResponseMode, OAuthErrorException.UNSUPPORTED_RESPONSE_TYPE, "Client is not allowed to initiate browser login with given response_type. Standard flow is disabled for the client."); return redirectErrorToClient(parsedResponseMode, OAuthErrorException.UNSUPPORTED_RESPONSE_TYPE, "Client is not allowed to initiate browser login with given response_type. Standard flow is disabled for the client.");
} }
if (parsedResponseType.isImplicitOrHybridFlow() && !client.isImplicitFlowEnabled()) { if (parsedResponseType.isImplicitOrHybridFlow() && !client.isImplicitFlowEnabled()) {
logger.flowNotAllowed("Implicit"); ServicesLogger.LOGGER.flowNotAllowed("Implicit");
event.error(Errors.NOT_ALLOWED); event.error(Errors.NOT_ALLOWED);
return redirectErrorToClient(parsedResponseMode, OAuthErrorException.UNSUPPORTED_RESPONSE_TYPE, "Client is not allowed to initiate browser login with given response_type. Implicit flow is disabled for the client."); return redirectErrorToClient(parsedResponseMode, OAuthErrorException.UNSUPPORTED_RESPONSE_TYPE, "Client is not allowed to initiate browser login with given response_type. Implicit flow is disabled for the client.");
} }
@ -249,7 +250,7 @@ public class AuthorizationEndpoint extends AuthorizationEndpointBase {
private Response checkOIDCParams() { private Response checkOIDCParams() {
if (parsedResponseType.isImplicitOrHybridFlow() && request.getNonce() == null) { if (parsedResponseType.isImplicitOrHybridFlow() && request.getNonce() == null) {
logger.missingParameter(OIDCLoginProtocol.NONCE_PARAM); ServicesLogger.LOGGER.missingParameter(OIDCLoginProtocol.NONCE_PARAM);
event.error(Errors.INVALID_REQUEST); event.error(Errors.INVALID_REQUEST);
return redirectErrorToClient(parsedResponseMode, OAuthErrorException.INVALID_REQUEST, "Missing parameter: nonce"); return redirectErrorToClient(parsedResponseMode, OAuthErrorException.INVALID_REQUEST, "Missing parameter: nonce");
} }

View file

@ -17,6 +17,7 @@
package org.keycloak.protocol.oidc.endpoints; package org.keycloak.protocol.oidc.endpoints;
import org.jboss.logging.Logger;
import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.annotations.cache.NoCache;
import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.HttpRequest;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
@ -38,7 +39,6 @@ import org.keycloak.representations.IDToken;
import org.keycloak.representations.RefreshToken; import org.keycloak.representations.RefreshToken;
import org.keycloak.services.ErrorPage; import org.keycloak.services.ErrorPage;
import org.keycloak.services.ErrorResponseException; import org.keycloak.services.ErrorResponseException;
import org.keycloak.services.ServicesLogger;
import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.messages.Messages; import org.keycloak.services.messages.Messages;
import org.keycloak.services.resources.Cors; import org.keycloak.services.resources.Cors;
@ -60,7 +60,7 @@ import javax.ws.rs.core.UriInfo;
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a> * @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
*/ */
public class LogoutEndpoint { public class LogoutEndpoint {
protected static ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(LogoutEndpoint.class);
@Context @Context
private KeycloakSession session; private KeycloakSession session;

View file

@ -17,6 +17,7 @@
package org.keycloak.protocol.oidc.endpoints; package org.keycloak.protocol.oidc.endpoints;
import org.jboss.logging.Logger;
import org.jboss.resteasy.spi.HttpRequest; import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.OAuth2Constants; import org.keycloak.OAuth2Constants;
@ -68,7 +69,7 @@ import java.util.Map;
*/ */
public class TokenEndpoint { public class TokenEndpoint {
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(TokenEndpoint.class);
private MultivaluedMap<String, String> formParams; private MultivaluedMap<String, String> formParams;
private ClientModel client; private ClientModel client;
private Map<String, String> clientAuthAttributes; private Map<String, String> clientAuthAttributes;
@ -309,7 +310,7 @@ public class TokenEndpoint {
private void updateClientSession(ClientSessionModel clientSession) { private void updateClientSession(ClientSessionModel clientSession) {
if(clientSession == null) { if(clientSession == null) {
logger.clientSessionNull(); ServicesLogger.LOGGER.clientSessionNull();
return; return;
} }
@ -327,16 +328,16 @@ public class TokenEndpoint {
private void updateClientSessions(List<ClientSessionModel> clientSessions) { private void updateClientSessions(List<ClientSessionModel> clientSessions) {
if(clientSessions == null) { if(clientSessions == null) {
logger.clientSessionNull(); ServicesLogger.LOGGER.clientSessionNull();
return; return;
} }
for (ClientSessionModel clientSession : clientSessions) { for (ClientSessionModel clientSession : clientSessions) {
if(clientSession == null) { if(clientSession == null) {
logger.clientSessionNull(); ServicesLogger.LOGGER.clientSessionNull();
continue; continue;
} }
if(clientSession.getClient() == null) { if(clientSession.getClient() == null) {
logger.clientModelNull(); ServicesLogger.LOGGER.clientModelNull();
continue; continue;
} }
if(client.getId().equals(clientSession.getClient().getId())) { if(client.getId().equals(clientSession.getClient().getId())) {

View file

@ -36,8 +36,6 @@ import java.io.InputStream;
*/ */
public class AuthorizationEndpointRequestParserProcessor { public class AuthorizationEndpointRequestParserProcessor {
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
public static AuthorizationEndpointRequest parseRequest(EventBuilder event, KeycloakSession session, ClientModel client, MultivaluedMap<String, String> requestParams) { public static AuthorizationEndpointRequest parseRequest(EventBuilder event, KeycloakSession session, ClientModel client, MultivaluedMap<String, String> requestParams) {
try { try {
AuthorizationEndpointRequest request = new AuthorizationEndpointRequest(); AuthorizationEndpointRequest request = new AuthorizationEndpointRequest();
@ -63,7 +61,7 @@ public class AuthorizationEndpointRequestParserProcessor {
return request; return request;
} catch (Exception e) { } catch (Exception e) {
logger.invalidRequest(e); ServicesLogger.LOGGER.invalidRequest(e);
event.error(Errors.INVALID_REQUEST); event.error(Errors.INVALID_REQUEST);
throw new ErrorPageException(session, Messages.INVALID_REQUEST); throw new ErrorPageException(session, Messages.INVALID_REQUEST);
} }

View file

@ -17,9 +17,9 @@
package org.keycloak.protocol.oidc.endpoints.request; package org.keycloak.protocol.oidc.endpoints.request;
import org.jboss.logging.Logger;
import org.keycloak.constants.AdapterConstants; import org.keycloak.constants.AdapterConstants;
import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.services.ServicesLogger;
import java.util.HashSet; import java.util.HashSet;
import java.util.Map; import java.util.Map;
@ -30,7 +30,7 @@ import java.util.Set;
*/ */
abstract class AuthzEndpointRequestParser { abstract class AuthzEndpointRequestParser {
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER; private static final Logger logger = Logger.getLogger(AuthzEndpointRequestParser.class);
/** /**
* Max number of additional req params copied into client session note to prevent DoS attacks * Max number of additional req params copied into client session note to prevent DoS attacks

View file

@ -18,10 +18,15 @@
package org.keycloak.protocol.oidc.mappers; package org.keycloak.protocol.oidc.mappers;
import org.keycloak.Config; import org.keycloak.Config;
import org.keycloak.models.ClientSessionModel;
import org.keycloak.models.KeycloakSession; import org.keycloak.models.KeycloakSession;
import org.keycloak.models.KeycloakSessionFactory; import org.keycloak.models.KeycloakSessionFactory;
import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.models.UserSessionModel;
import org.keycloak.protocol.ProtocolMapper; import org.keycloak.protocol.ProtocolMapper;
import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.representations.AccessToken;
import org.keycloak.representations.IDToken;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -54,4 +59,46 @@ public abstract class AbstractOIDCProtocolMapper implements ProtocolMapper {
public void postInit(KeycloakSessionFactory factory) { public void postInit(KeycloakSessionFactory factory) {
} }
public AccessToken transformUserInfoToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
UserSessionModel userSession, ClientSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInUserInfo(mappingModel)) {
return token;
}
setClaim(token, mappingModel, userSession);
return token;
}
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
UserSessionModel userSession, ClientSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)){
return token;
}
setClaim(token, mappingModel, userSession);
return token;
}
public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
UserSessionModel userSession, ClientSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)){
return token;
}
setClaim(token, mappingModel, userSession);
return token;
}
/**
* Intended to be overridden in {@link ProtocolMapper} implementations to add claims to an token.
* @param token
* @param mappingModel
* @param userSession
*/
protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
}
} }

View file

@ -35,33 +35,7 @@ import java.util.Set;
* *
* @author <a href="mailto:thomas.darimont@gmail.com">Thomas Darimont</a> * @author <a href="mailto:thomas.darimont@gmail.com">Thomas Darimont</a>
*/ */
abstract class AbstractUserRoleMappingMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper { abstract class AbstractUserRoleMappingMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
@Override
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
UserSessionModel userSession, ClientSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) {
return token;
}
setClaim(token, mappingModel, userSession);
return token;
}
@Override
public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) {
return token;
}
setClaim(token, mappingModel, userSession);
return token;
}
protected abstract void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession);
/** /**
* Returns the role names extracted from the given {@code roleModels} while recursively traversing "Composite Roles". * Returns the role names extracted from the given {@code roleModels} while recursively traversing "Composite Roles".

View file

@ -39,26 +39,12 @@ import java.util.Map;
* @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 $
*/ */
public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper { public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>(); private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static { static {
ProviderConfigProperty property; OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, AddressMapper.class);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property);
} }
public static final String PROVIDER_ID = "oidc-address-mapper"; public static final String PROVIDER_ID = "oidc-address-mapper";
@ -118,21 +104,7 @@ public class AddressMapper extends AbstractOIDCProtocolMapper implements OIDCAcc
} }
@Override @Override
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
UserSessionModel userSession, ClientSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
setClaim(token, userSession);
return token;
}
@Override
public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
setClaim(token, userSession);
return token;
}
protected void setClaim(IDToken token, UserSessionModel userSession) {
UserModel user = userSession.getUser(); UserModel user = userSession.getUser();
AddressClaimSet addressSet = new AddressClaimSet(); AddressClaimSet addressSet = new AddressClaimSet();
addressSet.setStreetAddress(user.getFirstAttribute("street")); addressSet.setStreetAddress(user.getFirstAttribute("street"));

View file

@ -38,26 +38,12 @@ import java.util.Map;
* @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 $
*/ */
public class FullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper { public class FullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>(); private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static { static {
ProviderConfigProperty property; OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, FullNameMapper.class);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property);
} }
@ -88,28 +74,13 @@ public class FullNameMapper extends AbstractOIDCProtocolMapper implements OIDCAc
return "Maps the user's first and last name to the OpenID Connect 'name' claim. Format is <first> + ' ' + <last>"; return "Maps the user's first and last name to the OpenID Connect 'name' claim. Format is <first> + ' ' + <last>";
} }
@Override protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
UserSessionModel userSession, ClientSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
setClaim(token, userSession);
return token;
}
protected void setClaim(IDToken token, UserSessionModel userSession) {
UserModel user = userSession.getUser(); UserModel user = userSession.getUser();
String first = user.getFirstName() == null ? "" : user.getFirstName() + " "; String first = user.getFirstName() == null ? "" : user.getFirstName() + " ";
String last = user.getLastName() == null ? "" : user.getLastName(); String last = user.getLastName() == null ? "" : user.getLastName();
token.getOtherClaims().put("name", first + last); token.getOtherClaims().put("name", first + last);
} }
@Override
public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
setClaim(token, userSession);
return token;
}
public static ProtocolMapperModel create(String name, public static ProtocolMapperModel create(String name,
boolean consentRequired, String consentText, boolean consentRequired, String consentText,
boolean accessToken, boolean idToken) { boolean accessToken, boolean idToken) {

View file

@ -40,21 +40,13 @@ import java.util.Map;
* @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 $
*/ */
public class GroupMembershipMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper { public class GroupMembershipMapper extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>(); private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
static { static {
ProviderConfigProperty property; OIDCAttributeMapperHelper.addTokenClaimNameConfig(configProperties);
ProviderConfigProperty property1; ProviderConfigProperty property1 = new ProviderConfigProperty();
property1 = new ProviderConfigProperty();
property1.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME);
property1.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
property1.setType(ProviderConfigProperty.STRING_TYPE);
property1.setDefaultValue("groups");
property1.setHelpText(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_TOOLTIP);
configProperties.add(property1);
property1 = new ProviderConfigProperty();
property1.setName("full.path"); property1.setName("full.path");
property1.setLabel("Full group path"); property1.setLabel("Full group path");
property1.setType(ProviderConfigProperty.BOOLEAN_TYPE); property1.setType(ProviderConfigProperty.BOOLEAN_TYPE);
@ -62,23 +54,7 @@ public class GroupMembershipMapper extends AbstractOIDCProtocolMapper implements
property1.setHelpText("Include full path to group i.e. /top/level1/level2, false will just specify the group name"); property1.setHelpText("Include full path to group i.e. /top/level1/level2, false will just specify the group name");
configProperties.add(property1); configProperties.add(property1);
property1 = new ProviderConfigProperty(); OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, GroupMembershipMapper.class);
property1.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
property1.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
property1.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property1.setDefaultValue("true");
property1.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property1);
property1 = new ProviderConfigProperty();
property1.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
property1.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
property1.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property1.setDefaultValue("true");
property1.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property1);
} }
public static final String PROVIDER_ID = "oidc-group-membership-mapper"; public static final String PROVIDER_ID = "oidc-group-membership-mapper";
@ -113,15 +89,14 @@ public class GroupMembershipMapper extends AbstractOIDCProtocolMapper implements
} }
@Override /**
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, * Adds the group membership information to the {@link IDToken#otherClaims}.
UserSessionModel userSession, ClientSessionModel clientSession) { * @param token
if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token; * @param mappingModel
buildMembership(token, mappingModel, userSession); * @param userSession
return token; */
} protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
public void buildMembership(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
List<String> membership = new LinkedList<>(); List<String> membership = new LinkedList<>();
boolean fullPath = useFullPath(mappingModel); boolean fullPath = useFullPath(mappingModel);
for (GroupModel group : userSession.getUser().getGroups()) { for (GroupModel group : userSession.getUser().getGroups()) {
@ -136,13 +111,6 @@ public class GroupMembershipMapper extends AbstractOIDCProtocolMapper implements
token.getOtherClaims().put(protocolClaim, membership); token.getOtherClaims().put(protocolClaim, membership);
} }
@Override
public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
buildMembership(token, mappingModel, userSession);
return token;
}
public static ProtocolMapperModel create(String name, public static ProtocolMapperModel create(String name,
String tokenClaimName, String tokenClaimName,
boolean consentRequired, String consentText, boolean consentRequired, String consentText,

View file

@ -37,53 +37,24 @@ import java.util.Map;
* @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 $
*/ */
public class HardcodedClaim extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper { public class HardcodedClaim extends AbstractOIDCProtocolMapper implements OIDCAccessTokenMapper, OIDCIDTokenMapper, UserInfoTokenMapper {
private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>(); private static final List<ProviderConfigProperty> configProperties = new ArrayList<ProviderConfigProperty>();
public static final String CLAIM_VALUE = "claim.value"; public static final String CLAIM_VALUE = "claim.value";
static { static {
ProviderConfigProperty property; OIDCAttributeMapperHelper.addTokenClaimNameConfig(configProperties);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME); ProviderConfigProperty property = new ProviderConfigProperty();
property.setLabel(OIDCAttributeMapperHelper.TOKEN_CLAIM_NAME_LABEL);
property.setType(ProviderConfigProperty.STRING_TYPE);
property.setHelpText("Claim name you want to hard code into the token. This can be a fully qualified name like 'address.street'. In this case, a nested json object will be created.");
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(CLAIM_VALUE); property.setName(CLAIM_VALUE);
property.setLabel("Claim value"); property.setLabel("Claim value");
property.setType(ProviderConfigProperty.STRING_TYPE); property.setType(ProviderConfigProperty.STRING_TYPE);
property.setHelpText("Value of the claim you want to hard code. 'true' and 'false can be used for boolean values."); property.setHelpText("Value of the claim you want to hard code. 'true' and 'false can be used for boolean values.");
configProperties.add(property); configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.JSON_TYPE);
property.setLabel(OIDCAttributeMapperHelper.JSON_TYPE);
List<String> types = new ArrayList(3);
types.add("String");
types.add("long");
types.add("int");
types.add("boolean");
property.setType(ProviderConfigProperty.LIST_TYPE);
property.setDefaultValue(types);
property.setHelpText("JSON type that should be used for the value of the claim. long, int, boolean, and String are valid values.");
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property);
property = new ProviderConfigProperty();
property.setName(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN);
property.setLabel(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true");
property.setHelpText(OIDCAttributeMapperHelper.INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property);
OIDCAttributeMapperHelper.addJsonTypeConfig(configProperties);
OIDCAttributeMapperHelper.addIncludeInTokensConfig(configProperties, HardcodedClaim.class);
} }
public static final String PROVIDER_ID = "oidc-hardcoded-claim-mapper"; public static final String PROVIDER_ID = "oidc-hardcoded-claim-mapper";
@ -113,28 +84,13 @@ public class HardcodedClaim extends AbstractOIDCProtocolMapper implements OIDCAc
return "Hardcode a claim into the token."; return "Hardcode a claim into the token.";
} }
@Override
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
UserSessionModel userSession, ClientSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInAccessToken(mappingModel)) return token;
setClaim(token, mappingModel, userSession);
return token;
}
protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) { protected void setClaim(IDToken token, ProtocolMapperModel mappingModel, UserSessionModel userSession) {
String attributeValue = mappingModel.getConfig().get(CLAIM_VALUE); String attributeValue = mappingModel.getConfig().get(CLAIM_VALUE);
if (attributeValue == null) return; if (attributeValue == null) return;
OIDCAttributeMapperHelper.mapClaim(token, mappingModel, attributeValue); OIDCAttributeMapperHelper.mapClaim(token, mappingModel, attributeValue);
} }
@Override
public IDToken transformIDToken(IDToken token, ProtocolMapperModel mappingModel, KeycloakSession session, UserSessionModel userSession, ClientSessionModel clientSession) {
if (!OIDCAttributeMapperHelper.includeInIDToken(mappingModel)) return token;
setClaim(token, mappingModel, userSession);
return token;
}
public static ProtocolMapperModel create(String name, public static ProtocolMapperModel create(String name,
String hardcodedName, String hardcodedName,
String hardcodedValue, String claimType, String hardcodedValue, String claimType,

View file

@ -83,6 +83,7 @@ public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAcc
@Override @Override
public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session, public AccessToken transformAccessToken(AccessToken token, ProtocolMapperModel mappingModel, KeycloakSession session,
UserSessionModel userSession, ClientSessionModel clientSession) { UserSessionModel userSession, ClientSessionModel clientSession) {
String role = mappingModel.getConfig().get(ROLE_CONFIG); String role = mappingModel.getConfig().get(ROLE_CONFIG);
String[] scopedRole = KeycloakModelUtils.parseRole(role); String[] scopedRole = KeycloakModelUtils.parseRole(role);
String appName = scopedRole[0]; String appName = scopedRole[0];
@ -97,6 +98,7 @@ public class HardcodedRole extends AbstractOIDCProtocolMapper implements OIDCAcc
} }
access.addRole(role); access.addRole(role);
} }
return token; return token;
} }

View file

@ -18,6 +18,7 @@
package org.keycloak.protocol.oidc.mappers; package org.keycloak.protocol.oidc.mappers;
import org.keycloak.models.ProtocolMapperModel; import org.keycloak.models.ProtocolMapperModel;
import org.keycloak.protocol.ProtocolMapper;
import org.keycloak.protocol.ProtocolMapperUtils; import org.keycloak.protocol.ProtocolMapperUtils;
import org.keycloak.protocol.oidc.OIDCLoginProtocol; import org.keycloak.protocol.oidc.OIDCLoginProtocol;
import org.keycloak.provider.ProviderConfigProperty; import org.keycloak.provider.ProviderConfigProperty;
@ -34,7 +35,6 @@ import java.util.Map;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class OIDCAttributeMapperHelper { public class OIDCAttributeMapperHelper {
private static final ServicesLogger logger = ServicesLogger.ROOT_LOGGER;
public static final String TOKEN_CLAIM_NAME = "claim.name"; public static final String TOKEN_CLAIM_NAME = "claim.name";
public static final String TOKEN_CLAIM_NAME_LABEL = "tokenClaimName.label"; public static final String TOKEN_CLAIM_NAME_LABEL = "tokenClaimName.label";
@ -67,7 +67,7 @@ public class OIDCAttributeMapperHelper {
return result; return result;
} else { } else {
if (valueAsList.size() > 1) { if (valueAsList.size() > 1) {
logger.multipleValuesForMapper(attributeValue.toString(), mappingModel.getName()); ServicesLogger.LOGGER.multipleValuesForMapper(attributeValue.toString(), mappingModel.getName());
} }
attributeValue = valueAsList.get(0); attributeValue = valueAsList.get(0);
@ -124,7 +124,7 @@ public class OIDCAttributeMapperHelper {
boolean consentRequired, String consentText, boolean consentRequired, String consentText,
boolean accessToken, boolean idToken, boolean accessToken, boolean idToken,
String mapperId) { String mapperId) {
return createClaimMapper(name, userAttribute,tokenClaimName, claimType, consentRequired, consentText, accessToken, idToken, false, mapperId); return createClaimMapper(name, userAttribute,tokenClaimName, claimType, consentRequired, consentText, accessToken, idToken, true, mapperId);
} }
public static ProtocolMapperModel createClaimMapper(String name, public static ProtocolMapperModel createClaimMapper(String name,
@ -163,18 +163,34 @@ public class OIDCAttributeMapperHelper {
} }
public static boolean includeInUserInfo(ProtocolMapperModel mappingModel){ public static boolean includeInUserInfo(ProtocolMapperModel mappingModel){
return "true".equals(mappingModel.getConfig().get(INCLUDE_IN_USERINFO)); String includeInUserInfo = mappingModel.getConfig().get(INCLUDE_IN_USERINFO);
// Backwards compatibility
if (includeInUserInfo == null && includeInIDToken(mappingModel)) {
return true;
} }
public static void addAttributeConfig(List<ProviderConfigProperty> configProperties) { return "true".equals(includeInUserInfo);
ProviderConfigProperty property; }
property = new ProviderConfigProperty();
public static void addAttributeConfig(List<ProviderConfigProperty> configProperties, Class<? extends ProtocolMapper> protocolMapperClass) {
addTokenClaimNameConfig(configProperties);
addJsonTypeConfig(configProperties);
addIncludeInTokensConfig(configProperties, protocolMapperClass);
}
public static void addTokenClaimNameConfig(List<ProviderConfigProperty> configProperties) {
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(TOKEN_CLAIM_NAME); property.setName(TOKEN_CLAIM_NAME);
property.setLabel(TOKEN_CLAIM_NAME_LABEL); property.setLabel(TOKEN_CLAIM_NAME_LABEL);
property.setType(ProviderConfigProperty.STRING_TYPE); property.setType(ProviderConfigProperty.STRING_TYPE);
property.setHelpText(TOKEN_CLAIM_NAME_TOOLTIP); property.setHelpText(TOKEN_CLAIM_NAME_TOOLTIP);
configProperties.add(property); configProperties.add(property);
property = new ProviderConfigProperty(); }
public static void addJsonTypeConfig(List<ProviderConfigProperty> configProperties) {
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(JSON_TYPE); property.setName(JSON_TYPE);
property.setLabel(JSON_TYPE); property.setLabel(JSON_TYPE);
List<String> types = new ArrayList(3); List<String> types = new ArrayList(3);
@ -183,29 +199,40 @@ public class OIDCAttributeMapperHelper {
types.add("int"); types.add("int");
types.add("boolean"); types.add("boolean");
property.setType(ProviderConfigProperty.LIST_TYPE); property.setType(ProviderConfigProperty.LIST_TYPE);
property.setDefaultValue(types); property.setOptions(types);
property.setHelpText(JSON_TYPE_TOOLTIP); property.setHelpText(JSON_TYPE_TOOLTIP);
configProperties.add(property); configProperties.add(property);
property = new ProviderConfigProperty(); }
public static void addIncludeInTokensConfig(List<ProviderConfigProperty> configProperties, Class<? extends ProtocolMapper> protocolMapperClass) {
if (OIDCIDTokenMapper.class.isAssignableFrom(protocolMapperClass)) {
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(INCLUDE_IN_ID_TOKEN); property.setName(INCLUDE_IN_ID_TOKEN);
property.setLabel(INCLUDE_IN_ID_TOKEN_LABEL); property.setLabel(INCLUDE_IN_ID_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE); property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true"); property.setDefaultValue("true");
property.setHelpText(INCLUDE_IN_ID_TOKEN_HELP_TEXT); property.setHelpText(INCLUDE_IN_ID_TOKEN_HELP_TEXT);
configProperties.add(property); configProperties.add(property);
property = new ProviderConfigProperty(); }
if (OIDCAccessTokenMapper.class.isAssignableFrom(protocolMapperClass)) {
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(INCLUDE_IN_ACCESS_TOKEN); property.setName(INCLUDE_IN_ACCESS_TOKEN);
property.setLabel(INCLUDE_IN_ACCESS_TOKEN_LABEL); property.setLabel(INCLUDE_IN_ACCESS_TOKEN_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE); property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("true"); property.setDefaultValue("true");
property.setHelpText(INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT); property.setHelpText(INCLUDE_IN_ACCESS_TOKEN_HELP_TEXT);
configProperties.add(property); configProperties.add(property);
property = new ProviderConfigProperty(); }
if (UserInfoTokenMapper.class.isAssignableFrom(protocolMapperClass)) {
ProviderConfigProperty property = new ProviderConfigProperty();
property.setName(INCLUDE_IN_USERINFO); property.setName(INCLUDE_IN_USERINFO);
property.setLabel(INCLUDE_IN_USERINFO_LABEL); property.setLabel(INCLUDE_IN_USERINFO_LABEL);
property.setType(ProviderConfigProperty.BOOLEAN_TYPE); property.setType(ProviderConfigProperty.BOOLEAN_TYPE);
property.setDefaultValue("false"); property.setDefaultValue("true");
property.setHelpText(INCLUDE_IN_USERINFO_HELP_TEXT); property.setHelpText(INCLUDE_IN_USERINFO_HELP_TEXT);
configProperties.add(property); configProperties.add(property);
} }
} }
}

Some files were not shown because too many files have changed in this diff Show more