Merge pull request #15 from patriot1burke/master

picketlink upgrade
This commit is contained in:
Bill Burke 2013-08-01 16:17:40 -07:00
commit 4f673117af
39 changed files with 1566 additions and 778 deletions

View file

@ -40,7 +40,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.picketlink</groupId> <groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-schema</artifactId> <artifactId>picketlink-idm-simple-schema</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.picketlink</groupId> <groupId>org.picketlink</groupId>

View file

@ -5,15 +5,23 @@
<persistence-unit name="keycloak-identity-store" transaction-type="RESOURCE_LOCAL"> <persistence-unit name="keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider> <provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.picketlink.idm.jpa.schema.IdentityObject</class> <class>org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.PartitionObject</class> <class>org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.RelationshipObject</class> <class>org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.RelationshipIdentityObject</class> <class>org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.RelationshipIdentityWeakObject</class> <class>org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.RelationshipObjectAttribute</class> <class>org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.IdentityObjectAttribute</class> <class>org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.CredentialObject</class> <class>org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.CredentialObjectAttribute</class> <class>org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity</class>
<class>org.keycloak.services.models.picketlink.mappings.RealmEntity</class>
<class>org.keycloak.services.models.picketlink.mappings.ResourceEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties> <properties>
<property name="hibernate.connection.url" value="jdbc:h2:mem:test"/> <property name="hibernate.connection.url" value="jdbc:h2:mem:test"/>
@ -21,8 +29,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="false" /> <property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" /> <property name="hibernate.format_sql" value="false" />
</properties> </properties>
</persistence-unit> </persistence-unit>

View file

@ -10,7 +10,7 @@
<properties> <properties>
<resteasy.version>3.0.2.Final</resteasy.version> <resteasy.version>3.0.2.Final</resteasy.version>
<picketlink.version>2.5.0.Keycloak-alpha-1</picketlink.version> <picketlink.version>2.5.0.Beta6</picketlink.version>
</properties> </properties>
<url>http://keycloak.org</url> <url>http://keycloak.org</url>
@ -57,10 +57,11 @@
<module>services</module> <module>services</module>
<module>integration</module> <module>integration</module>
<module>examples</module> <module>examples</module>
<!--
<module>sdk-html</module> <module>sdk-html</module>
<module>social</module> <module>social</module>
<module>server</module> <module>server</module>
<module>ui</module> <module>ui</module> -->
</modules> </modules>
<dependencyManagement> <dependencyManagement>
@ -158,7 +159,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.picketlink</groupId> <groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-schema</artifactId> <artifactId>picketlink-idm-simple-schema</artifactId>
<version>${picketlink.version}</version> <version>${picketlink.version}</version>
</dependency> </dependency>
<dependency> <dependency>

View file

@ -46,7 +46,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.picketlink</groupId> <groupId>org.picketlink</groupId>
<artifactId>picketlink-idm-schema</artifactId> <artifactId>picketlink-idm-simple-schema</artifactId>
<scope>provided</scope> <scope>provided</scope>
</dependency> </dependency>
<dependency> <dependency>

View file

@ -17,11 +17,11 @@ import java.io.IOException;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
@PreMatching @PreMatching
public class KeycloakSessionFilter implements ContainerRequestFilter, ContainerResponseFilter { public class KeycloakSessionRequestFilter implements ContainerRequestFilter, ContainerResponseFilter {
protected static final Logger logger = Logger.getLogger(KeycloakSessionFilter.class); protected static final Logger logger = Logger.getLogger(KeycloakSessionRequestFilter.class);
protected KeycloakSessionFactory factory; protected KeycloakSessionFactory factory;
public KeycloakSessionFilter(KeycloakSessionFactory factory) { public KeycloakSessionRequestFilter(KeycloakSessionFactory factory) {
this.factory = factory; this.factory = factory;
} }

View file

@ -0,0 +1,27 @@
package org.keycloak.services.filters;
import org.jboss.resteasy.logging.Logger;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.KeycloakSessionFactory;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.container.ContainerResponseContext;
import javax.ws.rs.container.ContainerResponseFilter;
import javax.ws.rs.container.PreMatching;
import java.io.IOException;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class KeycloakSessionResponseFilter implements ContainerResponseFilter {
protected static final Logger logger = Logger.getLogger(KeycloakSessionResponseFilter.class);
@Override
public void filter(ContainerRequestContext requestContext, ContainerResponseContext responseContext) throws IOException {
KeycloakSession ctx = (KeycloakSession)requestContext.getProperty(KeycloakSession.class.getName());
if (ctx != null) ctx.close();
}
}

View file

@ -0,0 +1,43 @@
package org.keycloak.services.models.jpa.entities;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.MapKey;
import javax.persistence.OneToMany;
import java.util.Collection;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RealmEntity {
@Id
protected String id;
protected String realmName;
protected boolean enabled;
protected boolean sslNotRequired;
protected boolean cookieLoginAllowed;
protected boolean registrationAllowed;
protected int tokenLifespan;
protected int accessCodeLifespan;
@Column(length = 2048)
protected String publicKeyPem;
@Column(length = 2048)
protected String privateKeyPem;
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
Collection<RequiredCredentailEntity> requiredCredentials;
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
Collection<ResourceEntity> resources;
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
Collection<RoleEntity> roles;
}

View file

@ -0,0 +1,11 @@
package org.keycloak.services.models.jpa.entities;
import javax.persistence.Entity;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class RequiredCredentailEntity {
}

View file

@ -0,0 +1,88 @@
package org.keycloak.services.models.jpa.entities;
import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import java.util.Collection;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class ResourceEntity {
@Id
@GeneratedValue
private String id;
private String resourceName;
private boolean enabled;
private boolean surrogateAuthRequired;
private String managementUrl;
@ManyToOne
private UserEntity resourceUser;
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
Collection<RoleEntity> roles;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getResourceName() {
return resourceName;
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isSurrogateAuthRequired() {
return surrogateAuthRequired;
}
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
this.surrogateAuthRequired = surrogateAuthRequired;
}
public String getManagementUrl() {
return managementUrl;
}
public void setManagementUrl(String managementUrl) {
this.managementUrl = managementUrl;
}
public UserEntity getResourceUser() {
return resourceUser;
}
public void setResourceUser(UserEntity resourceUser) {
this.resourceUser = resourceUser;
}
public Collection<RoleEntity> getRoles() {
return roles;
}
public void setRoles(Collection<RoleEntity> roles) {
this.roles = roles;
}
}

View file

@ -0,0 +1,43 @@
package org.keycloak.services.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class RoleEntity {
@Id
@GeneratedValue
private String id;
private String name;
private String description;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}

View file

@ -0,0 +1,46 @@
package org.keycloak.services.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class ScopeMappingEntity {
@Id
@GeneratedValue
private long id;
@ManyToOne
private UserEntity user;
@ManyToOne
private RoleEntity role;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public RoleEntity getRole() {
return role;
}
public void setRole(RoleEntity role) {
this.role = role;
}
}

View file

@ -0,0 +1,34 @@
package org.keycloak.services.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class UserEntity {
@Id
@GeneratedValue
private String id;
private String loginName;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
}

View file

@ -0,0 +1,47 @@
package org.keycloak.services.models.jpa.entities;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@Entity
public class UserRoleMappingEntity {
@Id
@GeneratedValue
private long id;
@ManyToOne
private UserEntity user;
@ManyToOne
private RoleEntity role;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public UserEntity getUser() {
return user;
}
public void setUser(UserEntity user) {
this.user = user;
}
public RoleEntity getRole() {
return role;
}
public void setRole(RoleEntity role) {
this.role = role;
}
}

View file

@ -4,11 +4,10 @@ import org.jboss.resteasy.spi.NotImplementedYetException;
import org.keycloak.services.models.KeycloakSession; import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.KeycloakTransaction; import org.keycloak.services.models.KeycloakTransaction;
import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.RealmModel;
import org.picketlink.idm.IdentityManager; import org.keycloak.services.models.picketlink.mappings.RealmData;
import org.picketlink.idm.IdentitySession; import org.picketlink.idm.PartitionManager;
import org.picketlink.idm.model.Realm;
import org.picketlink.idm.model.SimpleAgent;
import javax.persistence.EntityManager;
import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicLong;
/** /**
@ -16,20 +15,31 @@ import java.util.concurrent.atomic.AtomicLong;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class PicketlinkKeycloakSession implements KeycloakSession { public class PicketlinkKeycloakSession implements KeycloakSession {
protected IdentitySession session; public static ThreadLocal<EntityManager> currentEntityManager = new ThreadLocal<EntityManager>();
public static ThreadLocal<Exception> setWhere = new ThreadLocal<Exception>();
protected PartitionManager partitionManager;
protected EntityManager entityManager;
private static AtomicLong counter = new AtomicLong(1); private static AtomicLong counter = new AtomicLong(1);
public static String generateId() { public static String generateId() {
return counter.getAndIncrement() + "-" + System.currentTimeMillis(); return counter.getAndIncrement() + "-" + System.currentTimeMillis();
} }
public PicketlinkKeycloakSession(IdentitySession session) { public PicketlinkKeycloakSession(PartitionManager partitionManager, EntityManager entityManager) {
this.session = session; this.partitionManager = partitionManager;
this.entityManager = entityManager;
if (currentEntityManager.get() != null)
{
setWhere.get().printStackTrace();
throw new IllegalStateException("Thread local was leaked!");
}
currentEntityManager.set(entityManager);
setWhere.set(new Exception());
} }
@Override @Override
public KeycloakTransaction getTransaction() { public KeycloakTransaction getTransaction() {
return new PicketlinkKeycloakTransaction(session.getTransaction()); return new PicketlinkKeycloakTransaction(entityManager.getTransaction());
} }
@Override @Override
@ -39,21 +49,22 @@ public class PicketlinkKeycloakSession implements KeycloakSession {
@Override @Override
public RealmAdapter createRealm(String id, String name) { public RealmAdapter createRealm(String id, String name) {
Realm newRealm = session.createRealm(id); // Picketlink beta 6 uses name attribute for getPartition()
IdentityManager idm = session.createIdentityManager(newRealm); RealmData newRealm = new RealmData(id);
SimpleAgent agent = new SimpleAgent(RealmAdapter.REALM_AGENT_ID); newRealm.setId(id);
idm.add(agent); newRealm.setRealmName(name);
RealmAdapter realm = new RealmAdapter(newRealm, session); partitionManager.add(newRealm);
RealmAdapter realm = new RealmAdapter(this, newRealm, partitionManager);
return realm; return realm;
} }
@Override @Override
public RealmAdapter getRealm(String id) { public RealmAdapter getRealm(String id) {
Realm existing = session.findRealm(id); RealmData existing = partitionManager.getPartition(RealmData.class, id);
if (existing == null) { if (existing == null) {
return null; return null;
} }
return new RealmAdapter(existing, session); return new RealmAdapter(this, existing, partitionManager);
} }
@Override @Override
@ -64,6 +75,9 @@ public class PicketlinkKeycloakSession implements KeycloakSession {
@Override @Override
public void close() { public void close() {
session.close(); if (entityManager.getTransaction().isActive()) entityManager.getTransaction().rollback();
setWhere.set(null);
currentEntityManager.set(null);
if (entityManager.isOpen()) entityManager.close();
} }
} }

View file

@ -2,22 +2,26 @@ package org.keycloak.services.models.picketlink;
import org.keycloak.services.models.KeycloakSession; import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.KeycloakSessionFactory; import org.keycloak.services.models.KeycloakSessionFactory;
import org.picketlink.idm.IdentitySessionFactory; import org.picketlink.idm.PartitionManager;
import javax.persistence.EntityManagerFactory;
/** /**
* @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 PicketlinkKeycloakSessionFactory implements KeycloakSessionFactory { public class PicketlinkKeycloakSessionFactory implements KeycloakSessionFactory {
protected IdentitySessionFactory factory; protected EntityManagerFactory factory;
protected PartitionManager partitionManager;
public PicketlinkKeycloakSessionFactory(IdentitySessionFactory factory) { public PicketlinkKeycloakSessionFactory(EntityManagerFactory factory, PartitionManager partitionManager) {
this.factory = factory; this.factory = factory;
this.partitionManager = partitionManager;
} }
@Override @Override
public KeycloakSession createSession() { public KeycloakSession createSession() {
return new PicketlinkKeycloakSession(factory.createIdentitySession()); return new PicketlinkKeycloakSession(partitionManager, factory.createEntityManager());
} }
@Override @Override

View file

@ -1,16 +1,17 @@
package org.keycloak.services.models.picketlink; package org.keycloak.services.models.picketlink;
import org.keycloak.services.models.KeycloakTransaction; import org.keycloak.services.models.KeycloakTransaction;
import org.picketlink.idm.IdentityTransaction;
import javax.persistence.EntityTransaction;
/** /**
* @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 PicketlinkKeycloakTransaction implements KeycloakTransaction{ public class PicketlinkKeycloakTransaction implements KeycloakTransaction {
protected IdentityTransaction transaction; protected EntityTransaction transaction;
public PicketlinkKeycloakTransaction(IdentityTransaction transaction) { public PicketlinkKeycloakTransaction(EntityTransaction transaction) {
this.transaction = transaction; this.transaction = transaction;
} }

View file

@ -4,33 +4,32 @@ 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.managers.RealmManager;
import org.keycloak.services.models.KeycloakSession;
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.ResourceModel; import org.keycloak.services.models.ResourceModel;
import org.keycloak.services.models.RoleModel; import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserCredentialModel; import org.keycloak.services.models.UserCredentialModel;
import org.keycloak.services.models.UserModel; import org.keycloak.services.models.UserModel;
import org.keycloak.services.models.picketlink.mappings.RealmData;
import org.keycloak.services.models.picketlink.mappings.ResourceData;
import org.keycloak.services.models.picketlink.relationships.RealmAdminRelationship; import org.keycloak.services.models.picketlink.relationships.RealmAdminRelationship;
import org.keycloak.services.models.picketlink.relationships.RequiredCredentialRelationship; import org.keycloak.services.models.picketlink.relationships.RequiredCredentialRelationship;
import org.keycloak.services.models.picketlink.relationships.ResourceRelationship; import org.keycloak.services.models.picketlink.relationships.ResourceRelationship;
import org.keycloak.services.models.picketlink.relationships.ScopeRelationship; import org.keycloak.services.models.picketlink.relationships.ScopeRelationship;
import org.picketlink.idm.IdentityManager; import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.IdentitySession; import org.picketlink.idm.PartitionManager;
import org.picketlink.idm.RelationshipManager;
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.TOTPCredential; import org.picketlink.idm.credential.TOTPCredential;
import org.picketlink.idm.credential.TOTPCredentials; import org.picketlink.idm.credential.TOTPCredentials;
import org.picketlink.idm.credential.UsernamePasswordCredentials; import org.picketlink.idm.credential.UsernamePasswordCredentials;
import org.picketlink.idm.credential.X509CertificateCredentials; import org.picketlink.idm.credential.X509CertificateCredentials;
import org.picketlink.idm.model.Agent; import org.picketlink.idm.model.sample.Grant;
import org.picketlink.idm.model.Attribute; import org.picketlink.idm.model.sample.Role;
import org.picketlink.idm.model.Grant; import org.picketlink.idm.model.sample.SampleModel;
import org.picketlink.idm.model.Realm; import org.picketlink.idm.model.sample.User;
import org.picketlink.idm.model.Role;
import org.picketlink.idm.model.SimpleRole;
import org.picketlink.idm.model.SimpleUser;
import org.picketlink.idm.model.Tier;
import org.picketlink.idm.model.User;
import org.picketlink.idm.query.IdentityQuery; import org.picketlink.idm.query.IdentityQuery;
import org.picketlink.idm.query.RelationshipQuery; import org.picketlink.idm.query.RelationshipQuery;
@ -53,140 +52,138 @@ import java.util.Set;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class RealmAdapter implements RealmModel { public class RealmAdapter implements RealmModel {
public static final String REALM_AGENT_ID = "_realm_";
public static final String REALM_NAME = "name";
public static final String REALM_ACCESS_CODE_LIFESPAN = "accessCodeLifespan";
public static final String REALM_TOKEN_LIFESPAN = "tokenLifespan";
public static final String REALM_PRIVATE_KEY = "privateKey";
public static final String REALM_PUBLIC_KEY = "publicKey";
public static final String REALM_IS_SSL_NOT_REQUIRED = "isSSLNotRequired";
public static final String REALM_IS_COOKIE_LOGIN_ALLOWED = "isCookieLoginAllowed";
public static final String REALM_IS_REGISTRATION_ALLOWED = "isRegistrationAllowed";
protected Realm realm; protected RealmData realm;
protected Agent realmAgent;
protected IdentitySession identitySession;
protected volatile transient PublicKey publicKey; protected volatile transient PublicKey publicKey;
protected volatile transient PrivateKey privateKey; protected volatile transient PrivateKey privateKey;
protected IdentityManager idm; protected IdentityManager idm;
protected PartitionManager partitionManager;
protected RelationshipManager relationshipManager;
protected KeycloakSession session;
public RealmAdapter(Realm realm, IdentitySession session) { public RealmAdapter(KeycloakSession session, RealmData realm, PartitionManager partitionManager) {
this.session = session;
this.realm = realm; this.realm = realm;
this.identitySession = session; this.partitionManager = partitionManager;
realmAgent = getIdm().getAgent(REALM_AGENT_ID);
} }
protected IdentityManager getIdm() { protected IdentityManager getIdm() {
if (idm == null) idm = identitySession.createIdentityManager(realm); if (idm == null) idm = partitionManager.createIdentityManager(realm);
return idm; return idm;
} }
protected RelationshipManager getRelationshipManager() {
if (relationshipManager == null) relationshipManager = partitionManager.createRelationshipManager();
return relationshipManager;
}
protected void updateRealm() { protected void updateRealm() {
getIdm().update(realmAgent); partitionManager.update(realm);
} }
@Override @Override
public String getId() { public String getId() {
return realm.getId(); // for some reason picketlink queries by name when finding partition, don't know what ID is used for now
return realm.getName();
} }
@Override @Override
public String getName() { public String getName() {
return (String) realmAgent.getAttribute(REALM_NAME).getValue(); return realm.getRealmName();
} }
@Override @Override
public void setName(String name) { public void setName(String name) {
realmAgent.setAttribute(new Attribute<String>(REALM_NAME, name)); realm.setRealmName(name);
updateRealm(); updateRealm();
} }
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return realmAgent.isEnabled(); return realm.isEnabled();
} }
@Override @Override
public void setEnabled(boolean enabled) { public void setEnabled(boolean enabled) {
realmAgent.setEnabled(enabled); realm.setEnabled(enabled);
updateRealm(); updateRealm();
} }
@Override @Override
public boolean isSslNotRequired() { public boolean isSslNotRequired() {
return (Boolean) realmAgent.getAttribute(REALM_IS_SSL_NOT_REQUIRED).getValue(); return realm.isSslNotRequired();
} }
@Override @Override
public void setSslNotRequired(boolean sslNotRequired) { public void setSslNotRequired(boolean sslNotRequired) {
realmAgent.setAttribute(new Attribute<Boolean>(REALM_IS_SSL_NOT_REQUIRED, sslNotRequired)); realm.setSslNotRequired(sslNotRequired);
updateRealm(); updateRealm();
} }
@Override @Override
public boolean isCookieLoginAllowed() { public boolean isCookieLoginAllowed() {
return (Boolean) realmAgent.getAttribute(REALM_IS_COOKIE_LOGIN_ALLOWED).getValue(); return realm.isCookieLoginAllowed();
} }
@Override @Override
public void setCookieLoginAllowed(boolean cookieLoginAllowed) { public void setCookieLoginAllowed(boolean cookieLoginAllowed) {
realmAgent.setAttribute(new Attribute<Boolean>(REALM_IS_COOKIE_LOGIN_ALLOWED, cookieLoginAllowed)); realm.setCookieLoginAllowed(cookieLoginAllowed);
updateRealm(); updateRealm();
} }
@Override @Override
public boolean isRegistrationAllowed() { public boolean isRegistrationAllowed() {
return (Boolean) realmAgent.getAttribute(REALM_IS_REGISTRATION_ALLOWED).getValue(); return realm.isRegistrationAllowed();
} }
@Override @Override
public void setRegistrationAllowed(boolean registrationAllowed) { public void setRegistrationAllowed(boolean registrationAllowed) {
realmAgent.setAttribute(new Attribute<Boolean>(REALM_IS_REGISTRATION_ALLOWED, registrationAllowed)); realm.setRegistrationAllowed(registrationAllowed);
updateRealm(); updateRealm();
} }
@Override @Override
public int getTokenLifespan() { public int getTokenLifespan() {
return (Integer) realmAgent.getAttribute(REALM_TOKEN_LIFESPAN).getValue(); return realm.getTokenLifespan();
} }
@Override @Override
public void setTokenLifespan(int tokenLifespan) { public void setTokenLifespan(int tokenLifespan) {
realmAgent.setAttribute(new Attribute<Integer>(REALM_TOKEN_LIFESPAN, tokenLifespan)); realm.setTokenLifespan(tokenLifespan);
updateRealm(); updateRealm();
} }
@Override @Override
public int getAccessCodeLifespan() { public int getAccessCodeLifespan() {
return (Integer) realmAgent.getAttribute(REALM_ACCESS_CODE_LIFESPAN).getValue(); return realm.getAccessCodeLifespan();
} }
@Override @Override
public void setAccessCodeLifespan(int accessCodeLifespan) { public void setAccessCodeLifespan(int accessCodeLifespan) {
realmAgent.setAttribute(new Attribute<Integer>(REALM_ACCESS_CODE_LIFESPAN, accessCodeLifespan)); realm.setAccessCodeLifespan(accessCodeLifespan);
updateRealm(); updateRealm();
} }
@Override @Override
public String getPublicKeyPem() { public String getPublicKeyPem() {
return (String) realmAgent.getAttribute(REALM_PUBLIC_KEY).getValue(); return realm.getPublicKeyPem();
} }
@Override @Override
public void setPublicKeyPem(String publicKeyPem) { public void setPublicKeyPem(String publicKeyPem) {
realmAgent.setAttribute(new Attribute<String>(REALM_PUBLIC_KEY, publicKeyPem)); realm.setPublicKeyPem(publicKeyPem);
this.publicKey = null; this.publicKey = null;
updateRealm(); updateRealm();
} }
@Override @Override
public String getPrivateKeyPem() { public String getPrivateKeyPem() {
return (String) realmAgent.getAttribute(REALM_PRIVATE_KEY).getValue(); return realm.getPrivateKeyPem();
} }
@Override @Override
public void setPrivateKeyPem(String privateKeyPem) { public void setPrivateKeyPem(String privateKeyPem) {
realmAgent.setAttribute(new Attribute<String>(REALM_PRIVATE_KEY, privateKeyPem)); realm.setPrivateKeyPem(privateKeyPem);
this.privateKey = null; this.privateKey = null;
updateRealm(); updateRealm();
} }
@ -251,10 +248,8 @@ public class RealmAdapter implements RealmModel {
@Override @Override
public List<RequiredCredentialModel> getRequiredCredentials() { public List<RequiredCredentialModel> getRequiredCredentials() {
IdentityManager idm = getIdm(); RelationshipQuery<RequiredCredentialRelationship> query = getRelationshipManager().createRelationshipQuery(RequiredCredentialRelationship.class);
Agent realmAgent = idm.getAgent(REALM_AGENT_ID); query.setParameter(RequiredCredentialRelationship.REALM, realm.getName());
RelationshipQuery<RequiredCredentialRelationship> query = idm.createRelationshipQuery(RequiredCredentialRelationship.class);
query.setParameter(RequiredCredentialRelationship.REALM_AGENT, realmAgent);
List<RequiredCredentialRelationship> results = query.getResultList(); List<RequiredCredentialRelationship> results = query.getResultList();
List<RequiredCredentialModel> rtn = new ArrayList<RequiredCredentialModel>(); List<RequiredCredentialModel> rtn = new ArrayList<RequiredCredentialModel>();
for (RequiredCredentialRelationship relationship : results) { for (RequiredCredentialRelationship relationship : results) {
@ -269,16 +264,15 @@ public class RealmAdapter implements RealmModel {
@Override @Override
public void addRequiredCredential(RequiredCredentialModel cred) { public void addRequiredCredential(RequiredCredentialModel cred) {
IdentityManager idm = getIdm();
Agent realmAgent = idm.getAgent(REALM_AGENT_ID);
RequiredCredentialRelationship relationship = new RequiredCredentialRelationship(); RequiredCredentialRelationship relationship = new RequiredCredentialRelationship();
relationship.setCredentialType(cred.getType()); relationship.setCredentialType(cred.getType());
relationship.setInput(cred.isInput()); relationship.setInput(cred.isInput());
relationship.setSecret(cred.isSecret()); relationship.setSecret(cred.isSecret());
relationship.setRealmAgent(realmAgent); relationship.setRealm(realm.getName());
idm.add(relationship); getRelationshipManager().add(relationship);
} }
@Override @Override
public boolean validatePassword(UserModel user, String password) { public boolean validatePassword(UserModel user, String password) {
UsernamePasswordCredentials creds = new UsernamePasswordCredentials(user.getLoginName(), new Password(password)); UsernamePasswordCredentials creds = new UsernamePasswordCredentials(user.getLoginName(), new Password(password));
@ -319,30 +313,34 @@ public class RealmAdapter implements RealmModel {
@Override @Override
public UserAdapter getUser(String name) { public UserAdapter getUser(String name) {
User user = getIdm().getUser(name); User user = findPicketlinkUser(name);
if (user == null) return null; if (user == null) return null;
return new UserAdapter(user, getIdm()); return new UserAdapter(user, getIdm());
} }
protected User findPicketlinkUser(String name) {
return SampleModel.getUser(getIdm(), name);
}
@Override @Override
public UserAdapter addUser(String username) { public UserAdapter addUser(String username) {
User user = getIdm().getUser(username); User user = findPicketlinkUser(username);
if (user != null) throw new IllegalStateException("User already exists"); if (user != null) throw new IllegalStateException("User already exists");
user = new SimpleUser(username); user = new User(username);
getIdm().add(user); getIdm().add(user);
return new UserAdapter(user, getIdm()); return new UserAdapter(user, getIdm());
} }
@Override @Override
public RoleAdapter getRole(String name) { public RoleAdapter getRole(String name) {
Role role = getIdm().getRole(name); Role role = SampleModel.getRole(getIdm(), name);
if (role == null) return null; if (role == null) return null;
return new RoleAdapter(role, getIdm()); return new RoleAdapter(role, getIdm());
} }
@Override @Override
public RoleAdapter addRole(String name) { public RoleAdapter addRole(String name) {
Role role = new SimpleRole(name); Role role = new Role(name);
getIdm().add(role); getIdm().add(role);
return new RoleAdapter(role, getIdm()); return new RoleAdapter(role, getIdm());
} }
@ -377,14 +375,13 @@ public class RealmAdapter implements RealmModel {
@Override @Override
public List<ResourceModel> getResources() { public List<ResourceModel> getResources() {
IdentityManager idm = getIdm(); RelationshipQuery<ResourceRelationship> query = getRelationshipManager().createRelationshipQuery(ResourceRelationship.class);
RelationshipQuery<ResourceRelationship> query = idm.createRelationshipQuery(ResourceRelationship.class); query.setParameter(ResourceRelationship.REALM, realm.getName());
query.setParameter(ResourceRelationship.REALM_AGENT, realmAgent);
List<ResourceRelationship> results = query.getResultList(); List<ResourceRelationship> results = query.getResultList();
List<ResourceModel> resources = new ArrayList<ResourceModel>(); List<ResourceModel> resources = new ArrayList<ResourceModel>();
for (ResourceRelationship relationship : results) { for (ResourceRelationship relationship : results) {
Tier resourceTier = identitySession.findTier(relationship.getResourceId()); ResourceData resource = partitionManager.getPartition(ResourceData.class, relationship.getResource());
ResourceModel model = new ResourceAdapter(resourceTier,relationship, this, identitySession); ResourceModel model = new ResourceAdapter(resource, this, partitionManager);
resources.add(model); resources.add(model);
} }
@ -393,18 +390,12 @@ public class RealmAdapter implements RealmModel {
@Override @Override
public ResourceModel addResource(String name) { public ResourceModel addResource(String name) {
Tier newTier = identitySession.createTier(RealmManager.generateId()); ResourceData resourceData = new ResourceData(name);
IdentityManager idm = getIdm(); User resourceUser = new User(name);
ResourceRelationship relationship = new ResourceRelationship();
relationship.setResourceName(name);
relationship.setRealmAgent(realmAgent);
relationship.setResourceId(newTier.getId());
relationship.setManagementUrl(""); // Picketlink doesn't like null attribute values
User resourceUser = new SimpleUser(name);
idm.add(resourceUser); idm.add(resourceUser);
relationship.setResourceUser(resourceUser); resourceData.setResourceUser(resourceUser);
idm.add(relationship); partitionManager.add(resourceData);
ResourceModel resource = new ResourceAdapter(newTier, relationship, this, identitySession); ResourceModel resource = new ResourceAdapter(resourceData, this, partitionManager);
resource.addRole("*"); resource.addRole("*");
resource.addScope(new UserAdapter(resourceUser, idm), "*"); resource.addScope(new UserAdapter(resourceUser, idm), "*");
return resource; return resource;
@ -412,17 +403,17 @@ public class RealmAdapter implements RealmModel {
@Override @Override
public boolean hasRole(UserModel user, RoleModel role) { public boolean hasRole(UserModel user, RoleModel role) {
return getIdm().hasRole(((UserAdapter)user).getUser(), ((RoleAdapter)role).getRole()); return SampleModel.hasRole(getRelationshipManager(), ((UserAdapter) user).getUser(), ((RoleAdapter) role).getRole());
} }
@Override @Override
public void grantRole(UserModel user, RoleModel role) { public void grantRole(UserModel user, RoleModel role) {
getIdm().grantRole(((UserAdapter)user).getUser(), ((RoleAdapter)role).getRole()); SampleModel.grantRole(getRelationshipManager(), ((UserAdapter) user).getUser(), ((RoleAdapter) role).getRole());
} }
@Override @Override
public Set<String> getRoleMappings(UserModel user) { public Set<String> getRoleMappings(UserModel user) {
RelationshipQuery<Grant> query = getIdm().createRelationshipQuery(Grant.class); RelationshipQuery<Grant> query = getRelationshipManager().createRelationshipQuery(Grant.class);
query.setParameter(Grant.ASSIGNEE, ((UserAdapter)user).getUser()); query.setParameter(Grant.ASSIGNEE, ((UserAdapter)user).getUser());
List<Grant> grants = query.getResultList(); List<Grant> grants = query.getResultList();
HashSet<String> set = new HashSet<String>(); HashSet<String> set = new HashSet<String>();
@ -435,19 +426,18 @@ public class RealmAdapter implements RealmModel {
@Override @Override
public void addScope(UserModel agent, String roleName) { public void addScope(UserModel agent, String roleName) {
IdentityManager idm = getIdm(); IdentityManager idm = getIdm();
Role role = idm.getRole(roleName); Role role = SampleModel.getRole(idm, roleName);
if (role == null) throw new RuntimeException("role not found"); if (role == null) throw new RuntimeException("role not found");
ScopeRelationship scope = new ScopeRelationship(); ScopeRelationship scope = new ScopeRelationship();
scope.setClient(((UserAdapter)agent).getUser()); scope.setClient(((UserAdapter)agent).getUser());
scope.setScope(role); scope.setScope(role);
idm.add(scope); getRelationshipManager().add(scope);
} }
@Override @Override
public Set<String> getScope(UserModel agent) { public Set<String> getScope(UserModel agent) {
RelationshipQuery<ScopeRelationship> query = getIdm().createRelationshipQuery(ScopeRelationship.class); RelationshipQuery<ScopeRelationship> query = getRelationshipManager().createRelationshipQuery(ScopeRelationship.class);
query.setParameter(ScopeRelationship.CLIENT, ((UserAdapter)agent).getUser()); query.setParameter(ScopeRelationship.CLIENT, ((UserAdapter)agent).getUser());
List<ScopeRelationship> scope = query.getResultList(); List<ScopeRelationship> scope = query.getResultList();
HashSet<String> set = new HashSet<String>(); HashSet<String> set = new HashSet<String>();
@ -459,10 +449,9 @@ public class RealmAdapter implements RealmModel {
@Override @Override
public boolean isRealmAdmin(UserModel agent) { public boolean isRealmAdmin(UserModel agent) {
RealmAdapter realmModel = (RealmAdapter)new RealmManager(new PicketlinkKeycloakSession(identitySession)).defaultRealm(); RealmAdapter realmModel = (RealmAdapter)new RealmManager(session).defaultRealm();
IdentityManager idm = realmModel.getIdm(); RelationshipQuery<RealmAdminRelationship> query = getRelationshipManager().createRelationshipQuery(RealmAdminRelationship.class);
RelationshipQuery<RealmAdminRelationship> query = idm.createRelationshipQuery(RealmAdminRelationship.class); query.setParameter(RealmAdminRelationship.REALM, realm.getName());
query.setParameter(RealmAdminRelationship.REALM, realm.getId());
query.setParameter(RealmAdminRelationship.ADMIN, ((UserAdapter)agent).getUser()); query.setParameter(RealmAdminRelationship.ADMIN, ((UserAdapter)agent).getUser());
List<RealmAdminRelationship> results = query.getResultList(); List<RealmAdminRelationship> results = query.getResultList();
return results.size() > 0; return results.size() > 0;
@ -470,10 +459,9 @@ public class RealmAdapter implements RealmModel {
@Override @Override
public void addRealmAdmin(UserModel agent) { public void addRealmAdmin(UserModel agent) {
RealmAdapter realmModel = (RealmAdapter)new RealmManager(new PicketlinkKeycloakSession(identitySession)).defaultRealm();
RealmAdminRelationship relationship = new RealmAdminRelationship(); RealmAdminRelationship relationship = new RealmAdminRelationship();
relationship.setAdmin(((UserAdapter)agent).getUser()); relationship.setAdmin(((UserAdapter)agent).getUser());
relationship.setRealm(realm.getId()); relationship.setRealm(realm.getName());
idm.add(relationship); getRelationshipManager().add(relationship);
} }
} }

View file

@ -3,14 +3,15 @@ package org.keycloak.services.models.picketlink;
import org.keycloak.services.models.ResourceModel; import org.keycloak.services.models.ResourceModel;
import org.keycloak.services.models.RoleModel; import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserModel; import org.keycloak.services.models.UserModel;
import org.keycloak.services.models.picketlink.mappings.ResourceData;
import org.keycloak.services.models.picketlink.relationships.ResourceRelationship; import org.keycloak.services.models.picketlink.relationships.ResourceRelationship;
import org.keycloak.services.models.picketlink.relationships.ScopeRelationship; import org.keycloak.services.models.picketlink.relationships.ScopeRelationship;
import org.picketlink.idm.IdentityManager; import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.IdentitySession; import org.picketlink.idm.PartitionManager;
import org.picketlink.idm.model.Grant; import org.picketlink.idm.RelationshipManager;
import org.picketlink.idm.model.Role; import org.picketlink.idm.model.sample.Grant;
import org.picketlink.idm.model.SimpleRole; import org.picketlink.idm.model.sample.Role;
import org.picketlink.idm.model.Tier; import org.picketlink.idm.model.sample.SampleModel;
import org.picketlink.idm.query.IdentityQuery; import org.picketlink.idm.query.IdentityQuery;
import org.picketlink.idm.query.RelationshipQuery; import org.picketlink.idm.query.RelationshipQuery;
@ -24,89 +25,94 @@ import java.util.Set;
* @version $Revision: 1 $ * @version $Revision: 1 $
*/ */
public class ResourceAdapter implements ResourceModel { public class ResourceAdapter implements ResourceModel {
protected Tier tier; protected ResourceData resource;
protected ResourceRelationship agent;
protected RealmAdapter realm; protected RealmAdapter realm;
protected IdentitySession identitySession;
protected IdentityManager idm; protected IdentityManager idm;
protected PartitionManager partitionManager;
protected RelationshipManager relationshipManager;
public ResourceAdapter(Tier tier, ResourceRelationship agent, RealmAdapter realm, IdentitySession session) { public ResourceAdapter(ResourceData resource, RealmAdapter realm, PartitionManager partitionManager) {
this.tier = tier; this.resource = resource;
this.agent = agent;
this.realm = realm; this.realm = realm;
this.identitySession = session; this.partitionManager = partitionManager;
} }
protected IdentityManager getIdm() { protected IdentityManager getIdm() {
if (idm == null) idm = identitySession.createIdentityManager(tier); if (idm == null) idm = partitionManager.createIdentityManager(resource);
return idm; return idm;
} }
protected RelationshipManager getRelationshipManager() {
if (relationshipManager == null) relationshipManager = partitionManager.createRelationshipManager();
return relationshipManager;
}
@Override @Override
public void updateResource() { public void updateResource() {
getIdm().update(agent); partitionManager.update(resource);
} }
@Override @Override
public UserAdapter getResourceUser() { public UserAdapter getResourceUser() {
return new UserAdapter(agent.getResourceUser(), realm.getIdm()); return new UserAdapter(resource.getResourceUser(), realm.getIdm());
} }
@Override @Override
public String getId() { public String getId() {
return tier.getId(); // for some reason picketlink queries by name when finding partition, don't know what ID is used for now
return resource.getName();
} }
@Override @Override
public String getName() { public String getName() {
return agent.getResourceName(); return resource.getResourceName();
} }
@Override @Override
public void setName(String name) { public void setName(String name) {
agent.setResourceName(name); resource.setResourceName(name);
} }
@Override @Override
public boolean isEnabled() { public boolean isEnabled() {
return agent.getEnabled(); return resource.isEnabled();
} }
@Override @Override
public void setEnabled(boolean enabled) { public void setEnabled(boolean enabled) {
agent.setEnabled(enabled); resource.setEnabled(enabled);
} }
@Override @Override
public boolean isSurrogateAuthRequired() { public boolean isSurrogateAuthRequired() {
return agent.getSurrogateAuthRequired(); return resource.isSurrogateAuthRequired();
} }
@Override @Override
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) { public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
agent.setSurrogateAuthRequired(surrogateAuthRequired); resource.setSurrogateAuthRequired(surrogateAuthRequired);
} }
@Override @Override
public String getManagementUrl() { public String getManagementUrl() {
return agent.getManagementUrl(); return resource.getManagementUrl();
} }
@Override @Override
public void setManagementUrl(String url) { public void setManagementUrl(String url) {
agent.setManagementUrl(url); resource.setManagementUrl(url);
} }
@Override @Override
public RoleAdapter getRole(String name) { public RoleAdapter getRole(String name) {
Role role = getIdm().getRole(name); Role role = SampleModel.getRole(getIdm(), name);
if (role == null) return null; if (role == null) return null;
return new RoleAdapter(role, getIdm()); return new RoleAdapter(role, getIdm());
} }
@Override @Override
public RoleAdapter addRole(String name) { public RoleAdapter addRole(String name) {
Role role = new SimpleRole(name); Role role = new Role(name);
getIdm().add(role); getIdm().add(role);
return new RoleAdapter(role, getIdm()); return new RoleAdapter(role, getIdm());
} }
@ -114,7 +120,7 @@ public class ResourceAdapter implements ResourceModel {
@Override @Override
public List<RoleModel> getRoles() { public List<RoleModel> getRoles() {
IdentityQuery<Role> query = getIdm().createIdentityQuery(Role.class); IdentityQuery<Role> query = getIdm().createIdentityQuery(Role.class);
query.setParameter(Role.PARTITION, tier); query.setParameter(Role.PARTITION, resource);
List<Role> roles = query.getResultList(); List<Role> roles = query.getResultList();
List<RoleModel> roleModels = new ArrayList<RoleModel>(); List<RoleModel> roleModels = new ArrayList<RoleModel>();
for (Role role : roles) { for (Role role : roles) {
@ -125,12 +131,12 @@ public class ResourceAdapter implements ResourceModel {
@Override @Override
public Set<String> getRoleMappings(UserModel user) { public Set<String> getRoleMappings(UserModel user) {
RelationshipQuery<Grant> query = getIdm().createRelationshipQuery(Grant.class); RelationshipQuery<Grant> query = getRelationshipManager().createRelationshipQuery(Grant.class);
query.setParameter(Grant.ASSIGNEE, ((UserAdapter)user).getUser()); query.setParameter(Grant.ASSIGNEE, ((UserAdapter)user).getUser());
List<Grant> grants = query.getResultList(); List<Grant> grants = query.getResultList();
HashSet<String> set = new HashSet<String>(); HashSet<String> set = new HashSet<String>();
for (Grant grant : grants) { for (Grant grant : grants) {
if (grant.getRole().getPartition().getId().equals(tier.getId())) set.add(grant.getRole().getName()); if (grant.getRole().getPartition().getId().equals(resource.getId())) set.add(grant.getRole().getName());
} }
return set; return set;
} }
@ -138,7 +144,7 @@ public class ResourceAdapter implements ResourceModel {
@Override @Override
public void addScope(UserModel agent, String roleName) { public void addScope(UserModel agent, String roleName) {
IdentityManager idm = getIdm(); IdentityManager idm = getIdm();
Role role = idm.getRole(roleName); Role role = SampleModel.getRole(idm,roleName);
if (role == null) throw new RuntimeException("role not found"); if (role == null) throw new RuntimeException("role not found");
addScope(agent, new RoleAdapter(role, idm)); addScope(agent, new RoleAdapter(role, idm));
@ -153,12 +159,12 @@ public class ResourceAdapter implements ResourceModel {
@Override @Override
public Set<String> getScope(UserModel agent) { public Set<String> getScope(UserModel agent) {
RelationshipQuery<ScopeRelationship> query = getIdm().createRelationshipQuery(ScopeRelationship.class); RelationshipQuery<ScopeRelationship> query = getRelationshipManager().createRelationshipQuery(ScopeRelationship.class);
query.setParameter(ScopeRelationship.CLIENT, ((UserAdapter)agent).getUser()); query.setParameter(ScopeRelationship.CLIENT, ((UserAdapter)agent).getUser());
List<ScopeRelationship> scope = query.getResultList(); List<ScopeRelationship> scope = query.getResultList();
HashSet<String> set = new HashSet<String>(); HashSet<String> set = new HashSet<String>();
for (ScopeRelationship rel : scope) { for (ScopeRelationship rel : scope) {
if (rel.getScope().getPartition().getId().equals(tier.getId())) set.add(rel.getScope().getName()); if (rel.getScope().getPartition().getId().equals(resource.getId())) set.add(rel.getScope().getName());
} }
return set; return set;
} }

View file

@ -3,7 +3,7 @@ package org.keycloak.services.models.picketlink;
import org.keycloak.services.models.RoleModel; import org.keycloak.services.models.RoleModel;
import org.picketlink.idm.IdentityManager; import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.model.Attribute; import org.picketlink.idm.model.Attribute;
import org.picketlink.idm.model.Role; import org.picketlink.idm.model.sample.Role;
import java.io.Serializable; import java.io.Serializable;

View file

@ -3,7 +3,7 @@ package org.keycloak.services.models.picketlink;
import org.keycloak.services.models.UserModel; import org.keycloak.services.models.UserModel;
import org.picketlink.idm.IdentityManager; import org.picketlink.idm.IdentityManager;
import org.picketlink.idm.model.Attribute; import org.picketlink.idm.model.Attribute;
import org.picketlink.idm.model.User; import org.picketlink.idm.model.sample.User;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View file

@ -0,0 +1,109 @@
package org.keycloak.services.models.picketlink.mappings;
import org.picketlink.idm.jpa.annotations.AttributeValue;
import org.picketlink.idm.model.AbstractPartition;
import org.picketlink.idm.model.annotation.AttributeProperty;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class RealmData extends AbstractPartition {
private String realmName;
private boolean enabled;
private boolean sslNotRequired;
private boolean cookieLoginAllowed;
private boolean registrationAllowed;
private int tokenLifespan;
private int accessCodeLifespan;
private String publicKeyPem;
private String privateKeyPem;
public RealmData() {
super(null);
}
public RealmData(String name) {
super(name);
}
@AttributeProperty
public String getRealmName() {
return realmName;
}
public void setRealmName(String realmName) {
this.realmName = realmName;
}
@AttributeProperty
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@AttributeProperty
public boolean isSslNotRequired() {
return sslNotRequired;
}
public void setSslNotRequired(boolean sslNotRequired) {
this.sslNotRequired = sslNotRequired;
}
@AttributeProperty
public boolean isCookieLoginAllowed() {
return cookieLoginAllowed;
}
public void setCookieLoginAllowed(boolean cookieLoginAllowed) {
this.cookieLoginAllowed = cookieLoginAllowed;
}
@AttributeProperty
public boolean isRegistrationAllowed() {
return registrationAllowed;
}
public void setRegistrationAllowed(boolean registrationAllowed) {
this.registrationAllowed = registrationAllowed;
}
@AttributeProperty
public int getTokenLifespan() {
return tokenLifespan;
}
public void setTokenLifespan(int tokenLifespan) {
this.tokenLifespan = tokenLifespan;
}
@AttributeProperty
public int getAccessCodeLifespan() {
return accessCodeLifespan;
}
public void setAccessCodeLifespan(int accessCodeLifespan) {
this.accessCodeLifespan = accessCodeLifespan;
}
@AttributeProperty
public String getPublicKeyPem() {
return publicKeyPem;
}
public void setPublicKeyPem(String publicKeyPem) {
this.publicKeyPem = publicKeyPem;
}
@AttributeProperty
public String getPrivateKeyPem() {
return privateKeyPem;
}
public void setPrivateKeyPem(String privateKeyPem) {
this.privateKeyPem = privateKeyPem;
}
}

View file

@ -0,0 +1,128 @@
package org.keycloak.services.models.picketlink.mappings;
import org.picketlink.idm.jpa.annotations.AttributeValue;
import org.picketlink.idm.jpa.annotations.OwnerReference;
import org.picketlink.idm.jpa.annotations.entity.IdentityManaged;
import org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import java.io.Serializable;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@IdentityManaged(RealmData.class)
@Entity
public class RealmEntity implements Serializable {
@OneToOne
@Id
@OwnerReference
private PartitionTypeEntity partitionTypeEntity;
@AttributeValue
private String realmName;
@AttributeValue
private boolean enabled;
@AttributeValue
private boolean sslNotRequired;
@AttributeValue
private boolean cookieLoginAllowed;
@AttributeValue
private boolean registrationAllowed;
@AttributeValue
private int tokenLifespan;
@AttributeValue
private int accessCodeLifespan;
@AttributeValue
@Column(length = 2048)
private String publicKeyPem;
@AttributeValue
@Column(length = 2048)
private String privateKeyPem;
public PartitionTypeEntity getPartitionTypeEntity() {
return partitionTypeEntity;
}
public void setPartitionTypeEntity(PartitionTypeEntity partitionTypeEntity) {
this.partitionTypeEntity = partitionTypeEntity;
}
public String getRealmName() {
return realmName;
}
public void setRealmName(String realmName) {
this.realmName = realmName;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isSslNotRequired() {
return sslNotRequired;
}
public void setSslNotRequired(boolean sslNotRequired) {
this.sslNotRequired = sslNotRequired;
}
public boolean isCookieLoginAllowed() {
return cookieLoginAllowed;
}
public void setCookieLoginAllowed(boolean cookieLoginAllowed) {
this.cookieLoginAllowed = cookieLoginAllowed;
}
public boolean isRegistrationAllowed() {
return registrationAllowed;
}
public void setRegistrationAllowed(boolean registrationAllowed) {
this.registrationAllowed = registrationAllowed;
}
public int getTokenLifespan() {
return tokenLifespan;
}
public void setTokenLifespan(int tokenLifespan) {
this.tokenLifespan = tokenLifespan;
}
public int getAccessCodeLifespan() {
return accessCodeLifespan;
}
public void setAccessCodeLifespan(int accessCodeLifespan) {
this.accessCodeLifespan = accessCodeLifespan;
}
public String getPublicKeyPem() {
return publicKeyPem;
}
public void setPublicKeyPem(String publicKeyPem) {
this.publicKeyPem = publicKeyPem;
}
public String getPrivateKeyPem() {
return privateKeyPem;
}
public void setPrivateKeyPem(String privateKeyPem) {
this.privateKeyPem = privateKeyPem;
}
}

View file

@ -0,0 +1,68 @@
package org.keycloak.services.models.picketlink.mappings;
import org.picketlink.idm.jpa.annotations.AttributeValue;
import org.picketlink.idm.model.AbstractPartition;
import org.picketlink.idm.model.annotation.AttributeProperty;
import org.picketlink.idm.model.sample.User;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class ResourceData extends AbstractPartition {
private String resourceName;
private boolean enabled;
private boolean surrogateAuthRequired;
private String managementUrl;
private User resourceUser;
public ResourceData() {
super(null);
}
public ResourceData(String name) {
super(name);
}
public String getResourceName() {
return resourceName;
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
public User getResourceUser() {
return resourceUser;
}
public void setResourceUser(User resourceUser) {
this.resourceUser = resourceUser;
}
@AttributeProperty
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@AttributeProperty
public boolean isSurrogateAuthRequired() {
return surrogateAuthRequired;
}
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
this.surrogateAuthRequired = surrogateAuthRequired;
}
@AttributeProperty
public String getManagementUrl() {
return managementUrl;
}
public void setManagementUrl(String managementUrl) {
this.managementUrl = managementUrl;
}
}

View file

@ -0,0 +1,87 @@
package org.keycloak.services.models.picketlink.mappings;
import org.picketlink.idm.jpa.annotations.AttributeValue;
import org.picketlink.idm.jpa.annotations.OwnerReference;
import org.picketlink.idm.jpa.annotations.entity.IdentityManaged;
import org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import java.io.Serializable;
/**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
@IdentityManaged(ResourceData.class)
@Entity
public class ResourceEntity implements Serializable {
@OneToOne
@Id
@OwnerReference
private PartitionTypeEntity partitionTypeEntity;
@AttributeValue
private String realmName;
@AttributeValue
private boolean enabled;
@AttributeValue
private boolean surrogateAuthRequired;
@AttributeValue
private String managementUrl;
@OneToOne
@AttributeValue
AccountTypeEntity resourceUser;
public PartitionTypeEntity getPartitionTypeEntity() {
return partitionTypeEntity;
}
public void setPartitionTypeEntity(PartitionTypeEntity partitionTypeEntity) {
this.partitionTypeEntity = partitionTypeEntity;
}
public String getRealmName() {
return realmName;
}
public void setRealmName(String realmName) {
this.realmName = realmName;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public boolean isSurrogateAuthRequired() {
return surrogateAuthRequired;
}
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
this.surrogateAuthRequired = surrogateAuthRequired;
}
public String getManagementUrl() {
return managementUrl;
}
public void setManagementUrl(String managementUrl) {
this.managementUrl = managementUrl;
}
public AccountTypeEntity getResourceUser() {
return resourceUser;
}
public void setResourceUser(AccountTypeEntity resourceUser) {
this.resourceUser = resourceUser;
}
}

View file

@ -1,10 +1,12 @@
package org.keycloak.services.models.picketlink.relationships; package org.keycloak.services.models.picketlink.relationships;
import org.keycloak.services.models.picketlink.mappings.RealmData;
import org.picketlink.idm.model.AbstractAttributedType; import org.picketlink.idm.model.AbstractAttributedType;
import org.picketlink.idm.model.Agent; import org.picketlink.idm.model.Attribute;
import org.picketlink.idm.model.Relationship; import org.picketlink.idm.model.Relationship;
import org.picketlink.idm.model.annotation.AttributeProperty; import org.picketlink.idm.model.annotation.AttributeProperty;
import org.picketlink.idm.model.annotation.IdentityProperty; import org.picketlink.idm.model.sample.User;
import org.picketlink.idm.query.AttributeParameter;
import org.picketlink.idm.query.RelationshipQueryParameter; import org.picketlink.idm.query.RelationshipQueryParameter;
/** /**
@ -14,13 +16,7 @@ import org.picketlink.idm.query.RelationshipQueryParameter;
public class RealmAdminRelationship extends AbstractAttributedType implements Relationship { public class RealmAdminRelationship extends AbstractAttributedType implements Relationship {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static final RelationshipQueryParameter REALM = new RelationshipQueryParameter() { public static final AttributeParameter REALM = new AttributeParameter("realm");
@Override
public String getName() {
return "realm";
}
};
public static final RelationshipQueryParameter ADMIN = new RelationshipQueryParameter() { public static final RelationshipQueryParameter ADMIN = new RelationshipQueryParameter() {
@ -30,24 +26,22 @@ public class RealmAdminRelationship extends AbstractAttributedType implements Re
} }
}; };
protected String realm; //protected String realm;
protected Agent admin; protected User admin;
@AttributeProperty
public String getRealm() { public String getRealm() {
return realm; return (String)getAttribute("realm").getValue();
} }
public void setRealm(String realm) { public void setRealm(String realm) {
this.realm = realm; setAttribute(new Attribute<String>("realm", realm));
} }
@IdentityProperty public User getAdmin() {
public Agent getAdmin() {
return admin; return admin;
} }
public void setAdmin(Agent admin) { public void setAdmin(User admin) {
this.admin = admin; this.admin = admin;
} }
} }

View file

@ -1,10 +1,11 @@
package org.keycloak.services.models.picketlink.relationships; package org.keycloak.services.models.picketlink.relationships;
import org.keycloak.services.models.picketlink.mappings.RealmData;
import org.picketlink.idm.model.AbstractAttributedType; import org.picketlink.idm.model.AbstractAttributedType;
import org.picketlink.idm.model.Agent; import org.picketlink.idm.model.Attribute;
import org.picketlink.idm.model.Relationship; import org.picketlink.idm.model.Relationship;
import org.picketlink.idm.model.annotation.AttributeProperty; import org.picketlink.idm.model.annotation.AttributeProperty;
import org.picketlink.idm.model.annotation.IdentityProperty; import org.picketlink.idm.query.AttributeParameter;
import org.picketlink.idm.query.RelationshipQueryParameter; import org.picketlink.idm.query.RelationshipQueryParameter;
/** /**
@ -14,56 +15,59 @@ import org.picketlink.idm.query.RelationshipQueryParameter;
public class RequiredCredentialRelationship extends AbstractAttributedType implements Relationship { public class RequiredCredentialRelationship extends AbstractAttributedType implements Relationship {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static final RelationshipQueryParameter REALM_AGENT = new RelationshipQueryParameter() { public static final AttributeParameter REALM = new AttributeParameter("realm");
@Override
public String getName() {
return "realmAgent";
}
};
protected Agent realmAgent; //protected String realm;
protected String credentialType; //protected String credentialType;
protected boolean input; //protected boolean input;
protected boolean secret; //protected boolean secret;
public RequiredCredentialRelationship() { public RequiredCredentialRelationship() {
} }
@IdentityProperty /*
public Agent getRealmAgent() { @AttributeProperty
return realmAgent; public String getRealm() {
return realm;
} }
public void setRealmAgent(Agent realmAgent) { public void setRealm(String realm) {
this.realmAgent = realmAgent; this.realm = realm;
}*/
public String getRealm() {
return (String)getAttribute("realm").getValue();
}
public void setRealm(String realm) {
setAttribute(new Attribute<String>("realm", realm));
} }
@AttributeProperty @AttributeProperty
public String getCredentialType() { public String getCredentialType() {
return credentialType; return (String)getAttribute("credentialType").getValue();
} }
public void setCredentialType(String credentialType) { public void setCredentialType(String credentialType) {
this.credentialType = credentialType; setAttribute(new Attribute<String>("credentialType", credentialType));
} }
@AttributeProperty @AttributeProperty
public boolean isInput() { public boolean isInput() {
return input; return (Boolean)getAttribute("input").getValue();
} }
public void setInput(boolean input) { public void setInput(boolean input) {
this.input = input; setAttribute(new Attribute<Boolean>("input", input));
} }
@AttributeProperty @AttributeProperty
public boolean isSecret() { public boolean isSecret() {
return secret; return (Boolean)getAttribute("secret").getValue();
} }
public void setSecret(boolean secret) { public void setSecret(boolean secret) {
this.secret = secret; setAttribute(new Attribute<Boolean>("secret", secret));
} }
} }

View file

@ -1,11 +1,14 @@
package org.keycloak.services.models.picketlink.relationships; package org.keycloak.services.models.picketlink.relationships;
import org.keycloak.services.models.picketlink.mappings.RealmData;
import org.keycloak.services.models.picketlink.mappings.ResourceData;
import org.picketlink.idm.model.AbstractAttributedType; import org.picketlink.idm.model.AbstractAttributedType;
import org.picketlink.idm.model.Agent; import org.picketlink.idm.model.Attribute;
import org.picketlink.idm.model.Relationship; import org.picketlink.idm.model.Relationship;
import org.picketlink.idm.model.User;
import org.picketlink.idm.model.annotation.AttributeProperty; import org.picketlink.idm.model.annotation.AttributeProperty;
import org.picketlink.idm.model.annotation.IdentityProperty; import org.picketlink.idm.model.sample.Agent;
import org.picketlink.idm.model.sample.User;
import org.picketlink.idm.query.AttributeParameter;
import org.picketlink.idm.query.RelationshipQueryParameter; import org.picketlink.idm.query.RelationshipQueryParameter;
/** /**
@ -15,84 +18,26 @@ import org.picketlink.idm.query.RelationshipQueryParameter;
public class ResourceRelationship extends AbstractAttributedType implements Relationship { public class ResourceRelationship extends AbstractAttributedType implements Relationship {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
public static final RelationshipQueryParameter REALM_AGENT = new RelationshipQueryParameter() { public static final AttributeParameter REALM = new AttributeParameter("realm");
@Override protected String realm;
public String getName() { protected String resource;
return "realmAgent";
}
};
protected Agent realmAgent; public String getRealm() {
protected User resourceUser; return (String)getAttribute("realm").getValue();
protected String resourceId;
protected String resourceName;
protected String managementUrl = ""; // Picketlink doesn't like null attribute values
protected boolean surrogateAuthRequired;
protected boolean enabled;
@IdentityProperty
public Agent getRealmAgent() {
return realmAgent;
} }
public void setRealmAgent(Agent realmAgent) { public void setRealm(String realm) {
this.realmAgent = realmAgent; setAttribute(new Attribute<String>("realm", realm));
} }
@IdentityProperty
public User getResourceUser() { public String getResource() {
return resourceUser; return (String)getAttribute("resource").getValue();
} }
public void setResourceUser(User resourceUser) { public void setResource(String realm) {
this.resourceUser = resourceUser; setAttribute(new Attribute<String>("resource", realm));
} }
@AttributeProperty
public String getResourceId() {
return resourceId;
}
public void setResourceId(String resourceId) {
this.resourceId = resourceId;
}
@AttributeProperty
public String getResourceName() {
return resourceName;
}
public void setResourceName(String resourceName) {
this.resourceName = resourceName;
}
@AttributeProperty
public boolean getSurrogateAuthRequired() {
return surrogateAuthRequired;
}
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
this.surrogateAuthRequired = surrogateAuthRequired;
}
@AttributeProperty
public boolean getEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@AttributeProperty
public String getManagementUrl()
{
return managementUrl;
}
public void setManagementUrl(String managementUrl) {
if (managementUrl == null) managementUrl = ""; // Picketlink doesn't like NULL attribute values.
this.managementUrl = managementUrl;
}
} }

View file

@ -1,10 +1,9 @@
package org.keycloak.services.models.picketlink.relationships; package org.keycloak.services.models.picketlink.relationships;
import org.picketlink.idm.model.AbstractAttributedType; import org.picketlink.idm.model.AbstractAttributedType;
import org.picketlink.idm.model.Agent;
import org.picketlink.idm.model.Relationship; import org.picketlink.idm.model.Relationship;
import org.picketlink.idm.model.Role; import org.picketlink.idm.model.sample.Role;
import org.picketlink.idm.model.annotation.IdentityProperty; import org.picketlink.idm.model.sample.User;
import org.picketlink.idm.query.RelationshipQueryParameter; import org.picketlink.idm.query.RelationshipQueryParameter;
/** /**
@ -22,19 +21,17 @@ public class ScopeRelationship extends AbstractAttributedType implements Relatio
} }
}; };
protected Agent client; protected User client;
protected Role scope; protected Role scope;
@IdentityProperty public User getClient() {
public Agent getClient() {
return client; return client;
} }
public void setClient(Agent client) { public void setClient(User client) {
this.client = client; this.client = client;
} }
@IdentityProperty
public Role getScope() { public Role getScope() {
return scope; return scope;
} }

View file

@ -1,29 +1,36 @@
package org.keycloak.services.resources; package org.keycloak.services.resources;
import org.keycloak.SkeletonKeyContextResolver; import org.keycloak.SkeletonKeyContextResolver;
import org.keycloak.services.filters.KeycloakSessionFilter; import org.keycloak.services.filters.KeycloakSessionRequestFilter;
import org.keycloak.services.filters.KeycloakSessionResponseFilter;
import org.keycloak.services.managers.TokenManager; import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.models.KeycloakSessionFactory; import org.keycloak.services.models.KeycloakSessionFactory;
import org.keycloak.services.models.picketlink.PicketlinkKeycloakSession;
import org.keycloak.services.models.picketlink.PicketlinkKeycloakSessionFactory; import org.keycloak.services.models.picketlink.PicketlinkKeycloakSessionFactory;
import org.keycloak.services.models.picketlink.relationships.RealmAdminRelationship; import org.keycloak.services.models.picketlink.mappings.RealmEntity;
import org.keycloak.services.models.picketlink.relationships.RequiredCredentialRelationship; import org.keycloak.services.models.picketlink.mappings.ResourceEntity;
import org.keycloak.services.models.picketlink.relationships.ResourceRelationship; import org.picketlink.idm.PartitionManager;
import org.keycloak.services.models.picketlink.relationships.ScopeRelationship;
import org.picketlink.idm.IdentitySessionFactory;
import org.picketlink.idm.config.IdentityConfiguration;
import org.picketlink.idm.config.IdentityConfigurationBuilder; import org.picketlink.idm.config.IdentityConfigurationBuilder;
import org.picketlink.idm.internal.DefaultIdentitySessionFactory; import org.picketlink.idm.internal.DefaultPartitionManager;
import org.picketlink.idm.jpa.internal.ResourceLocalJpaIdentitySessionHandler; import org.picketlink.idm.jpa.internal.JPAContextInitializer;
import org.picketlink.idm.jpa.schema.CredentialObject; import org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity;
import org.picketlink.idm.jpa.schema.CredentialObjectAttribute; import org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity;
import org.picketlink.idm.jpa.schema.IdentityObject; import org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity;
import org.picketlink.idm.jpa.schema.IdentityObjectAttribute; import org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity;
import org.picketlink.idm.jpa.schema.PartitionObject; import org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity;
import org.picketlink.idm.jpa.schema.RelationshipIdentityObject; import org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity;
import org.picketlink.idm.jpa.schema.RelationshipObject; import org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity;
import org.picketlink.idm.jpa.schema.RelationshipObjectAttribute; import org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity;
import org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity;
import javax.annotation.PreDestroy; import javax.annotation.PreDestroy;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.ws.rs.core.Application; import javax.ws.rs.core.Application;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -39,14 +46,25 @@ public class KeycloakApplication extends Application {
protected KeycloakSessionFactory factory; protected KeycloakSessionFactory factory;
public KeycloakApplication() { public KeycloakApplication() {
this.factory = new PicketlinkKeycloakSessionFactory(createFactory()); KeycloakSessionFactory f = createSessionFactory();
KeycloakSessionFilter filter = new KeycloakSessionFilter(factory); this.factory = f;
KeycloakSessionRequestFilter filter = new KeycloakSessionRequestFilter(factory);
singletons.add(new RealmsResource(new TokenManager())); singletons.add(new RealmsResource(new TokenManager()));
singletons.add(filter); singletons.add(filter);
classes.add(KeycloakSessionResponseFilter.class);
classes.add(SkeletonKeyContextResolver.class); classes.add(SkeletonKeyContextResolver.class);
classes.add(RegistrationService.class); classes.add(RegistrationService.class);
} }
protected KeycloakSessionFactory createSessionFactory() {
return buildSessionFactory();
}
public static KeycloakSessionFactory buildSessionFactory() {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("keycloak-identity-store");
return new PicketlinkKeycloakSessionFactory(emf, buildPartitionManager());
}
public KeycloakSessionFactory getFactory() { public KeycloakSessionFactory getFactory() {
return factory; return factory;
} }
@ -56,27 +74,45 @@ public class KeycloakApplication extends Application {
factory.close(); factory.close();
} }
public IdentitySessionFactory createFactory() { public PartitionManager createPartitionManager() {
ResourceLocalJpaIdentitySessionHandler handler = new ResourceLocalJpaIdentitySessionHandler("keycloak-identity-store"); return buildPartitionManager();
}
public static PartitionManager buildPartitionManager() {
IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder(); IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder();
builder builder
.named("KEYCLOAK_JPA_CONFIG")
.stores() .stores()
.jpa() .jpa()
.identityClass(IdentityObject.class) .mappedEntity(
.attributeClass(IdentityObjectAttribute.class) AttributedTypeEntity.class,
.relationshipClass(RelationshipObject.class) AccountTypeEntity.class,
.relationshipIdentityClass(RelationshipIdentityObject.class) RoleTypeEntity.class,
.relationshipAttributeClass(RelationshipObjectAttribute.class) GroupTypeEntity.class,
.credentialClass(CredentialObject.class) IdentityTypeEntity.class,
.credentialAttributeClass(CredentialObjectAttribute.class) RelationshipTypeEntity.class,
.partitionClass(PartitionObject.class) RelationshipIdentityTypeEntity.class,
.supportAllFeatures() PartitionTypeEntity.class,
.supportRelationshipType(RealmAdminRelationship.class, ResourceRelationship.class, RequiredCredentialRelationship.class, ScopeRelationship.class) PasswordCredentialTypeEntity.class,
.setIdentitySessionHandler(handler); DigestCredentialTypeEntity.class,
X509CredentialTypeEntity.class,
OTPCredentialTypeEntity.class,
AttributeTypeEntity.class,
RealmEntity.class,
ResourceEntity.class
)
.supportGlobalRelationship(org.picketlink.idm.model.Relationship.class)
.addContextInitializer(new JPAContextInitializer(null) {
@Override
public EntityManager getEntityManager() {
return PicketlinkKeycloakSession.currentEntityManager.get();
}
})
.supportAllFeatures();
IdentityConfiguration build = builder.build(); DefaultPartitionManager partitionManager = new DefaultPartitionManager(builder.buildAll());
return new DefaultIdentitySessionFactory(build); return partitionManager;
} }

View file

@ -24,9 +24,6 @@ public class RealmSubResource {
@Context @Context
protected UriInfo uriInfo; protected UriInfo uriInfo;
@Context
protected KeycloakSession identitySession;
protected RealmModel realm; protected RealmModel realm;
public RealmSubResource(RealmModel realm) { public RealmSubResource(RealmModel realm) {
@ -42,29 +39,37 @@ public class RealmSubResource {
@GET @GET
@Produces("application/json") @Produces("application/json")
public PublishedRealmRepresentation getRealm(@PathParam("realm") String id) { public PublishedRealmRepresentation getRealm(@PathParam("realm") String id) {
return realmRep(realm, uriInfo); return new Transaction() {
protected PublishedRealmRepresentation callImpl() {
return realmRep(realm, uriInfo);
}
}.call();
} }
@GET @GET
@Path("html") @Path("html")
@Produces("text/html") @Produces("text/html")
public String getRealmHtml(@PathParam("realm") String id) { public String getRealmHtml(@PathParam("realm") String id) {
StringBuffer html = new StringBuffer(); return new Transaction() {
protected String callImpl() {
StringBuffer html = new StringBuffer();
String authUri = TokenService.loginPageUrl(uriInfo).build(realm.getId()).toString(); String authUri = TokenService.loginPageUrl(uriInfo).build(realm.getId()).toString();
String codeUri = TokenService.accessCodeToTokenUrl(uriInfo).build(realm.getId()).toString(); String codeUri = TokenService.accessCodeToTokenUrl(uriInfo).build(realm.getId()).toString();
String grantUrl = TokenService.grantAccessTokenUrl(uriInfo).build(realm.getId()).toString(); String grantUrl = TokenService.grantAccessTokenUrl(uriInfo).build(realm.getId()).toString();
String idGrantUrl = TokenService.grantIdentityTokenUrl(uriInfo).build(realm.getId()).toString(); String idGrantUrl = TokenService.grantIdentityTokenUrl(uriInfo).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>");
html.append("<p>code: ").append(codeUri).append("</p>"); html.append("<p>code: ").append(codeUri).append("</p>");
html.append("<p>grant: ").append(grantUrl).append("</p>"); html.append("<p>grant: ").append(grantUrl).append("</p>");
html.append("<p>identity grant: ").append(idGrantUrl).append("</p>"); html.append("<p>identity grant: ").append(idGrantUrl).append("</p>");
html.append("<p>public key: ").append(realm.getPublicKeyPem()).append("</p>"); html.append("<p>public key: ").append(realm.getPublicKeyPem()).append("</p>");
html.append("</body></html>"); html.append("</body></html>");
return html.toString(); return html.toString();
}
}.call();
} }

View file

@ -6,6 +6,7 @@ import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.managers.TokenManager; import org.keycloak.services.managers.TokenManager;
import org.keycloak.services.models.KeycloakSession; import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.KeycloakSessionFactory;
import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RoleModel; import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserModel; import org.keycloak.services.models.UserModel;
@ -38,9 +39,6 @@ public class RealmsResource {
@Context @Context
protected HttpHeaders headers; protected HttpHeaders headers;
@Context
protected KeycloakSession identitySession;
@Context @Context
ResourceContext resourceContext; ResourceContext resourceContext;
@ -55,58 +53,64 @@ public class RealmsResource {
} }
@Path("{realm}/tokens") @Path("{realm}/tokens")
public TokenService getTokenService(@PathParam("realm") String id) { public TokenService getTokenService(final @PathParam("realm") String id) {
RealmManager realmManager = new RealmManager(identitySession); return new Transaction(false) {
RealmModel realm = realmManager.getRealm(id); @Override
if (realm == null) { protected TokenService callImpl() {
logger.debug("realm not found"); RealmManager realmManager = new RealmManager(session);
throw new NotFoundException(); RealmModel realm = realmManager.getRealm(id);
} if (realm == null) {
TokenService tokenService = new TokenService(realm, tokenManager); logger.debug("realm not found");
resourceContext.initResource(tokenService); throw new NotFoundException();
return tokenService; }
TokenService tokenService = new TokenService(realm, tokenManager);
resourceContext.initResource(tokenService);
return tokenService;
}
}.call();
} }
@Path("{realm}") @Path("{realm}")
public RealmSubResource getRealmResource(@PathParam("realm") String id) { public RealmSubResource getRealmResource(final @PathParam("realm") String id) {
RealmManager realmManager = new RealmManager(identitySession); return new Transaction(false) {
RealmModel realm = realmManager.getRealm(id); @Override
if (realm == null) { protected RealmSubResource callImpl() {
logger.debug("realm not found"); RealmManager realmManager = new RealmManager(session);
throw new NotFoundException(); RealmModel realm = realmManager.getRealm(id);
} if (realm == null) {
RealmSubResource realmResource = new RealmSubResource(realm); logger.debug("realm not found");
resourceContext.initResource(realmResource); throw new NotFoundException();
return realmResource; }
RealmSubResource realmResource = new RealmSubResource(realm);
resourceContext.initResource(realmResource);
return realmResource;
}
}.call();
} }
@POST @POST
@Consumes("application/json") @Consumes("application/json")
public Response importRealm(RealmRepresentation rep) { public Response importRealm(final RealmRepresentation rep) {
identitySession.getTransaction().begin(); return new Transaction() {
RealmModel realm; @Override
try { protected Response callImpl() {
RealmManager realmManager = new RealmManager(identitySession); RealmManager realmManager = new RealmManager(session);
RealmModel defaultRealm = realmManager.getRealm(RealmModel.DEFAULT_REALM); RealmModel defaultRealm = realmManager.getRealm(RealmModel.DEFAULT_REALM);
UserModel realmCreator = new AuthenticationManager().authenticateBearerToken(defaultRealm, headers); UserModel realmCreator = new AuthenticationManager().authenticateBearerToken(defaultRealm, headers);
RoleModel creatorRole = defaultRealm.getRole(RegistrationService.REALM_CREATOR_ROLE); RoleModel creatorRole = defaultRealm.getRole(RegistrationService.REALM_CREATOR_ROLE);
if (!defaultRealm.hasRole(realmCreator, creatorRole)) { if (!defaultRealm.hasRole(realmCreator, creatorRole)) {
logger.warn("not a realm creator"); logger.warn("not a realm creator");
throw new NotAuthorizedException("Bearer"); throw new NotAuthorizedException("Bearer");
}
RealmModel realm = realmManager.importRealm(rep, realmCreator);
UriBuilder builder = uriInfo.getRequestUriBuilder().path(realm.getId());
return Response.created(builder.build())
.entity(RealmSubResource.realmRep(realm, uriInfo))
.type(MediaType.APPLICATION_JSON_TYPE).build();
} }
realm = realmManager.importRealm(rep, realmCreator); }.call();
identitySession.getTransaction().commit();
} catch (RuntimeException re) {
identitySession.getTransaction().rollback();
throw re;
}
UriBuilder builder = uriInfo.getRequestUriBuilder().path(realm.getId());
return Response.created(builder.build())
.entity(RealmSubResource.realmRep(realm, uriInfo))
.type(MediaType.APPLICATION_JSON_TYPE).build();
} }
} }

View file

@ -4,7 +4,7 @@ import org.jboss.resteasy.logging.Logger;
import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.CredentialRepresentation;
import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.KeycloakSession; import org.keycloak.services.models.KeycloakSessionFactory;
import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.RealmModel;
import org.keycloak.services.models.RoleModel; import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserModel; import org.keycloak.services.models.UserModel;
@ -32,44 +32,38 @@ public class RegistrationService {
@Context @Context
protected UriInfo uriInfo; protected UriInfo uriInfo;
@Context
protected KeycloakSession identitySession;
@POST @POST
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
public Response register(UserRepresentation newUser) { public Response register(final UserRepresentation newUser) {
identitySession.getTransaction().begin(); return new Transaction() {
try { @Override
RealmManager realmManager = new RealmManager(identitySession); protected Response callImpl() {
RealmModel defaultRealm = realmManager.defaultRealm(); RealmManager realmManager = new RealmManager(session);
if (!defaultRealm.isEnabled()) { RealmModel defaultRealm = realmManager.defaultRealm();
throw new ForbiddenException(); if (!defaultRealm.isEnabled()) {
} throw new ForbiddenException();
if (!defaultRealm.isRegistrationAllowed()) { }
throw new ForbiddenException(); if (!defaultRealm.isRegistrationAllowed()) {
} throw new ForbiddenException();
UserModel user = defaultRealm.getUser(newUser.getUsername()); }
if (user != null) { UserModel user = defaultRealm.getUser(newUser.getUsername());
return Response.status(400).type("text/plain").entity("user exists").build(); if (user != null) {
} return Response.status(400).type("text/plain").entity("user exists").build();
}
user = defaultRealm.addUser(newUser.getUsername()); user = defaultRealm.addUser(newUser.getUsername());
for (CredentialRepresentation cred : newUser.getCredentials()) { for (CredentialRepresentation cred : newUser.getCredentials()) {
UserCredentialModel credModel = new UserCredentialModel(); UserCredentialModel credModel = new UserCredentialModel();
credModel.setType(cred.getType()); credModel.setType(cred.getType());
credModel.setValue(cred.getValue()); credModel.setValue(cred.getValue());
defaultRealm.updateCredential(user, credModel); defaultRealm.updateCredential(user, credModel);
}
RoleModel realmCreator = defaultRealm.getRole(REALM_CREATOR_ROLE);
defaultRealm.grantRole(user, realmCreator);
URI uri = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(user.getLoginName()).build();
return Response.created(uri).build();
} }
RoleModel realmCreator = defaultRealm.getRole(REALM_CREATOR_ROLE); }.call();
defaultRealm.grantRole(user, realmCreator);
identitySession.getTransaction().commit();
URI uri = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(user.getLoginName()).build();
return Response.created(uri).build();
} catch (RuntimeException e) {
logger.error("Failed to register", e);
identitySession.getTransaction().rollback();
throw e;
}
} }

View file

@ -58,19 +58,17 @@ public class TokenService {
@Context @Context
protected HttpHeaders headers; protected HttpHeaders headers;
@Context @Context
protected KeycloakSession identitySession;
@Context
HttpRequest request; HttpRequest request;
@Context @Context
HttpResponse response; HttpResponse response;
protected String securityFailurePath = "/securityFailure.jsp"; protected String securityFailurePath = "/securityFailure.jsp";
protected String loginFormPath = "/loginForm.jsp"; protected String loginFormPath = "/loginForm.jsp";
protected String oauthFormPath = "/oauthGrantForm.jsp"; protected String oauthFormPath = "/oauthGrantForm.jsp";
protected RealmModel realm; protected RealmModel realm;
protected TokenManager tokenManager; protected TokenManager tokenManager;
protected AuthenticationManager authManager = new AuthenticationManager(); protected AuthenticationManager authManager = new AuthenticationManager();
private ResourceAdminManager resourceAdminManager = new ResourceAdminManager(); private ResourceAdminManager resourceAdminManager = new ResourceAdminManager();
@ -117,103 +115,116 @@ public class TokenService {
@POST @POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response grantIdentityToken(MultivaluedMap<String, String> form) { public Response grantIdentityToken(final MultivaluedMap<String, String> form) {
String username = form.getFirst(AuthenticationManager.FORM_USERNAME); return new Transaction() {
if (username == null) { protected Response callImpl() {
throw new NotAuthorizedException("No user"); String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
} if (username == null) {
if (!realm.isEnabled()) { throw new NotAuthorizedException("No user");
throw new NotAuthorizedException("Disabled realm"); }
} if (!realm.isEnabled()) {
UserModel user = realm.getUser(username); throw new NotAuthorizedException("Disabled realm");
if (user == null) { }
throw new NotAuthorizedException("No user"); UserModel user = realm.getUser(username);
} if (user == null) {
if (!user.isEnabled()) { throw new NotAuthorizedException("No user");
throw new NotAuthorizedException("Disabled user."); }
} if (!user.isEnabled()) {
if (!authManager.authenticateForm(realm, user, form)) { throw new NotAuthorizedException("Disabled user.");
throw new NotAuthorizedException("FORM"); }
} if (!authManager.authenticateForm(realm, user, form)) {
tokenManager = new TokenManager(); throw new NotAuthorizedException("FORM");
SkeletonKeyToken token = tokenManager.createIdentityToken(realm, username); }
String encoded = tokenManager.encodeToken(realm, token); tokenManager = new TokenManager();
AccessTokenResponse res = accessTokenResponse(token, encoded); SkeletonKeyToken token = tokenManager.createIdentityToken(realm, username);
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build(); String encoded = tokenManager.encodeToken(realm, token);
AccessTokenResponse res = accessTokenResponse(token, encoded);
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
}
}.call();
} }
@Path("grants/access") @Path("grants/access")
@POST @POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public Response grantAccessToken(MultivaluedMap<String, String> form) { public Response grantAccessToken(final MultivaluedMap<String, String> form) {
String username = form.getFirst(AuthenticationManager.FORM_USERNAME); return new Transaction() {
if (username == null) { protected Response callImpl() {
throw new NotAuthorizedException("No user"); String username = form.getFirst(AuthenticationManager.FORM_USERNAME);
} if (username == null) {
if (!realm.isEnabled()) { throw new NotAuthorizedException("No user");
throw new NotAuthorizedException("Disabled realm"); }
} if (!realm.isEnabled()) {
UserModel user = realm.getUser(username); throw new NotAuthorizedException("Disabled realm");
if (user == null) { }
throw new NotAuthorizedException("No user"); UserModel user = realm.getUser(username);
} if (user == null) {
if (!user.isEnabled()) { throw new NotAuthorizedException("No user");
throw new NotAuthorizedException("Disabled user."); }
} if (!user.isEnabled()) {
if (authManager.authenticateForm(realm, user, form)) { throw new NotAuthorizedException("Disabled user.");
throw new NotAuthorizedException("Auth failed"); }
} if (authManager.authenticateForm(realm, user, form)) {
SkeletonKeyToken token = tokenManager.createAccessToken(realm, user); throw new NotAuthorizedException("Auth failed");
String encoded = tokenManager.encodeToken(realm, token); }
AccessTokenResponse res = accessTokenResponse(token, encoded); SkeletonKeyToken token = tokenManager.createAccessToken(realm, user);
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build(); String encoded = tokenManager.encodeToken(realm, token);
AccessTokenResponse res = accessTokenResponse(token, encoded);
return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build();
}
}.call();
} }
@Path("auth/request/login") @Path("auth/request/login")
@POST @POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processLogin(MultivaluedMap<String, String> formData) { public Response processLogin(final MultivaluedMap<String, String> formData) {
String clientId = formData.getFirst("client_id"); return new Transaction() {
String scopeParam = formData.getFirst("scope"); protected Response callImpl() {
String state = formData.getFirst("state"); String clientId = formData.getFirst("client_id");
String redirect = formData.getFirst("redirect_uri"); String scopeParam = formData.getFirst("scope");
String state = formData.getFirst("state");
String redirect = formData.getFirst("redirect_uri");
if (!realm.isEnabled()) { if (!realm.isEnabled()) {
securityFailureForward("Realm not enabled."); securityFailureForward("Realm not enabled.");
return null; return null;
} }
UserModel client = realm.getUser(clientId); UserModel client = realm.getUser(clientId);
if (client == null) { if (client == null) {
securityFailureForward("Unknown login requester."); securityFailureForward("Unknown login requester.");
return null; return null;
} }
if (!client.isEnabled()) { if (!client.isEnabled()) {
securityFailureForward("Login requester not enabled."); securityFailureForward("Login requester not enabled.");
return null; return null;
} }
String username = formData.getFirst("username"); String username = formData.getFirst("username");
UserModel user = realm.getUser(username); UserModel user = realm.getUser(username);
if (user == null) { if (user == null) {
logger.error("Incorrect user name."); logger.error("Incorrect user name.");
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Incorrect user name."); request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Incorrect user name.");
forwardToLoginForm(redirect, clientId, scopeParam, state); forwardToLoginForm(redirect, clientId, scopeParam, state);
return null; return null;
} }
if (!user.isEnabled()) { if (!user.isEnabled()) {
securityFailureForward("Your account is not enabled."); securityFailureForward("Your account is not enabled.");
return null; return null;
} }
boolean authenticated = authManager.authenticateForm(realm, user, formData); boolean authenticated = authManager.authenticateForm(realm, user, formData);
if (!authenticated) { if (!authenticated) {
logger.error("Authentication failed"); logger.error("Authentication failed");
request.setAttribute("username", username); request.setAttribute("username", username);
request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Invalid credentials."); request.setAttribute("KEYCLOAK_LOGIN_ERROR_MESSAGE", "Invalid credentials.");
forwardToLoginForm(redirect, clientId, scopeParam, state); forwardToLoginForm(redirect, clientId, scopeParam, state);
return null; return null;
} }
return processAccessCode(scopeParam, state, redirect, client, user); return processAccessCode(scopeParam, state, redirect, client, user);
}
}.call();
} }
protected Response processAccessCode(String scopeParam, String state, String redirect, UserModel client, UserModel user) { protected Response processAccessCode(String scopeParam, String state, String redirect, UserModel client, UserModel user) {
@ -222,7 +233,6 @@ public class TokenService {
boolean isResource = realm.hasRole(client, resourceRole); boolean isResource = realm.hasRole(client, resourceRole);
if (!isResource && !realm.hasRole(client, identityRequestRole)) { if (!isResource && !realm.hasRole(client, identityRequestRole)) {
securityFailureForward("Login requester not allowed to request login."); securityFailureForward("Login requester not allowed to request login.");
identitySession.close();
return null; return null;
} }
AccessCodeEntry accessCode = tokenManager.createAccessCode(scopeParam, state, redirect, realm, client, user); AccessCodeEntry accessCode = tokenManager.createAccessCode(scopeParam, state, redirect, realm, client, user);
@ -230,7 +240,6 @@ public class TokenService {
logger.info("processAccessCode: go to oauth page?: " + (!isResource && (accessCode.getRealmRolesRequested().size() > 0 || accessCode.getResourceRolesRequested().size() > 0))); logger.info("processAccessCode: go to oauth page?: " + (!isResource && (accessCode.getRealmRolesRequested().size() > 0 || accessCode.getResourceRolesRequested().size() > 0)));
if (!isResource && (accessCode.getRealmRolesRequested().size() > 0 || accessCode.getResourceRolesRequested().size() > 0)) { if (!isResource && (accessCode.getRealmRolesRequested().size() > 0 || accessCode.getResourceRolesRequested().size() > 0)) {
oauthGrantPage(accessCode, client); oauthGrantPage(accessCode, client);
identitySession.close();
return null; return null;
} }
return redirectAccessCode(accessCode, state, redirect); return redirectAccessCode(accessCode, state, redirect);
@ -251,96 +260,100 @@ public class TokenService {
@Path("access/codes") @Path("access/codes")
@POST @POST
@Produces("application/json") @Produces("application/json")
public Response accessCodeToToken(MultivaluedMap<String, String> formData) { public Response accessCodeToToken(final MultivaluedMap<String, String> formData) {
logger.info("accessRequest <---"); return new Transaction() {
if (!realm.isEnabled()) { protected Response callImpl() {
throw new NotAuthorizedException("Realm not enabled"); logger.info("accessRequest <---");
} if (!realm.isEnabled()) {
throw new NotAuthorizedException("Realm not enabled");
}
String code = formData.getFirst("code"); String code = formData.getFirst("code");
if (code == null) { if (code == null) {
logger.debug("code not specified"); logger.debug("code not specified");
Map<String, String> error = new HashMap<String, String>(); Map<String, String> error = new HashMap<String, String>();
error.put("error", "invalid_request"); error.put("error", "invalid_request");
error.put("error_description", "code not specified"); error.put("error_description", "code not specified");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
} }
String client_id = formData.getFirst("client_id"); String client_id = formData.getFirst("client_id");
if (client_id == null) { if (client_id == null) {
logger.debug("client_id not specified"); logger.debug("client_id not specified");
Map<String, String> error = new HashMap<String, String>(); Map<String, String> error = new HashMap<String, String>();
error.put("error", "invalid_request"); error.put("error", "invalid_request");
error.put("error_description", "client_id not specified"); error.put("error_description", "client_id not specified");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
} }
UserModel client = realm.getUser(client_id); UserModel client = realm.getUser(client_id);
if (client == null) { if (client == null) {
logger.debug("Could not find user"); logger.debug("Could not find user");
Map<String, String> error = new HashMap<String, String>(); Map<String, String> error = new HashMap<String, String>();
error.put("error", "invalid_client"); error.put("error", "invalid_client");
error.put("error_description", "Could not find user"); error.put("error_description", "Could not find user");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
} }
if (!client.isEnabled()) { if (!client.isEnabled()) {
logger.debug("user is not enabled"); logger.debug("user is not enabled");
Map<String, String> error = new HashMap<String, String>(); Map<String, String> error = new HashMap<String, String>();
error.put("error", "invalid_client"); error.put("error", "invalid_client");
error.put("error_description", "User is not enabled"); error.put("error_description", "User is not enabled");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
} }
boolean authenticated = authManager.authenticateForm(realm, client, formData); boolean authenticated = authManager.authenticateForm(realm, client, formData);
if (!authenticated) { if (!authenticated) {
Map<String, String> error = new HashMap<String, String>(); Map<String, String> error = new HashMap<String, String>();
error.put("error", "unauthorized_client"); error.put("error", "unauthorized_client");
return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build();
} }
JWSInput input = new JWSInput(code, providers); JWSInput input = new JWSInput(code, providers);
boolean verifiedCode = false; boolean verifiedCode = false;
try { try {
verifiedCode = RSAProvider.verify(input, realm.getPublicKey()); verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
} catch (Exception ignored) { } catch (Exception ignored) {
logger.debug("Failed to verify signature", ignored); logger.debug("Failed to verify signature", ignored);
} }
if (!verifiedCode) { if (!verifiedCode) {
Map<String, String> res = new HashMap<String, String>(); Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant"); res.put("error", "invalid_grant");
res.put("error_description", "Unable to verify code signature"); res.put("error_description", "Unable to verify code signature");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build(); return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
} }
String key = input.readContent(String.class); String key = input.readContent(String.class);
AccessCodeEntry accessCode = tokenManager.pullAccessCode(key); AccessCodeEntry accessCode = tokenManager.pullAccessCode(key);
if (accessCode == null) { if (accessCode == null) {
Map<String, String> res = new HashMap<String, String>(); Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant"); res.put("error", "invalid_grant");
res.put("error_description", "Code not found"); res.put("error_description", "Code not found");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build(); return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
} }
if (accessCode.isExpired()) { if (accessCode.isExpired()) {
Map<String, String> res = new HashMap<String, String>(); Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant"); res.put("error", "invalid_grant");
res.put("error_description", "Code is expired"); res.put("error_description", "Code is expired");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build(); return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
} }
if (!accessCode.getToken().isActive()) { if (!accessCode.getToken().isActive()) {
Map<String, String> res = new HashMap<String, String>(); Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant"); res.put("error", "invalid_grant");
res.put("error_description", "Token expired"); res.put("error_description", "Token expired");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build(); return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
} }
if (!client.getLoginName().equals(accessCode.getClient().getLoginName())) { if (!client.getLoginName().equals(accessCode.getClient().getLoginName())) {
Map<String, String> res = new HashMap<String, String>(); Map<String, String> res = new HashMap<String, String>();
res.put("error", "invalid_grant"); res.put("error", "invalid_grant");
res.put("error_description", "Auth error"); res.put("error_description", "Auth error");
return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build(); return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res).build();
} }
logger.info("accessRequest SUCCESS"); logger.info("accessRequest SUCCESS");
AccessTokenResponse res = accessTokenResponse(realm.getPrivateKey(), accessCode.getToken()); AccessTokenResponse res = accessTokenResponse(realm.getPrivateKey(), accessCode.getToken());
return Response.ok(res).build(); return Response.ok(res).build();
}
}.call();
} }
@ -373,7 +386,6 @@ public class TokenService {
logger.error(message); logger.error(message);
request.setAttribute(JspRequestParameters.KEYCLOAK_SECURITY_FAILURE_MESSAGE, message); request.setAttribute(JspRequestParameters.KEYCLOAK_SECURITY_FAILURE_MESSAGE, message);
request.forward(securityFailurePath); request.forward(securityFailurePath);
identitySession.close();
} }
protected void forwardToLoginForm(String redirect, protected void forwardToLoginForm(String redirect,
@ -389,99 +401,113 @@ public class TokenService {
request.setAttribute("scope", scopeParam); request.setAttribute("scope", scopeParam);
request.setAttribute("state", state); request.setAttribute("state", state);
request.forward(loginFormPath); request.forward(loginFormPath);
identitySession.close();
} }
@Path("login") @Path("login")
@GET @GET
public Response loginPage(@QueryParam("response_type") String responseType, public Response loginPage(final @QueryParam("response_type") String responseType,
@QueryParam("redirect_uri") String redirect, final @QueryParam("redirect_uri") String redirect,
@QueryParam("client_id") String clientId, final @QueryParam("client_id") String clientId,
@QueryParam("scope") String scopeParam, final @QueryParam("scope") String scopeParam,
@QueryParam("state") String state) { final @QueryParam("state") String state) {
if (!realm.isEnabled()) { return new Transaction() {
securityFailureForward("Realm not enabled"); protected Response callImpl() {
return null; if (!realm.isEnabled()) {
} securityFailureForward("Realm not enabled");
UserModel client = realm.getUser(clientId); return null;
if (client == null) { }
securityFailureForward("Unknown login requester."); UserModel client = realm.getUser(clientId);
return null; if (client == null) {
} securityFailureForward("Unknown login requester.");
transaction.rollback();
return null;
}
if (!client.isEnabled()) { if (!client.isEnabled()) {
securityFailureForward("Login requester not enabled."); securityFailureForward("Login requester not enabled.");
identitySession.close(); transaction.rollback();
return null; session.close();
} return null;
}
RoleModel resourceRole = realm.getRole(RealmManager.RESOURCE_ROLE); RoleModel resourceRole = realm.getRole(RealmManager.RESOURCE_ROLE);
RoleModel identityRequestRole = realm.getRole(RealmManager.IDENTITY_REQUESTER_ROLE); RoleModel identityRequestRole = realm.getRole(RealmManager.IDENTITY_REQUESTER_ROLE);
boolean isResource = realm.hasRole(client, resourceRole); boolean isResource = realm.hasRole(client, resourceRole);
if (!isResource && !realm.hasRole(client, identityRequestRole)) { if (!isResource && !realm.hasRole(client, identityRequestRole)) {
securityFailureForward("Login requester not allowed to request login."); securityFailureForward("Login requester not allowed to request login.");
identitySession.close(); transaction.rollback();
return null; session.close();
} return null;
}
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) { if (user != null) {
logger.info(user.getLoginName() + " already logged in."); logger.info(user.getLoginName() + " already logged in.");
return processAccessCode(scopeParam, state, redirect, client, user); return processAccessCode(scopeParam, state, redirect, client, user);
} }
forwardToLoginForm(redirect, clientId, scopeParam, state); forwardToLoginForm(redirect, clientId, scopeParam, state);
return null; return null;
}
}.call();
} }
@Path("logout") @Path("logout")
@GET @GET
public Response logout(@QueryParam("redirect_uri") String redirectUri) { public Response logout(final @QueryParam("redirect_uri") String redirectUri) {
// todo do we care if anybody can trigger this? return new Transaction() {
protected Response callImpl() {
// todo do we care if anybody can trigger this?
UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers);
if (user != null) { if (user != null) {
logger.info("Logging out: " + user.getLoginName()); logger.info("Logging out: " + user.getLoginName());
authManager.expireIdentityCookie(realm, uriInfo); authManager.expireIdentityCookie(realm, uriInfo);
resourceAdminManager.singleLogOut(realm, user.getLoginName()); resourceAdminManager.singleLogOut(realm, user.getLoginName());
} }
// todo manage legal redirects // todo manage legal redirects
return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build(); return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build();
}
}.call();
} }
@Path("oauth/grant") @Path("oauth/grant")
@POST @POST
@Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response processOAuth(MultivaluedMap<String, String> formData) { public Response processOAuth(final MultivaluedMap<String, String> formData) {
String code = formData.getFirst("code"); return new Transaction() {
JWSInput input = new JWSInput(code, providers); protected Response callImpl() {
boolean verifiedCode = false; String code = formData.getFirst("code");
try { JWSInput input = new JWSInput(code, providers);
verifiedCode = RSAProvider.verify(input, realm.getPublicKey()); boolean verifiedCode = false;
} catch (Exception ignored) { try {
logger.debug("Failed to verify signature", ignored); verifiedCode = RSAProvider.verify(input, realm.getPublicKey());
} } catch (Exception ignored) {
if (!verifiedCode) { logger.debug("Failed to verify signature", ignored);
securityFailureForward("Illegal access code."); }
identitySession.close(); if (!verifiedCode) {
return null; securityFailureForward("Illegal access code.");
} session.close();
String key = input.readContent(String.class); return null;
AccessCodeEntry accessCodeEntry = tokenManager.getAccessCode(key); }
if (accessCodeEntry == null) { String key = input.readContent(String.class);
securityFailureForward("Unknown access code."); AccessCodeEntry accessCodeEntry = tokenManager.getAccessCode(key);
identitySession.close(); if (accessCodeEntry == null) {
return null; securityFailureForward("Unknown access code.");
} session.close();
return null;
}
String redirect = accessCodeEntry.getRedirectUri(); String redirect = accessCodeEntry.getRedirectUri();
String state = accessCodeEntry.getState(); String state = accessCodeEntry.getState();
if (formData.containsKey("cancel")) { if (formData.containsKey("cancel")) {
return redirectAccessDenied(redirect, state); return redirectAccessDenied(redirect, state);
} }
return redirectAccessCode(accessCodeEntry, state, redirect); return redirectAccessCode(accessCodeEntry, state, redirect);
}
}.call();
} }
protected Response redirectAccessDenied(String redirect, String state) { protected Response redirectAccessDenied(String redirect, String state) {

View file

@ -0,0 +1,96 @@
package org.keycloak.services.resources;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.KeycloakSessionFactory;
import org.keycloak.services.models.KeycloakTransaction;
/**
* Meant to be used as an inner class wrapper (I forget the pattern name, its been awhile).
*
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
* @version $Revision: 1 $
*/
public class Transaction {
protected KeycloakSession session;
protected KeycloakTransaction transaction;
protected boolean closeSession;
/**
* Pull KeycloakSession from @Context
*
* Will close session after finished
*
*/
public Transaction() {
this(true);
}
/**
* Pull KeycloakSession from @Context
*
* @param close whether to close the session or not after completion
*/
public Transaction(boolean close) {
this.session = ResteasyProviderFactory.getContextData(KeycloakSession.class);
transaction = session.getTransaction();
closeSession = close;
}
/**
* Creates and manages its own session.
*
* @param factory
*/
public Transaction(KeycloakSessionFactory factory) {
this.closeSession = true;
this.session = factory.createSession();
this.transaction = session.getTransaction();
}
protected void runImpl() {
}
/**
* Will not begin or end a transaction or close a session if the transaction was already active when called
*
*/
public void run() {
boolean wasActive = transaction.isActive();
if (!wasActive) transaction.begin();
try {
runImpl();
if (!wasActive && transaction.isActive()) transaction.commit();
} catch (RuntimeException e) {
if (!wasActive && transaction.isActive()) transaction.rollback();
throw e;
} finally {
if (!wasActive && closeSession) session.close();
}
}
protected <T> T callImpl() {
return null;
}
/**
* Will not begin or end a transaction or close a session if the transaction was already active when called
*
*/
public <T> T call() {
boolean wasActive = transaction.isActive();
if (!wasActive) transaction.begin();
try {
T rtn = callImpl();
if (!wasActive && transaction.isActive()) transaction.commit();
return rtn;
} catch (RuntimeException e) {
if (!wasActive && transaction.isActive()) transaction.rollback();
throw e;
} finally {
if (!wasActive && closeSession) session.close();
}
}
}

View file

@ -15,24 +15,8 @@ import org.keycloak.services.models.RequiredCredentialModel;
import org.keycloak.services.models.RoleModel; import org.keycloak.services.models.RoleModel;
import org.keycloak.services.models.UserModel; import org.keycloak.services.models.UserModel;
import org.keycloak.services.models.UserCredentialModel; import org.keycloak.services.models.UserCredentialModel;
import org.keycloak.services.models.picketlink.PicketlinkKeycloakSessionFactory; import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.models.picketlink.relationships.RealmAdminRelationship;
import org.keycloak.services.models.picketlink.relationships.RequiredCredentialRelationship;
import org.keycloak.services.models.picketlink.relationships.ResourceRelationship;
import org.keycloak.services.models.picketlink.relationships.ScopeRelationship;
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 java.util.List; import java.util.List;
@ -49,37 +33,15 @@ public class AdapterTest {
@Before @Before
public void before() throws Exception { public void before() throws Exception {
factory = new PicketlinkKeycloakSessionFactory(createFactory()); factory = KeycloakApplication.buildSessionFactory();
identitySession = factory.createSession(); identitySession = factory.createSession();
identitySession.getTransaction().begin();
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.getTransaction().commit();
identitySession.close(); identitySession.close();
factory.close(); factory.close();
} }
@ -132,6 +94,8 @@ public class AdapterTest {
for (RequiredCredentialModel cred : storedCreds) { for (RequiredCredentialModel cred : storedCreds) {
if (cred.getType().equals(RequiredCredentialRepresentation.PASSWORD)) password = true; if (cred.getType().equals(RequiredCredentialRepresentation.PASSWORD)) password = true;
else if (cred.getType().equals(RequiredCredentialRepresentation.TOTP)) totp = true; else if (cred.getType().equals(RequiredCredentialRepresentation.TOTP)) totp = true;
Assert.assertTrue(cred.isInput());
Assert.assertTrue(cred.isSecret());
} }
Assert.assertTrue(totp); Assert.assertTrue(totp);
Assert.assertTrue(password); Assert.assertTrue(password);

View file

@ -13,26 +13,8 @@ import org.keycloak.services.models.KeycloakSessionFactory;
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.UserModel; import org.keycloak.services.models.UserModel;
import org.keycloak.services.models.picketlink.PicketlinkKeycloakSessionFactory; import org.keycloak.services.resources.KeycloakApplication;
import org.keycloak.services.models.picketlink.relationships.RealmAdminRelationship;
import org.keycloak.services.models.picketlink.relationships.RequiredCredentialRelationship;
import org.keycloak.services.models.picketlink.relationships.ResourceRelationship;
import org.keycloak.services.models.picketlink.relationships.ScopeRelationship;
import org.keycloak.services.resources.RegistrationService; import org.keycloak.services.resources.RegistrationService;
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 java.util.Set; import java.util.Set;
@ -49,45 +31,23 @@ public class ImportTest {
@Before @Before
public void before() throws Exception { public void before() throws Exception {
factory = new PicketlinkKeycloakSessionFactory(createFactory()); factory = KeycloakApplication.buildSessionFactory();
identitySession = factory.createSession(); identitySession = factory.createSession();
identitySession.getTransaction().begin();
manager = new RealmManager(identitySession); 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 @After
public void after() throws Exception { public void after() throws Exception {
identitySession.getTransaction().commit();
identitySession.close(); identitySession.close();
factory.close(); factory.close();
} }
@Test @Test
public void install() throws Exception { public void install() throws Exception {
RealmModel defaultRealm = manager.createRealm(Realm.DEFAULT_REALM, Realm.DEFAULT_REALM); RealmModel defaultRealm = manager.createRealm(RealmModel.DEFAULT_REALM, RealmModel.DEFAULT_REALM);
defaultRealm.setName(Realm.DEFAULT_REALM); defaultRealm.setName(RealmModel.DEFAULT_REALM);
defaultRealm.setEnabled(true); defaultRealm.setEnabled(true);
defaultRealm.setTokenLifespan(300); defaultRealm.setTokenLifespan(300);
defaultRealm.setAccessCodeLifespan(60); defaultRealm.setAccessCodeLifespan(60);

View file

@ -4,7 +4,6 @@ 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.resources.RegistrationService; import org.keycloak.services.resources.RegistrationService;
import org.picketlink.idm.model.Realm;
/** /**
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a> * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
@ -12,8 +11,8 @@ import org.picketlink.idm.model.Realm;
*/ */
public class InstallationManager { public class InstallationManager {
public void install(RealmManager manager) { public void install(RealmManager manager) {
RealmModel defaultRealm = manager.createRealm(Realm.DEFAULT_REALM, Realm.DEFAULT_REALM); RealmModel defaultRealm = manager.createRealm(RealmModel.DEFAULT_REALM, RealmModel.DEFAULT_REALM);
defaultRealm.setName(Realm.DEFAULT_REALM); defaultRealm.setName(RealmModel.DEFAULT_REALM);
defaultRealm.setEnabled(true); defaultRealm.setEnabled(true);
defaultRealm.setTokenLifespan(300); defaultRealm.setTokenLifespan(300);
defaultRealm.setAccessCodeLifespan(60); defaultRealm.setAccessCodeLifespan(60);

View file

@ -14,9 +14,8 @@ import org.keycloak.representations.idm.UserRepresentation;
import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.AuthenticationManager;
import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.RealmManager;
import org.keycloak.services.models.KeycloakSession; import org.keycloak.services.models.KeycloakSession;
import org.keycloak.services.models.RealmModel;
import org.keycloak.services.resources.KeycloakApplication; import org.keycloak.services.resources.KeycloakApplication;
import org.picketlink.idm.IdentitySession;
import org.picketlink.idm.model.Realm;
import javax.ws.rs.NotAuthorizedException; import javax.ws.rs.NotAuthorizedException;
import javax.ws.rs.client.Client; import javax.ws.rs.client.Client;
@ -43,9 +42,12 @@ public class RealmCreationTest {
deployment.setApplicationClass(KeycloakApplication.class.getName()); deployment.setApplicationClass(KeycloakApplication.class.getName());
EmbeddedContainer.start(deployment); EmbeddedContainer.start(deployment);
KeycloakApplication application = (KeycloakApplication) deployment.getApplication(); KeycloakApplication application = (KeycloakApplication) deployment.getApplication();
KeycloakSession IdentitySession = application.getFactory().createSession(); KeycloakSession session = application.getFactory().createSession();
RealmManager manager = new RealmManager(IdentitySession); session.getTransaction().begin();
RealmManager manager = new RealmManager(session);
new InstallationManager().install(manager); new InstallationManager().install(manager);
session.getTransaction().commit();
session.close();
client = new ResteasyClientBuilder().build(); client = new ResteasyClientBuilder().build();
client.register(SkeletonKeyContextResolver.class); client.register(SkeletonKeyContextResolver.class);
} }
@ -72,14 +74,14 @@ public class RealmCreationTest {
Form form = new Form(); Form form = new Form();
form.param(AuthenticationManager.FORM_USERNAME, "bburke"); form.param(AuthenticationManager.FORM_USERNAME, "bburke");
form.param(RequiredCredentialRepresentation.PASSWORD, "badpassword"); form.param(RequiredCredentialRepresentation.PASSWORD, "badpassword");
tokenResponse = target.path("realms").path(Realm.DEFAULT_REALM).path("tokens/grants/identity-token").request().post(Entity.form(form), AccessTokenResponse.class); tokenResponse = target.path("realms").path(RealmModel.DEFAULT_REALM).path("tokens/grants/identity-token").request().post(Entity.form(form), AccessTokenResponse.class);
Assert.fail(); Assert.fail();
} catch (NotAuthorizedException e) { } catch (NotAuthorizedException e) {
} }
Form form = new Form(); Form form = new Form();
form.param(AuthenticationManager.FORM_USERNAME, "bburke"); form.param(AuthenticationManager.FORM_USERNAME, "bburke");
form.param(RequiredCredentialRepresentation.PASSWORD, "geheim"); form.param(RequiredCredentialRepresentation.PASSWORD, "geheim");
tokenResponse = target.path("realms").path(Realm.DEFAULT_REALM).path("tokens/grants/identity-token").request().post(Entity.form(form), AccessTokenResponse.class); tokenResponse = target.path("realms").path(RealmModel.DEFAULT_REALM).path("tokens/grants/identity-token").request().post(Entity.form(form), AccessTokenResponse.class);
Assert.assertNotNull(tokenResponse); Assert.assertNotNull(tokenResponse);
System.out.println(tokenResponse.getToken()); System.out.println(tokenResponse.getToken());
// //

View file

@ -5,15 +5,23 @@
<persistence-unit name="keycloak-identity-store" transaction-type="RESOURCE_LOCAL"> <persistence-unit name="keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
<provider>org.hibernate.ejb.HibernatePersistence</provider> <provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>org.picketlink.idm.jpa.schema.IdentityObject</class> <class>org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.PartitionObject</class> <class>org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.RelationshipObject</class> <class>org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.RelationshipIdentityObject</class> <class>org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.RelationshipIdentityWeakObject</class> <class>org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.RelationshipObjectAttribute</class> <class>org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.IdentityObjectAttribute</class> <class>org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.CredentialObject</class> <class>org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity</class>
<class>org.picketlink.idm.jpa.schema.CredentialObjectAttribute</class> <class>org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity</class>
<class>org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity</class>
<class>org.keycloak.services.models.picketlink.mappings.RealmEntity</class>
<class>org.keycloak.services.models.picketlink.mappings.ResourceEntity</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties> <properties>
<property name="hibernate.connection.url" value="jdbc:h2:mem:test"/> <property name="hibernate.connection.url" value="jdbc:h2:mem:test"/>
@ -21,9 +29,10 @@
<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="false" /> <property name="hibernate.show_sql" value="false" />
<property name="hibernate.format_sql" value="false" /> <property name="hibernate.format_sql" value="true" />
</properties> </properties>
</persistence-unit> </persistence-unit>
</persistence> </persistence>