Merge pull request #5 from patriot1burke/master

more impl and demo start
This commit is contained in:
Bill Burke 2013-07-19 15:03:46 -07:00
commit 32e85e81e9
26 changed files with 949 additions and 339 deletions

View file

@ -0,0 +1,111 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-alpha-1</version>
<relativePath>../../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.keycloak.example.as7.demo</groupId>
<artifactId>keycloak-server</artifactId>
<packaging>war</packaging>
<name>Keycloak Demo</name>
<description/>
<dependencies>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jose-jwt</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-services</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-api</artifactId>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-impl</artifactId>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-schema</artifactId>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-config</artifactId>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>resteasy-jaxrs</artifactId>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</exclusion>
<exclusion>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.161</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.1</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>auth-server</finalName>
<plugins>
<plugin>
<groupId>org.jboss.as.plugins</groupId>
<artifactId>jboss-as-maven-plugin</artifactId>
<version>7.4.Final</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View file

@ -0,0 +1,97 @@
package org.keycloak.example.demo;
import org.jboss.resteasy.jwt.JsonSerialization;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RequiredCredentialModel;
import org.keycloak.services.models.relationships.RealmAdminRelationship;
import org.keycloak.services.models.relationships.RequiredCredentialRelationship;
import org.keycloak.services.models.relationships.ResourceRelationship;
import org.keycloak.services.models.relationships.ScopeRelationship;
import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.resources.RegistrationService;
import org.picketlink.idm.IdentitySession;
import org.picketlink.idm.IdentitySessionFactory;
import org.picketlink.idm.config.IdentityConfiguration;
import org.picketlink.idm.config.IdentityConfigurationBuilder;
import org.picketlink.idm.internal.DefaultIdentitySessionFactory;
import org.picketlink.idm.jpa.internal.ResourceLocalJpaIdentitySessionHandler;
import org.picketlink.idm.jpa.schema.CredentialObject;
import org.picketlink.idm.jpa.schema.CredentialObjectAttribute;
import org.picketlink.idm.jpa.schema.IdentityObject;
import org.picketlink.idm.jpa.schema.IdentityObjectAttribute;
import org.picketlink.idm.jpa.schema.PartitionObject;
import org.picketlink.idm.jpa.schema.RelationshipIdentityObject;
import org.picketlink.idm.jpa.schema.RelationshipObject;
import org.picketlink.idm.jpa.schema.RelationshipObjectAttribute;
import org.picketlink.idm.model.Realm;
import org.picketlink.idm.model.SimpleRole;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Application;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashSet;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class DemoApplication extends KeycloakApplication {
public DemoApplication() {
super();
IdentitySession session = factory.createIdentitySession();
session.getTransaction().begin();
RealmManager realmManager = new RealmManager(session);
if (realmManager.defaultRealm() == null) {
install(realmManager);
}
session.getTransaction().commit();
}
public void install(RealmManager manager) {
RealmModel defaultRealm = manager.createRealm(Realm.DEFAULT_REALM, Realm.DEFAULT_REALM);
defaultRealm.setName(Realm.DEFAULT_REALM);
defaultRealm.setEnabled(true);
defaultRealm.setTokenLifespan(300);
defaultRealm.setAccessCodeLifespan(60);
defaultRealm.setSslNotRequired(false);
defaultRealm.setCookieLoginAllowed(true);
defaultRealm.setRegistrationAllowed(true);
manager.generateRealmKeys(defaultRealm);
defaultRealm.updateRealm();
defaultRealm.addRequiredCredential(RequiredCredentialModel.PASSWORD);
defaultRealm.getIdm().add(new SimpleRole(RegistrationService.REALM_CREATOR_ROLE));
RealmRepresentation rep = loadJson("META-INF/testrealm.json");
RealmModel realm = manager.createRealm("demo", rep.getRealm());
manager.importRealm(rep, realm);
}
public static RealmRepresentation loadJson(String path)
{
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path);
ByteArrayOutputStream os = new ByteArrayOutputStream();
int c;
try {
while ( (c = is.read()) != -1)
{
os.write(c);
}
byte[] bytes = os.toByteArray();
//System.out.println(new String(bytes));
return JsonSerialization.fromBytes(RealmRepresentation.class, bytes);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,29 @@
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version="1.0">
<persistence-unit name="keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.picketlink.idm.jpa.schema.IdentityObject</class>
<class>org.picketlink.idm.jpa.schema.PartitionObject</class>
<class>org.picketlink.idm.jpa.schema.RelationshipObject</class>
<class>org.picketlink.idm.jpa.schema.RelationshipIdentityObject</class>
<class>org.picketlink.idm.jpa.schema.RelationshipIdentityWeakObject</class>
<class>org.picketlink.idm.jpa.schema.RelationshipObjectAttribute</class>
<class>org.picketlink.idm.jpa.schema.IdentityObjectAttribute</class>
<class>org.picketlink.idm.jpa.schema.CredentialObject</class>
<class>org.picketlink.idm.jpa.schema.CredentialObjectAttribute</class>
<properties>
<property name="hibernate.connection.url" value="jdbc:h2:mem:test"/>
<property name="hibernate.connection.driver_class" value="org.h2.Driver"/>
<property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" />
</properties>
</persistence-unit>
</persistence>

View file

@ -0,0 +1,101 @@
{
"realm" : "demo",
"enabled" : true,
"tokenLifespan" : 6000,
"accessCodeLifespan" : 30,
"requiredCredentials" : [
{
"type" : "Password",
"input" : true,
"secret" : true
}
],
"users" : [
{
"username" : "wburke",
"enabled" : true,
"attributes" : {
"email" : "bburke@redhat.com"
},
"credentials" : [
{ "type" : "Password",
"value" : "userpassword" }
]
},
{
"username" : "loginclient",
"enabled" : true,
"credentials" : [
{ "type" : "Password",
"value" : "clientpassword" }
]
},
{
"username" : "admin",
"enabled" : true,
"credentials" : [
{ "type" : "Password",
"value" : "adminpassword" }
]
},
{
"username" : "oauthclient",
"enabled" : true,
"credentials" : [
{ "type" : "Password",
"value" : "clientpassword" }
]
}
],
"roleMappings" : [
{
"username" : "admin",
"roles" : ["admin"]
}
],
"scopeMappings" : [
{
"username" : "loginclient",
"roles" : ["*"]
}
],
"resources" : [
{
"name" : "Application",
"roles" : ["admin", "user"],
"roleMappings" : [
{
"username" : "wburke",
"roles" : ["user"]
},
{
"username" : "admin",
"roles" : ["admin"]
}
],
"scopeMappings" : [
{
"username" : "oauthclient",
"roles" : ["user"]
}
]
},
{
"name" : "OtherApp",
"roles" : ["admin", "user"],
"roleMappings" : [
{
"username" : "wburke",
"roles" : ["user"]
},
{
"username" : "admin",
"roles" : ["admin"]
}
]
}
]
}

View file

@ -0,0 +1,13 @@
<jboss-deployment-structure>
<deployment>
<!-- This allows you to define additional dependencies, it is the same as using the Dependencies: manifest attribute -->
<dependencies>
<!--
<module name="org.jboss.resteasy.resteasy-jaxrs" services="import"/>
<module name="org.jboss.resteasy.resteasy-jackson-provider" services="import"/> -->
<module name="org.jboss.resteasy.jose-jwt"/>
<module name="org.jboss.resteasy.resteasy-crypto"/>
<module name="org.bouncycastle"/>
</dependencies>
</deployment>
</jboss-deployment-structure>

View file

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>org.jboss.resteasy.plugins.server.servlet.HttpServlet30Dispatcher</servlet-class>
<init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.keycloak.example.demo.DemoApplication</param-value>
</init-param>
<init-param>
<param-name>resteasy.servlet.mapping.prefix</param-name>
<param-value>/rest</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
<async-supported>true</async-supported>
</servlet>
<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/rest/*</url-pattern>
</servlet-mapping>
<!--
<security-constraint>
<web-resource-collection>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint> -->
</web-app>

20
examples/pom.xml Executable file
View file

@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<parent>
<artifactId>keycloak-parent</artifactId>
<groupId>org.keycloak</groupId>
<version>1.0-alpha-1</version>
<relativePath>../pom.xml</relativePath>
</parent>
<name>Examples</name>
<description/>
<modelVersion>4.0.0</modelVersion>
<groupId>org.keycloak</groupId>
<artifactId>examples-pom</artifactId>
<packaging>pom</packaging>
<modules>
<module>as7-eap-demo/server</module>
</modules>
</project>

21
pom.xml
View file

@ -55,6 +55,7 @@
<module>core</module> <module>core</module>
<module>services</module> <module>services</module>
<module>integration</module> <module>integration</module>
<module>examples</module>
</modules> </modules>
<dependencyManagement> <dependencyManagement>
@ -69,16 +70,6 @@
<artifactId>bcmail-jdk16</artifactId> <artifactId>bcmail-jdk16</artifactId>
<version>1.46</version> <version>1.46</version>
</dependency> </dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
<version>5.1.6.FINAL</version>
</dependency>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-tree</artifactId>
<version>5.1.6.FINAL</version>
</dependency>
<dependency> <dependency>
<groupId>org.jboss.resteasy</groupId> <groupId>org.jboss.resteasy</groupId>
<artifactId>jaxrs-api</artifactId> <artifactId>jaxrs-api</artifactId>
@ -145,6 +136,11 @@
<artifactId>tjws</artifactId> <artifactId>tjws</artifactId>
<version>${resteasy.version}</version> <version>${resteasy.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-common</artifactId>
<version>2.5.0-SNAPSHOT</version>
</dependency>
<dependency> <dependency>
<groupId>org.picketlink</groupId> <groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-api</artifactId> <artifactId>picketlink-idm-api</artifactId>
@ -165,6 +161,11 @@
<artifactId>picketlink-config</artifactId> <artifactId>picketlink-config</artifactId>
<version>2.5.0-SNAPSHOT</version> <version>2.5.0-SNAPSHOT</version>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<version>3.1.1.GA</version>
</dependency>
<dependency> <dependency>
<groupId>junit</groupId> <groupId>junit</groupId>
<artifactId>junit</artifactId> <artifactId>junit</artifactId>

View file

@ -19,25 +19,35 @@
<version>${project.version}</version> <version>${project.version}</version>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency>
<groupId>org.jboss.logging</groupId>
<artifactId>jboss-logging</artifactId>
<scope>provided</scope>
</dependency>
<dependency> <dependency>
<groupId>org.picketlink</groupId> <groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-api</artifactId> <artifactId>picketlink-idm-api</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.picketlink</groupId>
<artifactId>picketlink-common</artifactId>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.picketlink</groupId> <groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-impl</artifactId> <artifactId>picketlink-idm-impl</artifactId>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.picketlink</groupId> <groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-schema</artifactId> <artifactId>picketlink-idm-schema</artifactId>
<scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.picketlink</groupId> <groupId>org.picketlink</groupId>
<artifactId>picketlink-config</artifactId> <artifactId>picketlink-config</artifactId>
</dependency> <scope>provided</scope>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.jboss.resteasy</groupId> <groupId>org.jboss.resteasy</groupId>

View file

@ -1,5 +1,6 @@
package org.keycloak.services.filters; package org.keycloak.services.filters;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.picketlink.idm.IdentitySession; import org.picketlink.idm.IdentitySession;
import org.picketlink.idm.IdentitySessionFactory; import org.picketlink.idm.IdentitySessionFactory;
@ -17,6 +18,7 @@ import java.io.IOException;
*/ */
@PreMatching @PreMatching
public class IdentitySessionFilter implements ContainerRequestFilter, ContainerResponseFilter { public class IdentitySessionFilter implements ContainerRequestFilter, ContainerResponseFilter {
protected static final Logger logger = Logger.getLogger(IdentitySessionFilter.class);
protected IdentitySessionFactory factory; protected IdentitySessionFactory factory;
public IdentitySessionFilter(IdentitySessionFactory factory) { public IdentitySessionFilter(IdentitySessionFactory factory) {

View file

@ -5,7 +5,6 @@ import org.keycloak.RSATokenVerifier;
import org.keycloak.VerificationException; import org.keycloak.VerificationException;
import org.keycloak.representations.SkeletonKeyToken; import org.keycloak.representations.SkeletonKeyToken;
import org.keycloak.representations.idm.RequiredCredentialRepresentation; import org.keycloak.representations.idm.RequiredCredentialRepresentation;
import org.keycloak.services.models.RealmManager;
import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RequiredCredentialModel; import org.keycloak.services.models.RequiredCredentialModel;
import org.picketlink.idm.credential.Credentials; import org.picketlink.idm.credential.Credentials;

View file

@ -1,6 +1,5 @@
package org.keycloak.services.managers; package org.keycloak.services.managers;
import org.keycloak.services.models.RealmManager;
import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RequiredCredentialModel; import org.keycloak.services.models.RequiredCredentialModel;
import org.keycloak.services.resources.RegistrationService; import org.keycloak.services.resources.RegistrationService;

View file

@ -0,0 +1,295 @@
package org.keycloak.services.managers;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
import org.keycloak.representations.idm.ResourceRepresentation;
import org.keycloak.representations.idm.RoleMappingRepresentation;
import org.keycloak.representations.idm.ScopeMappingRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RequiredCredentialModel;
import org.keycloak.services.models.ResourceModel;
import org.keycloak.services.models.UserCredentialModel;
import org.keycloak.services.resources.RegistrationService;
import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.IdentitySession;
import org.picketlink.idm.model.Attribute;
import org.picketlink.idm.model.Realm;
import org.picketlink.idm.model.Role;
import org.picketlink.idm.model.SimpleAgent;
import org.picketlink.idm.model.SimpleRole;
import org.picketlink.idm.model.SimpleUser;
import org.picketlink.idm.model.User;
import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Response;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RealmManager {
private static AtomicLong counter = new AtomicLong(1);
public static String generateId() {
return counter.getAndIncrement() + "-" + System.currentTimeMillis();
}
protected IdentitySession identitySession;
public RealmManager(IdentitySession IdentitySession) {
this.identitySession = IdentitySession;
}
public RealmModel defaultRealm() {
return getRealm(Realm.DEFAULT_REALM);
}
public RealmModel getRealm(String id) {
Realm existing = identitySession.findRealm(id);
if (existing == null) {
return null;
}
return new RealmModel(existing, identitySession);
}
public RealmModel createRealm(String name) {
return createRealm(generateId(), name);
}
public RealmModel createRealm(String id, String name) {
Realm newRealm = identitySession.createRealm(id);
IdentityManager idm = identitySession.createIdentityManager(newRealm);
SimpleAgent agent = new SimpleAgent(RealmModel.REALM_AGENT_ID);
idm.add(agent);
RealmModel realm = new RealmModel(newRealm, identitySession);
return realm;
}
public void generateRealmKeys(RealmModel realm) {
KeyPair keyPair = null;
try {
keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
realm.setPrivateKey(keyPair.getPrivate());
realm.setPublicKey(keyPair.getPublic());
realm.updateRealm();
}
public RealmModel importRealm(RealmRepresentation rep, User realmCreator) {
verifyRealmRepresentation(rep);
RealmModel realm = createRealm(rep.getRealm());
importRealm(rep, realm);
realm.addRealmAdmin(realmCreator);
realm.updateRealm();
return realm;
}
public void importRealm(RealmRepresentation rep, RealmModel newRealm) {
generateRealmKeys(newRealm);
newRealm.setName(rep.getRealm());
newRealm.setEnabled(rep.isEnabled());
newRealm.setTokenLifespan(rep.getTokenLifespan());
newRealm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
newRealm.setSslNotRequired(rep.isSslNotRequired());
newRealm.setCookieLoginAllowed(rep.isCookieLoginAllowed());
newRealm.updateRealm();
Map<String, User> userMap = new HashMap<String, User>();
for (RequiredCredentialRepresentation requiredCred : rep.getRequiredCredentials()) {
RequiredCredentialModel credential = new RequiredCredentialModel();
credential.setType(requiredCred.getType());
credential.setInput(requiredCred.isInput());
credential.setSecret(requiredCred.isSecret());
newRealm.addRequiredCredential(credential);
}
for (UserRepresentation userRep : rep.getUsers()) {
User user = new SimpleUser(userRep.getUsername());
user.setEnabled(userRep.isEnabled());
if (userRep.getAttributes() != null) {
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet()) {
user.setAttribute(new Attribute<String>(entry.getKey(), entry.getValue()));
}
}
newRealm.getIdm().add(user);
if (userRep.getCredentials() != null) {
for (UserRepresentation.Credential cred : userRep.getCredentials()) {
UserCredentialModel credential = new UserCredentialModel();
credential.setType(cred.getType());
credential.setValue(cred.getValue());
newRealm.updateCredential(user, credential);
}
}
userMap.put(user.getLoginName(), user);
}
Map<String, Role> roles = new HashMap<String, Role>();
if (rep.getRoles() != null) {
for (String roleString : rep.getRoles()) {
SimpleRole role = new SimpleRole(roleString.trim());
newRealm.getIdm().add(role);
roles.put(role.getName(), role);
}
}
if (rep.getRoleMappings() != null) {
for (RoleMappingRepresentation mapping : rep.getRoleMappings()) {
User user = userMap.get(mapping.getUsername());
for (String roleString : mapping.getRoles()) {
Role role = roles.get(roleString.trim());
if (role == null) {
role = new SimpleRole(roleString.trim());
newRealm.getIdm().add(role);
roles.put(role.getName(), role);
}
newRealm.getIdm().grantRole(user, role);
}
}
}
if (rep.getScopeMappings() != null) {
for (ScopeMappingRepresentation scope : rep.getScopeMappings()) {
for (String roleString : scope.getRoles()) {
Role role = roles.get(roleString.trim());
if (role == null) {
role = new SimpleRole(roleString.trim());
newRealm.getIdm().add(role);
roles.put(role.getName(), role);
}
User user = userMap.get(scope.getUsername());
newRealm.addScope(user, role.getName());
}
}
}
if (!roles.containsKey("*")) {
SimpleRole wildcard = new SimpleRole("*");
newRealm.getIdm().add(wildcard);
roles.put("*", wildcard);
}
if (rep.getResources() != null) {
createResources(rep, newRealm, userMap);
}
}
protected void createResources(RealmRepresentation rep, RealmModel realm, Map<String, User> userMap) {
for (ResourceRepresentation resourceRep : rep.getResources()) {
ResourceModel resource = realm.addResource(resourceRep.getName());
resource.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
resource.updateResource();
Map<String, Role> roles = new HashMap<String, Role>();
if (resourceRep.getRoles() != null) {
for (String roleString : resourceRep.getRoles()) {
SimpleRole role = new SimpleRole(roleString.trim());
resource.getIdm().add(role);
roles.put(role.getName(), role);
}
}
if (resourceRep.getRoleMappings() != null) {
for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings()) {
User user = userMap.get(mapping.getUsername());
for (String roleString : mapping.getRoles()) {
Role role = roles.get(roleString.trim());
if (role == null) {
role = new SimpleRole(roleString.trim());
resource.getIdm().add(role);
roles.put(role.getName(), role);
}
Role role1 = resource.getIdm().getRole(role.getName());
realm.getIdm().grantRole(user, role1);
}
}
}
if (resourceRep.getScopeMappings() != null) {
for (ScopeMappingRepresentation mapping : resourceRep.getScopeMappings()) {
User user = userMap.get(mapping.getUsername());
for (String roleString : mapping.getRoles()) {
Role role = roles.get(roleString.trim());
if (role == null) {
role = new SimpleRole(roleString.trim());
resource.getIdm().add(role);
roles.put(role.getName(), role);
}
resource.addScope(user, role.getName());
}
}
}
if (!roles.containsKey("*")) {
SimpleRole wildcard = new SimpleRole("*");
resource.getIdm().add(wildcard);
roles.put("*", wildcard);
}
}
}
protected void verifyRealmRepresentation(RealmRepresentation rep) {
if (rep.getRequiredCredentials() == null) {
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("Realm credential requirements not defined").type("text/plain").build());
}
HashMap<String, UserRepresentation> userReps = new HashMap<String, UserRepresentation>();
for (UserRepresentation userRep : rep.getUsers()) userReps.put(userRep.getUsername(), userRep);
// override enabled to false if user does not have at least all of browser or client credentials
for (UserRepresentation userRep : rep.getUsers()) {
if (userRep.getCredentials() == null) {
userRep.setEnabled(false);
} else {
boolean hasBrowserCredentials = true;
for (RequiredCredentialRepresentation credential : rep.getRequiredCredentials()) {
boolean hasCredential = false;
for (UserRepresentation.Credential cred : userRep.getCredentials()) {
if (cred.getType().equals(credential.getType())) {
hasCredential = true;
break;
}
}
if (!hasCredential) {
hasBrowserCredentials = false;
break;
}
}
if (!hasBrowserCredentials) {
userRep.setEnabled(false);
}
}
}
if (rep.getResources() != null) {
// check mappings
for (ResourceRepresentation resourceRep : rep.getResources()) {
if (resourceRep.getRoleMappings() != null) {
for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings()) {
if (!userReps.containsKey(mapping.getUsername())) {
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("No users declared for role mapping").type("text/plain").build());
}
}
}
}
}
}
}

View file

@ -5,7 +5,6 @@ import org.jboss.resteasy.jose.jws.JWSBuilder;
import org.jboss.resteasy.jwt.JsonSerialization; import org.jboss.resteasy.jwt.JsonSerialization;
import org.keycloak.representations.SkeletonKeyScope; import org.keycloak.representations.SkeletonKeyScope;
import org.keycloak.representations.SkeletonKeyToken; import org.keycloak.representations.SkeletonKeyToken;
import org.keycloak.services.models.RealmManager;
import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.ResourceModel; import org.keycloak.services.models.ResourceModel;
import org.picketlink.idm.model.User; import org.picketlink.idm.model.User;
@ -94,7 +93,7 @@ public class TokenManager {
} }
public SkeletonKeyToken createLoginToken(RealmModel realm, User client, User user) { public SkeletonKeyToken createLoginToken(RealmModel realm, User client, User user) {
Set<String> mapping = realm.getScope(client); Set<String> mapping = realm.getScopes(client);
if (!mapping.contains("*")) { if (!mapping.contains("*")) {
throw new ForbiddenException(Response.status(403).entity("<h1>Security Alert</h1><p>Known client not authorized to request a user login.</p>").type("text/html").build()); throw new ForbiddenException(Response.status(403).entity("<h1>Security Alert</h1><p>Known client not authorized to request a user login.</p>").type("text/html").build());
} }

View file

@ -1,66 +0,0 @@
package org.keycloak.services.models;
import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.IdentitySession;
import org.picketlink.idm.model.Realm;
import org.picketlink.idm.model.SimpleAgent;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RealmManager {
private static AtomicLong counter = new AtomicLong(1);
public static String generateId() {
return counter.getAndIncrement() + "-" + System.currentTimeMillis();
}
protected IdentitySession identitySession;
public RealmManager(IdentitySession IdentitySession) {
this.identitySession = IdentitySession;
}
public RealmModel defaultRealm() {
return getRealm(Realm.DEFAULT_REALM);
}
public RealmModel getRealm(String id) {
Realm existing = identitySession.findRealm(id);
if (existing == null) {
return null;
}
return new RealmModel(existing, identitySession);
}
public RealmModel createRealm(String name) {
return createRealm(generateId(), name);
}
public RealmModel createRealm(String id, String name) {
Realm newRealm = identitySession.createRealm(id);
IdentityManager idm = identitySession.createIdentityManager(newRealm);
SimpleAgent agent = new SimpleAgent(RealmModel.REALM_AGENT_ID);
idm.add(agent);
RealmModel realm = new RealmModel(newRealm, identitySession);
return realm;
}
public void generateRealmKeys(RealmModel realm) {
KeyPair keyPair = null;
try {
keyPair = KeyPairGenerator.getInstance("RSA").generateKeyPair();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
realm.setPrivateKey(keyPair.getPrivate());
realm.setPublicKey(keyPair.getPublic());
realm.updateRealm();
}
}

View file

@ -3,6 +3,7 @@ package org.keycloak.services.models;
import org.bouncycastle.openssl.PEMWriter; import org.bouncycastle.openssl.PEMWriter;
import org.jboss.resteasy.security.PemUtils; import org.jboss.resteasy.security.PemUtils;
import org.keycloak.representations.idm.RequiredCredentialRepresentation; import org.keycloak.representations.idm.RequiredCredentialRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.relationships.RealmAdminRelationship; import org.keycloak.services.models.relationships.RealmAdminRelationship;
import org.keycloak.services.models.relationships.ResourceRelationship; import org.keycloak.services.models.relationships.ResourceRelationship;
import org.keycloak.services.models.relationships.RequiredCredentialRelationship; import org.keycloak.services.models.relationships.RequiredCredentialRelationship;
@ -314,11 +315,12 @@ public class RealmModel {
ScopeRelationship scope = new ScopeRelationship(); ScopeRelationship scope = new ScopeRelationship();
scope.setClient(agent); scope.setClient(agent);
scope.setScope(role); scope.setScope(role);
idm.add(scope);
} }
public Set<String> getScope(Agent agent) { public Set<String> getScopes(Agent agent) {
RelationshipQuery<ScopeRelationship> query = getIdm().createRelationshipQuery(ScopeRelationship.class); RelationshipQuery<ScopeRelationship> query = getIdm().createRelationshipQuery(ScopeRelationship.class);
query.setParameter(ScopeRelationship.CLIENT, agent); query.setParameter(ScopeRelationship.CLIENT, agent);
List<ScopeRelationship> scope = query.getResultList(); List<ScopeRelationship> scope = query.getResultList();

View file

@ -54,7 +54,7 @@ public class KeycloakApplication extends Application {
factory.close(); factory.close();
} }
public static IdentitySessionFactory createFactory() { public IdentitySessionFactory createFactory() {
ResourceLocalJpaIdentitySessionHandler handler = new ResourceLocalJpaIdentitySessionHandler("keycloak-identity-store"); ResourceLocalJpaIdentitySessionHandler handler = new ResourceLocalJpaIdentitySessionHandler("keycloak-identity-store");
IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder(); IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder();

View file

@ -45,22 +45,10 @@ public class RealmSubResource {
public String getRealmHtml(@PathParam("realm") String id) { public String getRealmHtml(@PathParam("realm") String id) {
StringBuffer html = new StringBuffer(); StringBuffer html = new StringBuffer();
UriBuilder auth = uriInfo.getBaseUriBuilder(); String authUri = TokenService.loginPage(uriInfo).build(realm.getId()).toString();
auth.path(TokenService.class) String codeUri = TokenService.accessCodeRequest(uriInfo).build(realm.getId()).toString();
.path(TokenService.class, "requestAccessCode"); String grantUrl = TokenService.grantRequest(uriInfo).build(realm.getId()).toString();
String authUri = auth.build(realm.getId()).toString(); String idGrantUrl = TokenService.identityGrantRequest(uriInfo).build(realm.getId()).toString();
UriBuilder code = uriInfo.getBaseUriBuilder();
code.path(TokenService.class).path(TokenService.class, "accessRequest");
String codeUri = code.build(realm.getId()).toString();
UriBuilder grant = uriInfo.getBaseUriBuilder();
grant.path(TokenService.class).path(TokenService.class, "accessTokenGrant");
String grantUrl = grant.build(realm.getId()).toString();
UriBuilder idGrant = uriInfo.getBaseUriBuilder();
grant.path(TokenService.class).path(TokenService.class, "identityTokenGrant");
String idGrantUrl = idGrant.build(realm.getId()).toString();
html.append("<html><body><h1>Realm: ").append(realm.getName()).append("</h1>"); html.append("<html><body><h1>Realm: ").append(realm.getName()).append("</h1>");
html.append("<p>auth: ").append(authUri).append("</p>"); html.append("<p>auth: ").append(authUri).append("</p>");

View file

@ -2,33 +2,23 @@ package org.keycloak.services.resources;
import org.jboss.resteasy.logging.Logger; import org.jboss.resteasy.logging.Logger;
import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.representations.idm.RequiredCredentialRepresentation;
import org.keycloak.representations.idm.ResourceRepresentation;
import org.keycloak.representations.idm.RoleMappingRepresentation;
import org.keycloak.representations.idm.ScopeMappingRepresentation;
import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.TokenManager; import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.models.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RequiredCredentialModel;
import org.keycloak.services.models.ResourceModel;
import org.keycloak.services.models.UserCredentialModel;
import org.picketlink.idm.IdentitySession; import org.picketlink.idm.IdentitySession;
import org.picketlink.idm.model.Attribute;
import org.picketlink.idm.model.Realm; import org.picketlink.idm.model.Realm;
import org.picketlink.idm.model.Role; import org.picketlink.idm.model.Role;
import org.picketlink.idm.model.SimpleRole;
import org.picketlink.idm.model.SimpleUser;
import org.picketlink.idm.model.User; import org.picketlink.idm.model.User;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.NotAuthorizedException; import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.NotFoundException; import javax.ws.rs.NotFoundException;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam; import javax.ws.rs.PathParam;
import javax.ws.rs.WebApplicationException; import javax.ws.rs.Produces;
import javax.ws.rs.container.ResourceContext; import javax.ws.rs.container.ResourceContext;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.HttpHeaders; import javax.ws.rs.core.HttpHeaders;
@ -36,8 +26,6 @@ import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriBuilder;
import javax.ws.rs.core.UriInfo; import javax.ws.rs.core.UriInfo;
import java.util.HashMap;
import java.util.Map;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -67,6 +55,7 @@ public class RealmsResource {
@Path("{realm}/tokens") @Path("{realm}/tokens")
public TokenService getTokenService(@PathParam("realm") String id) { public TokenService getTokenService(@PathParam("realm") String id) {
logger.info("**** HERE token service****");
RealmManager realmManager = new RealmManager(identitySession); RealmManager realmManager = new RealmManager(identitySession);
RealmModel realm = realmManager.getRealm(id); RealmModel realm = realmManager.getRealm(id);
if (realm == null) { if (realm == null) {
@ -82,6 +71,7 @@ public class RealmsResource {
@Path("{realm}") @Path("{realm}")
public RealmSubResource getRealmResource(@PathParam("realm") String id) { public RealmSubResource getRealmResource(@PathParam("realm") String id) {
logger.info("**** HERE @Path {realm} ****");
RealmManager realmManager = new RealmManager(identitySession); RealmManager realmManager = new RealmManager(identitySession);
RealmModel realm = realmManager.getRealm(id); RealmModel realm = realmManager.getRealm(id);
if (realm == null) { if (realm == null) {
@ -101,7 +91,15 @@ public class RealmsResource {
identitySession.getTransaction().begin(); identitySession.getTransaction().begin();
RealmModel realm; RealmModel realm;
try { try {
realm = createRealm(rep); RealmManager realmManager = new RealmManager(identitySession);
RealmModel defaultRealm = realmManager.getRealm(Realm.DEFAULT_REALM);
User realmCreator = new AuthenticationManager().authenticateToken(defaultRealm, headers);
Role creatorRole = defaultRealm.getIdm().getRole(RegistrationService.REALM_CREATOR_ROLE);
if (!defaultRealm.getIdm().hasRole(realmCreator, creatorRole)) {
logger.warn("not a realm creator");
throw new NotAuthorizedException("Bearer");
}
realm = realmManager.importRealm(rep, realmCreator);
identitySession.getTransaction().commit(); identitySession.getTransaction().commit();
} catch (RuntimeException re) { } catch (RuntimeException re) {
identitySession.getTransaction().rollback(); identitySession.getTransaction().rollback();
@ -112,214 +110,4 @@ public class RealmsResource {
.entity(RealmSubResource.realmRep(realm, uriInfo)) .entity(RealmSubResource.realmRep(realm, uriInfo))
.type(MediaType.APPLICATION_JSON_TYPE).build(); .type(MediaType.APPLICATION_JSON_TYPE).build();
} }
protected RealmModel createRealm(RealmRepresentation rep) {
RealmManager realmManager = new RealmManager(identitySession);
RealmModel defaultRealm = realmManager.getRealm(Realm.DEFAULT_REALM);
User realmCreator = new AuthenticationManager().authenticateToken(defaultRealm, headers);
Role creatorRole = defaultRealm.getIdm().getRole(RegistrationService.REALM_CREATOR_ROLE);
if (!defaultRealm.getIdm().hasRole(realmCreator, creatorRole)) {
logger.warn("not a realm creator");
throw new NotAuthorizedException("Bearer");
}
verifyRealmRepresentation(rep);
RealmModel realm = realmManager.createRealm(rep.getRealm());
realmManager.generateRealmKeys(realm);
realm.addRealmAdmin(realmCreator);
realm.setName(rep.getRealm());
realm.setEnabled(rep.isEnabled());
realm.setTokenLifespan(rep.getTokenLifespan());
realm.setAccessCodeLifespan(rep.getAccessCodeLifespan());
realm.setSslNotRequired(rep.isSslNotRequired());
realm.setCookieLoginAllowed(rep.isCookieLoginAllowed());
realm.updateRealm();
Map<String, User> userMap = new HashMap<String, User>();
for (RequiredCredentialRepresentation requiredCred : rep.getRequiredCredentials()) {
RequiredCredentialModel credential = new RequiredCredentialModel();
credential.setType(requiredCred.getType());
credential.setInput(requiredCred.isInput());
credential.setSecret(requiredCred.isSecret());
realm.addRequiredCredential(credential);
}
for (UserRepresentation userRep : rep.getUsers()) {
User user = new SimpleUser(userRep.getUsername());
user.setEnabled(userRep.isEnabled());
if (userRep.getAttributes() != null) {
for (Map.Entry<String, String> entry : userRep.getAttributes().entrySet()) {
user.setAttribute(new Attribute<String>(entry.getKey(), entry.getValue()));
}
}
realm.getIdm().add(user);
if (userRep.getCredentials() != null) {
for (UserRepresentation.Credential cred : userRep.getCredentials()) {
UserCredentialModel credential = new UserCredentialModel();
credential.setType(cred.getType());
credential.setValue(cred.getValue());
realm.updateCredential(user, credential);
}
}
userMap.put(user.getLoginName(), user);
}
Map<String, Role> roles = new HashMap<String, Role>();
if (rep.getRoles() != null) {
for (String roleString : rep.getRoles()) {
SimpleRole role = new SimpleRole(roleString.trim());
realm.getIdm().add(role);
roles.put(role.getName(), role);
}
}
if (rep.getRoleMappings() != null) {
for (RoleMappingRepresentation mapping : rep.getRoleMappings()) {
User user = userMap.get(mapping.getUsername());
for (String roleString : mapping.getRoles()) {
Role role = roles.get(roleString.trim());
if (role == null) {
role = new SimpleRole(roleString.trim());
realm.getIdm().add(role);
roles.put(role.getName(), role);
}
realm.getIdm().grantRole(user, role);
}
}
}
if (rep.getScopeMappings() != null) {
for (ScopeMappingRepresentation scope : rep.getScopeMappings()) {
for (String roleString : scope.getRoles()) {
Role role = roles.get(roleString.trim());
if (role == null) {
role = new SimpleRole(roleString.trim());
realm.getIdm().add(role);
roles.put(role.getName(), role);
}
User user = userMap.get(scope.getUsername());
realm.addScope(user, role.getName());
}
}
}
if (!roles.containsKey("*")) {
SimpleRole wildcard = new SimpleRole("*");
realm.getIdm().add(wildcard);
roles.put("*", wildcard);
}
if (rep.getResources() != null) {
createResources(rep, realm, userMap);
}
return realm;
}
protected void createResources(RealmRepresentation rep, RealmModel realm, Map<String, User> userMap) {
for (ResourceRepresentation resourceRep : rep.getResources()) {
ResourceModel resource = realm.addResource(resourceRep.getName());
resource.setSurrogateAuthRequired(resourceRep.isSurrogateAuthRequired());
resource.updateResource();
Map<String, Role> roles = new HashMap<String, Role>();
if (resourceRep.getRoles() != null) {
for (String roleString : resourceRep.getRoles()) {
SimpleRole role = new SimpleRole(roleString.trim());
resource.getIdm().add(role);
roles.put(role.getName(), role);
}
}
if (resourceRep.getRoleMappings() != null) {
for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings()) {
User user = userMap.get(mapping.getUsername());
for (String roleString : mapping.getRoles()) {
Role role = roles.get(roleString.trim());
if (role == null) {
role = new SimpleRole(roleString.trim());
resource.getIdm().add(role);
roles.put(role.getName(), role);
}
Role role1 = resource.getIdm().getRole(role.getName());
realm.getIdm().grantRole(user, role1);
}
}
}
if (resourceRep.getScopeMappings() != null) {
for (ScopeMappingRepresentation mapping : resourceRep.getScopeMappings()) {
User user = userMap.get(mapping.getUsername());
for (String roleString : mapping.getRoles()) {
Role role = roles.get(roleString.trim());
if (role == null) {
role = new SimpleRole(roleString.trim());
resource.getIdm().add(role);
roles.put(role.getName(), role);
}
resource.addScope(user, role.getName());
}
}
}
if (!roles.containsKey("*")) {
SimpleRole wildcard = new SimpleRole("*");
resource.getIdm().add(wildcard);
roles.put("*", wildcard);
}
}
}
protected void verifyRealmRepresentation(RealmRepresentation rep) {
if (rep.getRequiredCredentials() == null) {
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("Realm credential requirements not defined").type("text/plain").build());
}
HashMap<String, UserRepresentation> userReps = new HashMap<String, UserRepresentation>();
for (UserRepresentation userRep : rep.getUsers()) userReps.put(userRep.getUsername(), userRep);
// override enabled to false if user does not have at least all of browser or client credentials
for (UserRepresentation userRep : rep.getUsers()) {
if (userRep.getCredentials() == null) {
userRep.setEnabled(false);
} else {
boolean hasBrowserCredentials = true;
for (RequiredCredentialRepresentation credential : rep.getRequiredCredentials()) {
boolean hasCredential = false;
for (UserRepresentation.Credential cred : userRep.getCredentials()) {
if (cred.getType().equals(credential.getType())) {
hasCredential = true;
break;
}
}
if (!hasCredential) {
hasBrowserCredentials = false;
break;
}
}
if (!hasBrowserCredentials) {
userRep.setEnabled(false);
}
}
}
if (rep.getResources() != null) {
// check mappings
for (ResourceRepresentation resourceRep : rep.getResources()) {
if (resourceRep.getRoleMappings() != null) {
for (RoleMappingRepresentation mapping : resourceRep.getRoleMappings()) {
if (!userReps.containsKey(mapping.getUsername())) {
throw new WebApplicationException(Response.status(Response.Status.BAD_REQUEST)
.entity("No users declared for role mapping").type("text/plain").build());
}
}
}
}
}
}
} }

View file

@ -2,7 +2,7 @@ package org.keycloak.services.resources;
import org.jboss.resteasy.logging.Logger; import org.jboss.resteasy.logging.Logger;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.models.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.UserCredentialModel; import org.keycloak.services.models.UserCredentialModel;
import org.picketlink.idm.IdentitySession; import org.picketlink.idm.IdentitySession;
@ -12,8 +12,10 @@ import org.picketlink.idm.model.User;
import javax.ws.rs.Consumes; import javax.ws.rs.Consumes;
import javax.ws.rs.ForbiddenException; import javax.ws.rs.ForbiddenException;
import javax.ws.rs.GET;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context; import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType; import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response; import javax.ws.rs.core.Response;

View file

@ -71,6 +71,36 @@ public class TokenService {
this.tokenManager = tokenManager; this.tokenManager = tokenManager;
} }
public static UriBuilder tokenServiceBase(UriInfo uriInfo) {
UriBuilder base = uriInfo.getBaseUriBuilder()
.path(RealmsResource.class).path(RealmsResource.class, "getTokenService");
return base;
}
public static UriBuilder accessCodeRequest(UriInfo uriInfo) {
return tokenServiceBase(uriInfo).path(TokenService.class, "accessRequest");
}
public static UriBuilder grantRequest(UriInfo uriInfo) {
return tokenServiceBase(uriInfo).path(TokenService.class, "accessTokenGrant");
}
public static UriBuilder identityGrantRequest(UriInfo uriInfo) {
return tokenServiceBase(uriInfo).path(TokenService.class, "accessTokenGrant");
}
public static UriBuilder loginPage(UriInfo uriInfo) {
return tokenServiceBase(uriInfo).path(TokenService.class, "requestAccessCode");
}
public static UriBuilder loginAction(UriInfo uriInfo) {
return tokenServiceBase(uriInfo).path(TokenService.class, "login");
}
@Path("grants/identity-token") @Path("grants/identity-token")
@POST @POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@ -334,7 +364,7 @@ public class TokenService {
} }
html.append("</table><p>To Authorize, please login below</p>"); html.append("</table><p>To Authorize, please login below</p>");
} else { } else {
Set<String> scopeMapping = realm.getScope(client); Set<String> scopeMapping = realm.getScopes(client);
if (scopeMapping.contains("*")) { if (scopeMapping.contains("*")) {
html.append("<h1>Login For ").append(realm.getName()).append(" Realm</h1>"); html.append("<h1>Login For ").append(realm.getName()).append(" Realm</h1>");
if (validationError != null) { if (validationError != null) {
@ -388,7 +418,7 @@ public class TokenService {
} }
} }
UriBuilder formActionUri = uriInfo.getBaseUriBuilder().path(TokenService.class).path(TokenService.class, "login"); UriBuilder formActionUri = loginAction(uriInfo);
String action = formActionUri.build(realm.getId()).toString(); String action = formActionUri.build(realm.getId()).toString();
html.append("<form action=\"").append(action).append("\" method=\"POST\">"); html.append("<form action=\"").append(action).append("\" method=\"POST\">");
html.append("Username: <input type=\"text\" name=\"username\" size=\"20\"><br>"); html.append("Username: <input type=\"text\" name=\"username\" size=\"20\"><br>");

View file

@ -8,17 +8,33 @@ import org.junit.Test;
import org.junit.runners.MethodSorters; import org.junit.runners.MethodSorters;
import org.keycloak.representations.idm.RequiredCredentialRepresentation; import org.keycloak.representations.idm.RequiredCredentialRepresentation;
import org.keycloak.services.managers.InstallationManager; import org.keycloak.services.managers.InstallationManager;
import org.keycloak.services.models.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RequiredCredentialModel; import org.keycloak.services.models.RequiredCredentialModel;
import org.keycloak.services.models.UserCredentialModel; import org.keycloak.services.models.UserCredentialModel;
import org.keycloak.services.models.relationships.RealmAdminRelationship;
import org.keycloak.services.models.relationships.RequiredCredentialRelationship;
import org.keycloak.services.models.relationships.ResourceRelationship;
import org.keycloak.services.models.relationships.ScopeRelationship;
import org.keycloak.services.resources.KeycloakApplication; import org.keycloak.services.resources.KeycloakApplication;
import org.picketlink.idm.IdentitySession; import org.picketlink.idm.IdentitySession;
import org.picketlink.idm.IdentitySessionFactory; import org.picketlink.idm.IdentitySessionFactory;
import org.picketlink.idm.IdentityManager; import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.config.IdentityConfiguration;
import org.picketlink.idm.config.IdentityConfigurationBuilder;
import org.picketlink.idm.credential.Credentials; import org.picketlink.idm.credential.Credentials;
import org.picketlink.idm.credential.Password; import org.picketlink.idm.credential.Password;
import org.picketlink.idm.credential.UsernamePasswordCredentials; import org.picketlink.idm.credential.UsernamePasswordCredentials;
import org.picketlink.idm.internal.DefaultIdentitySessionFactory;
import org.picketlink.idm.jpa.internal.ResourceLocalJpaIdentitySessionHandler;
import org.picketlink.idm.jpa.schema.CredentialObject;
import org.picketlink.idm.jpa.schema.CredentialObjectAttribute;
import org.picketlink.idm.jpa.schema.IdentityObject;
import org.picketlink.idm.jpa.schema.IdentityObjectAttribute;
import org.picketlink.idm.jpa.schema.PartitionObject;
import org.picketlink.idm.jpa.schema.RelationshipIdentityObject;
import org.picketlink.idm.jpa.schema.RelationshipObject;
import org.picketlink.idm.jpa.schema.RelationshipObjectAttribute;
import org.picketlink.idm.model.Role; import org.picketlink.idm.model.Role;
import org.picketlink.idm.model.SimpleRole; import org.picketlink.idm.model.SimpleRole;
import org.picketlink.idm.model.SimpleUser; import org.picketlink.idm.model.SimpleUser;
@ -39,11 +55,35 @@ public class AdapterTest {
@Before @Before
public void before() throws Exception { public void before() throws Exception {
factory = KeycloakApplication.createFactory(); factory = createFactory();
IdentitySession = factory.createIdentitySession(); IdentitySession = factory.createIdentitySession();
adapter = new RealmManager(IdentitySession); adapter = new RealmManager(IdentitySession);
} }
public static IdentitySessionFactory createFactory() {
ResourceLocalJpaIdentitySessionHandler handler = new ResourceLocalJpaIdentitySessionHandler("keycloak-identity-store");
IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder();
builder
.stores()
.jpa()
.identityClass(IdentityObject.class)
.attributeClass(IdentityObjectAttribute.class)
.relationshipClass(RelationshipObject.class)
.relationshipIdentityClass(RelationshipIdentityObject.class)
.relationshipAttributeClass(RelationshipObjectAttribute.class)
.credentialClass(CredentialObject.class)
.credentialAttributeClass(CredentialObjectAttribute.class)
.partitionClass(PartitionObject.class)
.supportAllFeatures()
.supportRelationshipType(RealmAdminRelationship.class, ResourceRelationship.class, RequiredCredentialRelationship.class, ScopeRelationship.class)
.setIdentitySessionHandler(handler);
IdentityConfiguration build = builder.build();
return new DefaultIdentitySessionFactory(build);
}
@After @After
public void after() throws Exception { public void after() throws Exception {
IdentitySession.close(); IdentitySession.close();

View file

@ -0,0 +1,116 @@
package org.keycloak.test;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;
import org.keycloak.representations.idm.RealmRepresentation;
import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RequiredCredentialModel;
import org.keycloak.services.models.relationships.RealmAdminRelationship;
import org.keycloak.services.models.relationships.RequiredCredentialRelationship;
import org.keycloak.services.models.relationships.ResourceRelationship;
import org.keycloak.services.models.relationships.ScopeRelationship;
import org.keycloak.services.resources.RegistrationService;
import org.picketlink.idm.IdentitySession;
import org.picketlink.idm.IdentitySessionFactory;
import org.picketlink.idm.config.IdentityConfiguration;
import org.picketlink.idm.config.IdentityConfigurationBuilder;
import org.picketlink.idm.internal.DefaultIdentitySessionFactory;
import org.picketlink.idm.jpa.internal.ResourceLocalJpaIdentitySessionHandler;
import org.picketlink.idm.jpa.schema.CredentialObject;
import org.picketlink.idm.jpa.schema.CredentialObjectAttribute;
import org.picketlink.idm.jpa.schema.IdentityObject;
import org.picketlink.idm.jpa.schema.IdentityObjectAttribute;
import org.picketlink.idm.jpa.schema.PartitionObject;
import org.picketlink.idm.jpa.schema.RelationshipIdentityObject;
import org.picketlink.idm.jpa.schema.RelationshipObject;
import org.picketlink.idm.jpa.schema.RelationshipObjectAttribute;
import org.picketlink.idm.model.Realm;
import org.picketlink.idm.model.SimpleRole;
import org.picketlink.idm.model.User;
import java.util.Set;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class ImportTest {
private IdentitySessionFactory factory;
private IdentitySession identitySession;
private RealmManager manager;
private RealmModel realmModel;
@Before
public void before() throws Exception {
factory = createFactory();
identitySession = factory.createIdentitySession();
manager = new RealmManager(identitySession);
}
public static IdentitySessionFactory createFactory() {
ResourceLocalJpaIdentitySessionHandler handler = new ResourceLocalJpaIdentitySessionHandler("keycloak-identity-store");
IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder();
builder
.stores()
.jpa()
.identityClass(IdentityObject.class)
.attributeClass(IdentityObjectAttribute.class)
.relationshipClass(RelationshipObject.class)
.relationshipIdentityClass(RelationshipIdentityObject.class)
.relationshipAttributeClass(RelationshipObjectAttribute.class)
.credentialClass(CredentialObject.class)
.credentialAttributeClass(CredentialObjectAttribute.class)
.partitionClass(PartitionObject.class)
.supportAllFeatures()
.supportRelationshipType(RealmAdminRelationship.class, ResourceRelationship.class, RequiredCredentialRelationship.class, ScopeRelationship.class)
.setIdentitySessionHandler(handler);
IdentityConfiguration build = builder.build();
return new DefaultIdentitySessionFactory(build);
}
@After
public void after() throws Exception {
identitySession.close();
factory.close();
}
@Test
public void install() throws Exception {
RealmModel defaultRealm = manager.createRealm(Realm.DEFAULT_REALM, Realm.DEFAULT_REALM);
defaultRealm.setName(Realm.DEFAULT_REALM);
defaultRealm.setEnabled(true);
defaultRealm.setTokenLifespan(300);
defaultRealm.setAccessCodeLifespan(60);
defaultRealm.setSslNotRequired(false);
defaultRealm.setCookieLoginAllowed(true);
defaultRealm.setRegistrationAllowed(true);
manager.generateRealmKeys(defaultRealm);
defaultRealm.updateRealm();
defaultRealm.addRequiredCredential(RequiredCredentialModel.PASSWORD);
defaultRealm.getIdm().add(new SimpleRole(RegistrationService.REALM_CREATOR_ROLE));
RealmRepresentation rep = KeycloakTestBase.loadJson("testrealm.json");
RealmModel realm = manager.createRealm("demo", rep.getRealm());
manager.importRealm(rep, realm);
User user = realm.getIdm().getUser("loginclient");
Assert.assertNotNull(user);
Set<String> scopes = realm.getScopes(user);
System.out.println("Scopes size: " + scopes.size());
Assert.assertTrue(scopes.contains("*"));
}
}

View file

@ -1,10 +1,8 @@
package org.keycloak.test; package org.keycloak.test;
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.spi.ResteasyDeployment; import org.jboss.resteasy.spi.ResteasyDeployment;
import org.jboss.resteasy.test.EmbeddedContainer; import org.jboss.resteasy.test.EmbeddedContainer;
import org.junit.AfterClass;
import org.junit.Assert; import org.junit.Assert;
import org.junit.BeforeClass; import org.junit.BeforeClass;
import org.junit.Test; import org.junit.Test;
@ -15,7 +13,7 @@ import org.keycloak.representations.idm.RequiredCredentialRepresentation;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.InstallationManager; import org.keycloak.services.managers.InstallationManager;
import org.keycloak.services.models.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.resources.KeycloakApplication; import org.keycloak.services.resources.KeycloakApplication;
import org.picketlink.idm.IdentitySession; import org.picketlink.idm.IdentitySession;
import org.picketlink.idm.model.Realm; import org.picketlink.idm.model.Realm;

View file

@ -21,8 +21,8 @@
<property name="hibernate.connection.username" value="sa"/> <property name="hibernate.connection.username" value="sa"/>
<property name="hibernate.connection.password" value=""/> <property name="hibernate.connection.password" value=""/>
<property name="hibernate.hbm2ddl.auto" value="create-drop" /> <property name="hibernate.hbm2ddl.auto" value="create-drop" />
<property name="hibernate.show_sql" value="true" /> <property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="true" /> <property name="hibernate.format_sql" value="false" />
</properties> </properties>
</persistence-unit> </persistence-unit>

2
services/src/test/resources/testrealm.json Normal file → Executable file
View file

@ -56,7 +56,7 @@
"scopeMappings" : [ "scopeMappings" : [
{ {
"username" : "loginclient", "username" : "loginclient",
"roles" : ["login"] "roles" : ["*"]
} }
], ],
"resources" : [ "resources" : [