jpa backend
This commit is contained in:
parent
d6ee6aef9f
commit
d04ca2c34f
182 changed files with 6199 additions and 1740 deletions
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
|
<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
|
||||||
xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
|
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
|
||||||
</web-fragment>
|
</web-fragment>
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
|
<web-fragment version="3.0" xmlns="http://java.sun.com/xml/ns/javaee"
|
||||||
xmlns:xml="http://www.w3.org/XML/1998/namespace" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
|
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-fragment_3_0.xsd ">
|
||||||
</web-fragment>
|
</web-fragment>
|
||||||
|
|
|
@ -37,7 +37,8 @@ public class JaxrsOAuthClient extends AbstractOAuthClient {
|
||||||
.queryParam("state", state)
|
.queryParam("state", state)
|
||||||
.build();
|
.build();
|
||||||
NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure, true);
|
NewCookie cookie = new NewCookie(getStateCookieName(), state, getStateCookiePath(uriInfo), null, null, -1, isSecure, true);
|
||||||
logger.info("NewCookie: " + cookie.toString());
|
logger.debug("NewCookie: " + cookie.toString());
|
||||||
|
logger.debug("Oauth Redirect to: " + url);
|
||||||
return Response.status(302)
|
return Response.status(302)
|
||||||
.location(url)
|
.location(url)
|
||||||
.cookie(cookie).build();
|
.cookie(cookie).build();
|
||||||
|
|
|
@ -4,7 +4,10 @@ import org.codehaus.jackson.annotate.JsonIgnore;
|
||||||
import org.codehaus.jackson.annotate.JsonProperty;
|
import org.codehaus.jackson.annotate.JsonProperty;
|
||||||
import org.jboss.resteasy.jwt.JsonWebToken;
|
import org.jboss.resteasy.jwt.JsonWebToken;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package org.keycloak.representations.idm.admin;
|
package org.keycloak.representations.idm.admin;
|
||||||
|
|
||||||
import org.codehaus.jackson.annotate.JsonIgnore;
|
import org.codehaus.jackson.annotate.JsonIgnore;
|
||||||
import org.codehaus.jackson.annotate.JsonProperty;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Posted to managed client from admin server.
|
* Posted to managed client from admin server.
|
||||||
|
|
|
@ -6,13 +6,10 @@ import org.bouncycastle.openssl.PEMWriter;
|
||||||
import org.bouncycastle.x509.X509V1CertificateGenerator;
|
import org.bouncycastle.x509.X509V1CertificateGenerator;
|
||||||
import org.jboss.resteasy.jose.jws.JWSBuilder;
|
import org.jboss.resteasy.jose.jws.JWSBuilder;
|
||||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||||
import org.keycloak.RSATokenVerifier;
|
|
||||||
import org.keycloak.ResourceMetadata;
|
|
||||||
import org.keycloak.VerificationException;
|
|
||||||
import org.keycloak.representations.SkeletonKeyToken;
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.keycloak.representations.SkeletonKeyToken;
|
||||||
|
|
||||||
import javax.security.auth.x500.X500Principal;
|
import javax.security.auth.x500.X500Principal;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
|
@ -5,9 +5,9 @@ import org.jboss.resteasy.jose.jws.JWSBuilder;
|
||||||
import org.jboss.resteasy.jose.jws.JWSInput;
|
import org.jboss.resteasy.jose.jws.JWSInput;
|
||||||
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
|
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
|
||||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||||
|
import org.junit.Test;
|
||||||
import org.keycloak.representations.SkeletonKeyScope;
|
import org.keycloak.representations.SkeletonKeyScope;
|
||||||
import org.keycloak.representations.SkeletonKeyToken;
|
import org.keycloak.representations.SkeletonKeyToken;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.security.KeyPair;
|
import java.security.KeyPair;
|
||||||
import java.security.KeyPairGenerator;
|
import java.security.KeyPairGenerator;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<%@ page import="javax.ws.rs.core.*" language="java" contentType="text/html; charset=ISO-8859-1"
|
<%@ page import="javax.ws.rs.core.UriBuilder" language="java" contentType="text/html; charset=ISO-8859-1"
|
||||||
pageEncoding="ISO-8859-1"%>
|
pageEncoding="ISO-8859-1"%>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<%@ page import="javax.ws.rs.core.*" language="java" contentType="text/html; charset=ISO-8859-1"
|
<%@ page import="javax.ws.rs.core.UriBuilder" language="java" contentType="text/html; charset=ISO-8859-1"
|
||||||
pageEncoding="ISO-8859-1"%>
|
pageEncoding="ISO-8859-1"%>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
|
|
@ -35,11 +35,6 @@
|
||||||
<artifactId>keycloak-model-api</artifactId>
|
<artifactId>keycloak-model-api</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-model-picketlink</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-social-core</artifactId>
|
<artifactId>keycloak-social-core</artifactId>
|
||||||
|
@ -75,22 +70,6 @@
|
||||||
<artifactId>keycloak-admin-ui-styles</artifactId>
|
<artifactId>keycloak-admin-ui-styles</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-api</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-impl</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-simple-schema</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-config</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
<artifactId>resteasy-jaxrs</artifactId>
|
<artifactId>resteasy-jaxrs</artifactId>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package org.keycloak.example.demo;
|
package org.keycloak.example.demo;
|
||||||
|
|
||||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
import org.keycloak.services.managers.ApplianceBootstrap;
|
import org.keycloak.services.managers.ApplianceBootstrap;
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.services.resources.KeycloakApplication;
|
import org.keycloak.services.resources.KeycloakApplication;
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
|
|
@ -2,24 +2,22 @@
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
|
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
|
||||||
version="1.0">
|
version="1.0">
|
||||||
<persistence-unit name="keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
|
<persistence-unit name="jpa-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
|
||||||
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
|
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
|
||||||
|
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.ApplicationScopeMappingEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.ApplicationUserRoleMappingEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.CredentialEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.RealmEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.RealmScopeMappingEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.RealmUserRoleMappingEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.RoleEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.SocialLinkEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.UserEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
|
||||||
<class>org.keycloak.models.picketlink.mappings.RealmEntity</class>
|
|
||||||
<class>org.keycloak.models.picketlink.mappings.ApplicationEntity</class>
|
|
||||||
|
|
||||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<%@ page import="org.keycloak.models.*,org.keycloak.services.resources.*,javax.ws.rs.core.*,java.util.*" language="java" contentType="text/html; charset=ISO-8859-1"
|
<%@ page import="org.keycloak.models.RealmModel,org.keycloak.models.RoleModel,org.keycloak.models.UserModel,javax.ws.rs.core.MultivaluedMap" language="java" contentType="text/html; charset=ISO-8859-1"
|
||||||
pageEncoding="ISO-8859-1"%>
|
pageEncoding="ISO-8859-1"%>
|
||||||
|
<%@ page import="java.util.List" %>
|
||||||
<%
|
<%
|
||||||
RealmModel realm = (RealmModel)request.getAttribute(RealmModel.class.getName());
|
RealmModel realm = (RealmModel)request.getAttribute(RealmModel.class.getName());
|
||||||
String username = (String)request.getAttribute("username");
|
String username = (String)request.getAttribute("username");
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<%@ page import="javax.ws.rs.core.*" language="java" contentType="text/html; charset=ISO-8859-1"
|
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
|
||||||
pageEncoding="ISO-8859-1"%>
|
pageEncoding="ISO-8859-1"%>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
|
|
|
@ -35,11 +35,6 @@
|
||||||
<artifactId>keycloak-model-api</artifactId>
|
<artifactId>keycloak-model-api</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.keycloak</groupId>
|
|
||||||
<artifactId>keycloak-model-picketlink</artifactId>
|
|
||||||
<version>${project.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-social-core</artifactId>
|
<artifactId>keycloak-social-core</artifactId>
|
||||||
|
@ -65,22 +60,6 @@
|
||||||
<artifactId>keycloak-forms</artifactId>
|
<artifactId>keycloak-forms</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-api</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-impl</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-idm-simple-schema</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-config</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
<artifactId>resteasy-jaxrs</artifactId>
|
<artifactId>resteasy-jaxrs</artifactId>
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package org.keycloak.example.demo;
|
package org.keycloak.example.demo;
|
||||||
|
|
||||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
import org.jboss.resteasy.jwt.JsonSerialization;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.representations.idm.RealmRepresentation;
|
import org.keycloak.representations.idm.RealmRepresentation;
|
||||||
import org.keycloak.services.managers.ApplianceBootstrap;
|
import org.keycloak.services.managers.ApplianceBootstrap;
|
||||||
import org.keycloak.services.managers.RealmManager;
|
import org.keycloak.services.managers.RealmManager;
|
||||||
import org.keycloak.models.KeycloakSession;
|
|
||||||
import org.keycloak.models.RealmModel;
|
|
||||||
import org.keycloak.services.resources.KeycloakApplication;
|
import org.keycloak.services.resources.KeycloakApplication;
|
||||||
|
|
||||||
import javax.servlet.ServletContext;
|
import javax.servlet.ServletContext;
|
||||||
|
|
|
@ -2,24 +2,22 @@
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
|
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
|
||||||
version="1.0">
|
version="1.0">
|
||||||
<persistence-unit name="keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
|
<persistence-unit name="jpa-keycloak-identity-store" transaction-type="RESOURCE_LOCAL">
|
||||||
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
|
<jta-data-source>java:jboss/datasources/ExampleDS</jta-data-source>
|
||||||
|
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.ApplicationEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.ApplicationScopeMappingEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.RoleTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.ApplicationUserRoleMappingEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.CredentialEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.OAuthClientEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.RelationshipTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.RealmEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.RelationshipIdentityTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.RealmScopeMappingEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.RealmUserRoleMappingEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.PasswordCredentialTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.RequiredCredentialEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.RoleEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.X509CredentialTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.SocialLinkEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.UserEntity</class>
|
||||||
<class>org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity</class>
|
<class>org.keycloak.models.jpa.entities.UserRoleMappingEntity</class>
|
||||||
<class>org.keycloak.models.picketlink.mappings.RealmEntity</class>
|
|
||||||
<class>org.keycloak.models.picketlink.mappings.ApplicationEntity</class>
|
|
||||||
|
|
||||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||||
|
|
||||||
|
@ -30,4 +28,5 @@
|
||||||
</properties>
|
</properties>
|
||||||
</persistence-unit>
|
</persistence-unit>
|
||||||
|
|
||||||
|
|
||||||
</persistence>
|
</persistence>
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<%@ page import="org.keycloak.models.*,org.keycloak.services.resources.*,javax.ws.rs.core.*,java.util.*" language="java" contentType="text/html; charset=ISO-8859-1"
|
<%@ page import="org.keycloak.models.RealmModel,org.keycloak.models.RoleModel,org.keycloak.models.UserModel,javax.ws.rs.core.MultivaluedMap" language="java" contentType="text/html; charset=ISO-8859-1"
|
||||||
pageEncoding="ISO-8859-1"%>
|
pageEncoding="ISO-8859-1"%>
|
||||||
|
<%@ page import="java.util.List" %>
|
||||||
<%
|
<%
|
||||||
RealmModel realm = (RealmModel)request.getAttribute(RealmModel.class.getName());
|
RealmModel realm = (RealmModel)request.getAttribute(RealmModel.class.getName());
|
||||||
String username = (String)request.getAttribute("username");
|
String username = (String)request.getAttribute("username");
|
||||||
|
|
|
@ -33,11 +33,6 @@
|
||||||
<artifactId>keycloak-social-core</artifactId>
|
<artifactId>keycloak-social-core</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
|
||||||
<groupId>org.picketlink</groupId>
|
|
||||||
<artifactId>picketlink-common</artifactId>
|
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.jboss.resteasy</groupId>
|
<groupId>org.jboss.resteasy</groupId>
|
||||||
<artifactId>resteasy-jaxrs</artifactId>
|
<artifactId>resteasy-jaxrs</artifactId>
|
||||||
|
|
|
@ -21,12 +21,11 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.forms;
|
package org.keycloak.forms;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import org.keycloak.forms.model.RequiredCredential;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
import org.keycloak.forms.model.RequiredCredential;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
|
9
forms/src/main/java/org/keycloak/forms/OAuthGrantBean.java
Normal file → Executable file
9
forms/src/main/java/org/keycloak/forms/OAuthGrantBean.java
Normal file → Executable file
|
@ -21,14 +21,13 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.forms;
|
package org.keycloak.forms;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
|
||||||
|
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
|
* @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -21,11 +21,10 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.forms;
|
package org.keycloak.forms;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
|
|
11
forms/src/main/java/org/keycloak/forms/SocialBean.java
Normal file → Executable file
11
forms/src/main/java/org/keycloak/forms/SocialBean.java
Normal file → Executable file
|
@ -21,15 +21,14 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.forms;
|
package org.keycloak.forms;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import javax.imageio.spi.ServiceRegistry;
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
|
||||||
|
|
||||||
import org.keycloak.forms.model.SocialProvider;
|
import org.keycloak.forms.model.SocialProvider;
|
||||||
import org.keycloak.services.resources.flows.Urls;
|
import org.keycloak.services.resources.flows.Urls;
|
||||||
|
|
||||||
|
import javax.ws.rs.core.UriBuilder;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
|
|
3
forms/src/main/java/org/keycloak/forms/TotpBean.java
Normal file → Executable file
3
forms/src/main/java/org/keycloak/forms/TotpBean.java
Normal file → Executable file
|
@ -21,11 +21,12 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.forms;
|
package org.keycloak.forms;
|
||||||
|
|
||||||
|
import org.keycloak.models.utils.Base32;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
import org.picketlink.common.util.Base32;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
|
|
@ -21,10 +21,10 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.forms;
|
package org.keycloak.forms;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
|
|
||||||
import org.keycloak.services.resources.flows.Urls;
|
import org.keycloak.services.resources.flows.Urls;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
*/
|
*/
|
||||||
|
|
16
forms/src/main/java/org/keycloak/service/FormServiceImpl.java
Normal file → Executable file
16
forms/src/main/java/org/keycloak/service/FormServiceImpl.java
Normal file → Executable file
|
@ -21,19 +21,12 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.service;
|
package org.keycloak.service;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.ResourceBundle;
|
|
||||||
|
|
||||||
import freemarker.template.Configuration;
|
import freemarker.template.Configuration;
|
||||||
import freemarker.template.Template;
|
import freemarker.template.Template;
|
||||||
import freemarker.template.TemplateException;
|
import freemarker.template.TemplateException;
|
||||||
import org.jboss.resteasy.logging.Logger;
|
import org.jboss.resteasy.logging.Logger;
|
||||||
import org.keycloak.forms.MessageBean;
|
|
||||||
import org.keycloak.forms.LoginBean;
|
import org.keycloak.forms.LoginBean;
|
||||||
|
import org.keycloak.forms.MessageBean;
|
||||||
import org.keycloak.forms.OAuthGrantBean;
|
import org.keycloak.forms.OAuthGrantBean;
|
||||||
import org.keycloak.forms.RealmBean;
|
import org.keycloak.forms.RealmBean;
|
||||||
import org.keycloak.forms.RegisterBean;
|
import org.keycloak.forms.RegisterBean;
|
||||||
|
@ -45,6 +38,13 @@ import org.keycloak.forms.UserBean;
|
||||||
import org.keycloak.services.FormService;
|
import org.keycloak.services.FormService;
|
||||||
import org.keycloak.services.resources.flows.Pages;
|
import org.keycloak.services.resources.flows.Pages;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
|
* @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -7,7 +7,6 @@ import org.apache.catalina.connector.Request;
|
||||||
import org.apache.catalina.connector.Response;
|
import org.apache.catalina.connector.Response;
|
||||||
import org.apache.catalina.valves.ValveBase;
|
import org.apache.catalina.valves.ValveBase;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
|
||||||
import org.keycloak.SkeletonKeySession;
|
import org.keycloak.SkeletonKeySession;
|
||||||
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
|
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
|
||||||
import org.keycloak.representations.SkeletonKeyToken;
|
import org.keycloak.representations.SkeletonKeyToken;
|
||||||
|
|
|
@ -1,879 +0,0 @@
|
||||||
package org.keycloak.adapters.as7;
|
|
||||||
|
|
||||||
import org.apache.catalina.Lifecycle;
|
|
||||||
import org.apache.catalina.LifecycleEvent;
|
|
||||||
import org.apache.catalina.LifecycleException;
|
|
||||||
import org.apache.catalina.LifecycleListener;
|
|
||||||
import org.apache.catalina.authenticator.Constants;
|
|
||||||
import org.apache.catalina.authenticator.FormAuthenticator;
|
|
||||||
import org.apache.catalina.connector.Request;
|
|
||||||
import org.apache.catalina.connector.Response;
|
|
||||||
import org.apache.catalina.core.StandardContext;
|
|
||||||
import org.apache.catalina.deploy.LoginConfig;
|
|
||||||
import org.apache.catalina.realm.GenericPrincipal;
|
|
||||||
import org.bouncycastle.openssl.PEMWriter;
|
|
||||||
import org.codehaus.jackson.map.ObjectMapper;
|
|
||||||
import org.codehaus.jackson.map.ObjectWriter;
|
|
||||||
import org.codehaus.jackson.map.SerializationConfig;
|
|
||||||
import org.codehaus.jackson.map.annotate.JsonSerialize;
|
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.jboss.resteasy.client.jaxrs.ResteasyClient;
|
|
||||||
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
|
|
||||||
import org.jboss.resteasy.jose.jws.JWSBuilder;
|
|
||||||
import org.jboss.resteasy.jose.jws.JWSInput;
|
|
||||||
import org.jboss.resteasy.jose.jws.crypto.RSAProvider;
|
|
||||||
import org.jboss.resteasy.jwt.JsonSerialization;
|
|
||||||
import org.jboss.resteasy.plugins.providers.RegisterBuiltin;
|
|
||||||
import org.jboss.resteasy.plugins.server.servlet.ServletUtil;
|
|
||||||
import org.jboss.resteasy.spi.ResteasyProviderFactory;
|
|
||||||
import org.jboss.resteasy.spi.ResteasyUriInfo;
|
|
||||||
import org.jboss.resteasy.util.BasicAuthHelper;
|
|
||||||
import org.keycloak.EnvUtil;
|
|
||||||
import org.keycloak.PemUtils;
|
|
||||||
import org.keycloak.ResourceMetadata;
|
|
||||||
import org.keycloak.SkeletonKeySession;
|
|
||||||
import org.keycloak.adapters.as7.config.AuthServerConfig;
|
|
||||||
import org.keycloak.adapters.as7.config.ManagedResourceConfig;
|
|
||||||
import org.keycloak.representations.AccessTokenResponse;
|
|
||||||
import org.keycloak.representations.SkeletonKeyToken;
|
|
||||||
|
|
||||||
import javax.security.auth.login.LoginException;
|
|
||||||
import javax.servlet.RequestDispatcher;
|
|
||||||
import javax.servlet.ServletException;
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
|
||||||
import javax.ws.rs.client.WebTarget;
|
|
||||||
import javax.ws.rs.core.HttpHeaders;
|
|
||||||
import javax.ws.rs.core.UriBuilder;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
import java.security.KeyStore;
|
|
||||||
import java.security.Principal;
|
|
||||||
import java.security.PrivateKey;
|
|
||||||
import java.security.PublicKey;
|
|
||||||
import java.security.cert.Certificate;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Turns a web deployment into an authentication server that follwos the OAuth 2 protocol and Skeleton Key bearer tokens.
|
|
||||||
* Authentication store is backed by a JBoss security domain.
|
|
||||||
* <p/>
|
|
||||||
* Servlet FORM authentication that uses the local security domain to authenticate and for role mappings.
|
|
||||||
* <p/>
|
|
||||||
* Supports bearer token creation and authentication. The client asking for access must be set up as a valid user
|
|
||||||
* within the security domain.
|
|
||||||
* <p/>
|
|
||||||
* If no an OAuth access request, this works like normal FORM authentication and authorization.
|
|
||||||
*
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
public class OAuthAuthenticationServerValve extends FormAuthenticator implements LifecycleListener {
|
|
||||||
|
|
||||||
|
|
||||||
public static class AccessCode {
|
|
||||||
protected String id = UUID.randomUUID().toString() + System.currentTimeMillis();
|
|
||||||
protected long expiration;
|
|
||||||
protected SkeletonKeyToken token;
|
|
||||||
protected String client;
|
|
||||||
protected boolean sso;
|
|
||||||
protected String redirect;
|
|
||||||
|
|
||||||
public boolean isExpired() {
|
|
||||||
return expiration != 0 && (System.currentTimeMillis() / 1000) > expiration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getExpiration() {
|
|
||||||
return expiration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setExpiration(long expiration) {
|
|
||||||
this.expiration = expiration;
|
|
||||||
}
|
|
||||||
|
|
||||||
public SkeletonKeyToken getToken() {
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToken(SkeletonKeyToken token) {
|
|
||||||
this.token = token;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getClient() {
|
|
||||||
return client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setClient(String client) {
|
|
||||||
this.client = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSso() {
|
|
||||||
return sso;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setSso(boolean sso) {
|
|
||||||
this.sso = sso;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getRedirect() {
|
|
||||||
return redirect;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRedirect(String redirect) {
|
|
||||||
this.redirect = redirect;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected ConcurrentHashMap<String, AccessCode> accessCodeMap = new ConcurrentHashMap<String, AccessCode>();
|
|
||||||
private static final Logger log = Logger.getLogger(OAuthAuthenticationServerValve.class);
|
|
||||||
|
|
||||||
private static AtomicLong counter = new AtomicLong(1);
|
|
||||||
|
|
||||||
private static String generateId() {
|
|
||||||
return counter.getAndIncrement() + "." + UUID.randomUUID().toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AuthServerConfig skeletonKeyConfig;
|
|
||||||
protected PrivateKey realmPrivateKey;
|
|
||||||
protected PublicKey realmPublicKey;
|
|
||||||
protected String realmPublicKeyPem;
|
|
||||||
protected ResteasyProviderFactory providers;
|
|
||||||
protected ResourceMetadata resourceMetadata;
|
|
||||||
protected UserSessionManagement userSessionManagement = new UserSessionManagement();
|
|
||||||
protected ObjectMapper mapper;
|
|
||||||
protected ObjectWriter accessTokenResponseWriter;
|
|
||||||
protected ObjectWriter mapWriter;
|
|
||||||
|
|
||||||
private static KeyStore loadKeyStore(String filename, String password) throws Exception {
|
|
||||||
KeyStore trustStore = KeyStore.getInstance(KeyStore
|
|
||||||
.getDefaultType());
|
|
||||||
File truststoreFile = new File(filename);
|
|
||||||
FileInputStream trustStream = new FileInputStream(truststoreFile);
|
|
||||||
trustStore.load(trustStream, password.toCharArray());
|
|
||||||
trustStream.close();
|
|
||||||
return trustStore;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void start() throws LifecycleException {
|
|
||||||
super.start();
|
|
||||||
StandardContext standardContext = (StandardContext) context;
|
|
||||||
standardContext.addLifecycleListener(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void lifecycleEvent(LifecycleEvent event) {
|
|
||||||
if (event.getType() == Lifecycle.AFTER_START_EVENT) init();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void init() {
|
|
||||||
mapper = new ObjectMapper();
|
|
||||||
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
|
|
||||||
accessTokenResponseWriter = mapper.writerWithType(AccessTokenResponse.class);
|
|
||||||
mapWriter = mapper.writerWithType(mapper.getTypeFactory().constructMapType(Map.class, String.class, String.class));
|
|
||||||
|
|
||||||
InputStream is = null;
|
|
||||||
String path = context.getServletContext().getInitParameter("skeleton.key.config.file");
|
|
||||||
if (path == null) {
|
|
||||||
is = context.getServletContext().getResourceAsStream("/WEB-INF/resteasy-oauth.json");
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
is = new FileInputStream(path);
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
skeletonKeyConfig = mapper.readValue(is, AuthServerConfig.class);
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
if (skeletonKeyConfig.getLoginRole() == null) {
|
|
||||||
throw new RuntimeException("You must define the login-role in your config file");
|
|
||||||
}
|
|
||||||
if (skeletonKeyConfig.getClientRole() == null) {
|
|
||||||
throw new RuntimeException("You must define the oauth-client-role in your config file");
|
|
||||||
}
|
|
||||||
if (skeletonKeyConfig.getRealmPrivateKey() != null) {
|
|
||||||
try {
|
|
||||||
realmPrivateKey = PemUtils.decodePrivateKey(skeletonKeyConfig.getRealmPrivateKey());
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (skeletonKeyConfig.getRealmPublicKey() != null) {
|
|
||||||
try {
|
|
||||||
realmPublicKey = PemUtils.decodePublicKey(skeletonKeyConfig.getRealmPublicKey());
|
|
||||||
realmPublicKeyPem = skeletonKeyConfig.getRealmPublicKey();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (skeletonKeyConfig.getRealmKeyStore() != null) {
|
|
||||||
if (skeletonKeyConfig.getRealmKeyAlias() == null) throw new RuntimeException("Must define realm-key-alias");
|
|
||||||
String keystorePath = EnvUtil.replace(skeletonKeyConfig.getRealmKeyStore());
|
|
||||||
try {
|
|
||||||
KeyStore ks = loadKeyStore(keystorePath, skeletonKeyConfig.getRealmKeystorePassword());
|
|
||||||
if (realmPrivateKey == null) {
|
|
||||||
realmPrivateKey = (PrivateKey) ks.getKey(skeletonKeyConfig.getRealmKeyAlias(), skeletonKeyConfig.getRealmPrivateKeyPassword().toCharArray());
|
|
||||||
}
|
|
||||||
if (realmPublicKey == null) {
|
|
||||||
Certificate cert = ks.getCertificate(skeletonKeyConfig.getRealmKeyAlias());
|
|
||||||
realmPublicKey = cert.getPublicKey();
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (realmPublicKey == null) throw new RuntimeException("You have not declared a keystore or public key");
|
|
||||||
if (realmPrivateKey == null) throw new RuntimeException("You have not declared a keystore or private key");
|
|
||||||
if (realmPublicKeyPem == null) {
|
|
||||||
StringWriter sw = new StringWriter();
|
|
||||||
PEMWriter writer = new PEMWriter(sw);
|
|
||||||
try {
|
|
||||||
writer.writeObject(realmPublicKey);
|
|
||||||
writer.flush();
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
realmPublicKeyPem = sw.toString();
|
|
||||||
realmPublicKeyPem = PemUtils.removeBeginEnd(realmPublicKeyPem);
|
|
||||||
}
|
|
||||||
providers = new ResteasyProviderFactory();
|
|
||||||
ClassLoader old = Thread.currentThread().getContextClassLoader();
|
|
||||||
Thread.currentThread().setContextClassLoader(OAuthAuthenticationServerValve.class.getClassLoader());
|
|
||||||
try {
|
|
||||||
ResteasyProviderFactory.getInstance(); // initialize builtins
|
|
||||||
RegisterBuiltin.register(providers);
|
|
||||||
} finally {
|
|
||||||
Thread.currentThread().setContextClassLoader(old);
|
|
||||||
}
|
|
||||||
resourceMetadata = new ResourceMetadata();
|
|
||||||
resourceMetadata.setRealm(skeletonKeyConfig.getRealm());
|
|
||||||
resourceMetadata.setRealmKey(realmPublicKey);
|
|
||||||
String truststore = skeletonKeyConfig.getTruststore();
|
|
||||||
if (truststore != null) {
|
|
||||||
truststore = EnvUtil.replace(truststore);
|
|
||||||
String truststorePassword = skeletonKeyConfig.getTruststorePassword();
|
|
||||||
KeyStore trust = null;
|
|
||||||
try {
|
|
||||||
trust = loadKeyStore(truststore, truststorePassword);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Failed to load truststore", e);
|
|
||||||
}
|
|
||||||
resourceMetadata.setTruststore(trust);
|
|
||||||
}
|
|
||||||
String clientKeystore = skeletonKeyConfig.getClientKeystore();
|
|
||||||
String clientKeyPassword = null;
|
|
||||||
if (clientKeystore != null) {
|
|
||||||
clientKeystore = EnvUtil.replace(clientKeystore);
|
|
||||||
String clientKeystorePassword = skeletonKeyConfig.getClientKeystorePassword();
|
|
||||||
KeyStore serverKS = null;
|
|
||||||
try {
|
|
||||||
serverKS = loadKeyStore(clientKeystore, clientKeystorePassword);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException("Failed to load keystore", e);
|
|
||||||
}
|
|
||||||
resourceMetadata.setClientKeystore(serverKS);
|
|
||||||
clientKeyPassword = skeletonKeyConfig.getClientKeyPassword();
|
|
||||||
resourceMetadata.setClientKeyPassword(clientKeyPassword);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void invoke(Request request, Response response) throws IOException, ServletException {
|
|
||||||
try {
|
|
||||||
String contextPath = request.getContextPath();
|
|
||||||
String requestURI = request.getDecodedRequestURI();
|
|
||||||
log.debug("--- invoke: " + requestURI);
|
|
||||||
if (request.getMethod().equalsIgnoreCase("GET")
|
|
||||||
&& context.getLoginConfig().getLoginPage().equals(request.getRequestPathMB().toString())) {
|
|
||||||
if (handleLoginPage(request, response)) return;
|
|
||||||
} else if (request.getMethod().equalsIgnoreCase("GET")
|
|
||||||
&& requestURI.endsWith(Actions.J_OAUTH_LOGOUT)) {
|
|
||||||
logoutCurrentUser(request, response);
|
|
||||||
return;
|
|
||||||
} else if (request.getMethod().equalsIgnoreCase("POST")
|
|
||||||
&& requestURI.endsWith(Actions.J_OAUTH_ADMIN_FORCED_LOGOUT)) {
|
|
||||||
adminLogout(request, response);
|
|
||||||
return;
|
|
||||||
} else if (request.getMethod().equalsIgnoreCase("POST")
|
|
||||||
&& requestURI.startsWith(contextPath) &&
|
|
||||||
requestURI.endsWith(Constants.FORM_ACTION)
|
|
||||||
&& request.getParameter("client_id") != null) {
|
|
||||||
handleOAuth(request, response);
|
|
||||||
return;
|
|
||||||
} else if (request.getMethod().equalsIgnoreCase("POST")
|
|
||||||
&& requestURI.endsWith(Actions.J_OAUTH_TOKEN_GRANT)) {
|
|
||||||
tokenGrant(request, response);
|
|
||||||
return;
|
|
||||||
} else if (request.getMethod().equalsIgnoreCase("POST")
|
|
||||||
&& requestURI.startsWith(contextPath) &&
|
|
||||||
requestURI.endsWith(Actions.J_OAUTH_RESOLVE_ACCESS_CODE)) {
|
|
||||||
resolveAccessCode(request, response);
|
|
||||||
return;
|
|
||||||
} else if (request.getMethod().equalsIgnoreCase("GET")
|
|
||||||
&& requestURI.startsWith(contextPath) &&
|
|
||||||
requestURI.endsWith("j_oauth_realm_info.html")) {
|
|
||||||
publishRealmInfoHtml(request, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// propagate the skeleton key token string?
|
|
||||||
if (!skeletonKeyConfig.isCancelPropagation()) {
|
|
||||||
if (request.getAttribute(SkeletonKeySession.class.getName()) == null && request.getSessionInternal() != null) {
|
|
||||||
SkeletonKeySession skSession = (SkeletonKeySession) request.getSessionInternal().getNote(SkeletonKeySession.class.getName());
|
|
||||||
if (skSession != null) {
|
|
||||||
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
|
|
||||||
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
request.setAttribute("OAUTH_FORM_ACTION", "j_security_check");
|
|
||||||
super.invoke(request, response);
|
|
||||||
} finally {
|
|
||||||
ResteasyProviderFactory.clearContextData(); // to clear push of SkeletonKeySession
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected boolean handleLoginPage(Request request, Response response) throws IOException, ServletException {
|
|
||||||
String client_id = request.getParameter("client_id");
|
|
||||||
// if this is not an OAUTH redirect, just return and let the default flow happen
|
|
||||||
if (client_id == null) return false;
|
|
||||||
|
|
||||||
String redirect_uri = request.getParameter("redirect_uri");
|
|
||||||
String state = request.getParameter("state");
|
|
||||||
|
|
||||||
if (redirect_uri == null) {
|
|
||||||
response.sendError(400, "No oauth redirect query parameter set");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// only bypass authentication if our session is authenticated,
|
|
||||||
// the login query parameter is on request URL,
|
|
||||||
// and we have configured the login-role
|
|
||||||
else if (!skeletonKeyConfig.isSsoDisabled()
|
|
||||||
&& request.getSessionInternal() != null
|
|
||||||
&& request.getSessionInternal().getPrincipal() != null
|
|
||||||
&& request.getParameter("login") != null) {
|
|
||||||
log.debug("We're ALREADY LOGGED IN!!!");
|
|
||||||
GenericPrincipal gp = (GenericPrincipal) request.getSessionInternal().getPrincipal();
|
|
||||||
redirectAccessCode(true, response, redirect_uri, client_id, state, gp);
|
|
||||||
} else {
|
|
||||||
UriBuilder builder = UriBuilder.fromUri("j_security_check")
|
|
||||||
.queryParam("redirect_uri", redirect_uri)
|
|
||||||
.queryParam("client_id", client_id);
|
|
||||||
if (state != null) builder.queryParam("state", state);
|
|
||||||
String loginAction = builder.build().toString();
|
|
||||||
request.setAttribute("OAUTH_FORM_ACTION", loginAction);
|
|
||||||
getNext().invoke(request, response);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected GenericPrincipal checkLoggedIn(Request request, HttpServletResponse response) {
|
|
||||||
if (request.getPrincipal() != null) {
|
|
||||||
return (GenericPrincipal) request.getPrincipal();
|
|
||||||
} else if (request.getSessionInternal() != null && request.getSessionInternal().getPrincipal() != null) {
|
|
||||||
return (GenericPrincipal) request.getSessionInternal().getPrincipal();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected void adminLogout(Request request, HttpServletResponse response) throws IOException {
|
|
||||||
log.debug("<< adminLogout");
|
|
||||||
GenericPrincipal gp = checkLoggedIn(request, response);
|
|
||||||
if (gp == null) {
|
|
||||||
if (bearer(request, response, false)) {
|
|
||||||
gp = (GenericPrincipal) request.getPrincipal();
|
|
||||||
} else {
|
|
||||||
response.sendError(403);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!gp.hasRole(skeletonKeyConfig.getAdminRole())) {
|
|
||||||
response.sendError(403);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String logoutUser = request.getParameter("user");
|
|
||||||
if (logoutUser != null) {
|
|
||||||
userSessionManagement.logout(logoutUser);
|
|
||||||
logoutResources(logoutUser, gp.getName());
|
|
||||||
} else {
|
|
||||||
userSessionManagement.logoutAllBut(gp.getName());
|
|
||||||
logoutResources(null, gp.getName());
|
|
||||||
}
|
|
||||||
String forwardTo = request.getParameter("forward");
|
|
||||||
if (forwardTo == null) {
|
|
||||||
response.setStatus(204);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RequestDispatcher disp =
|
|
||||||
context.getServletContext().getRequestDispatcher(forwardTo);
|
|
||||||
try {
|
|
||||||
disp.forward(request.getRequest(), response);
|
|
||||||
} catch (Throwable t) {
|
|
||||||
request.setAttribute(RequestDispatcher.ERROR_EXCEPTION, t);
|
|
||||||
response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
|
||||||
"failed to forward");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected void logoutCurrentUser(Request request, HttpServletResponse response) throws IOException {
|
|
||||||
if (request.getSessionInternal() == null || request.getSessionInternal().getPrincipal() == null) {
|
|
||||||
redirectToWelcomePage(request, response);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GenericPrincipal principal = (GenericPrincipal) request.getSessionInternal().getPrincipal();
|
|
||||||
String username = principal.getName();
|
|
||||||
String admin = username;
|
|
||||||
userSessionManagement.logout(username);
|
|
||||||
request.setUserPrincipal(null);
|
|
||||||
request.setAuthType(null);
|
|
||||||
// logout user on all declared authenticated applications
|
|
||||||
logoutResources(username, admin);
|
|
||||||
redirectToWelcomePage(request, response);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void logoutResources(String username, String admin) {
|
|
||||||
if (skeletonKeyConfig.getResources().size() != 0) {
|
|
||||||
SkeletonKeyToken token = new SkeletonKeyToken();
|
|
||||||
token.id(generateId());
|
|
||||||
token.principal(admin);
|
|
||||||
token.audience(skeletonKeyConfig.getRealm());
|
|
||||||
SkeletonKeyToken.Access realmAccess = new SkeletonKeyToken.Access();
|
|
||||||
realmAccess.addRole(skeletonKeyConfig.getAdminRole());
|
|
||||||
token.setRealmAccess(realmAccess);
|
|
||||||
String tokenString = buildTokenString(realmPrivateKey, token);
|
|
||||||
ResteasyClient client = new ResteasyClientBuilder()
|
|
||||||
.providerFactory(providers)
|
|
||||||
.hostnameVerification(ResteasyClientBuilder.HostnameVerificationPolicy.ANY)
|
|
||||||
.trustStore(resourceMetadata.getTruststore())
|
|
||||||
.keyStore(resourceMetadata.getClientKeystore(), resourceMetadata.getClientKeyPassword())
|
|
||||||
.build();
|
|
||||||
try {
|
|
||||||
for (String resource : skeletonKeyConfig.getResources()) {
|
|
||||||
try {
|
|
||||||
log.debug("logging out: " + resource);
|
|
||||||
WebTarget target = client.target(resource).path(Actions.J_OAUTH_REMOTE_LOGOUT);
|
|
||||||
if (username != null) target = target.queryParam("user", username);
|
|
||||||
javax.ws.rs.core.Response response = target.request()
|
|
||||||
.header("Authorization", "Bearer " + tokenString)
|
|
||||||
.put(null);
|
|
||||||
if (response.getStatus() != 204) log.error("Failed to log out");
|
|
||||||
response.close();
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
log.error("Failed to log out", ignored);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
client.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void redirectToWelcomePage(Request request, HttpServletResponse response) throws IOException {
|
|
||||||
ResteasyUriInfo uriInfo = ServletUtil.extractUriInfo(request, null);
|
|
||||||
String[] welcomes = context.findWelcomeFiles();
|
|
||||||
if (welcomes.length > 0) {
|
|
||||||
UriBuilder welcome = uriInfo.getBaseUriBuilder().path(welcomes[0]);
|
|
||||||
response.sendRedirect(welcome.toTemplate());
|
|
||||||
} else {
|
|
||||||
response.setStatus(204);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected void publishRealmInfoHtml(Request request, HttpServletResponse response) throws IOException {
|
|
||||||
ManagedResourceConfig rep = getRealmRepresentation(request);
|
|
||||||
StringWriter writer;
|
|
||||||
String json;
|
|
||||||
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
|
||||||
mapper.setSerializationInclusion(JsonSerialize.Inclusion.NON_DEFAULT);
|
|
||||||
mapper.enable(SerializationConfig.Feature.INDENT_OUTPUT);
|
|
||||||
|
|
||||||
StringBuffer html = new StringBuffer();
|
|
||||||
html.append("<html><body bgcolor=\"#CED8F6\">");
|
|
||||||
html.append("<h1>Realm: ").append(rep.getRealm()).append("</h1>");
|
|
||||||
|
|
||||||
ManagedResourceConfig bearer = new ManagedResourceConfig();
|
|
||||||
bearer.setRealm(rep.getRealm());
|
|
||||||
bearer.setRealmKey(rep.getRealmKey());
|
|
||||||
writer = new StringWriter();
|
|
||||||
mapper.writeValue(writer, bearer);
|
|
||||||
json = writer.toString();
|
|
||||||
|
|
||||||
html.append("<h3>BearerTokenAuthValve Json Config</h3>");
|
|
||||||
html.append("<form><textarea rows=\"7\" cols=\"80\">").append(json).append("</textarea></form>");
|
|
||||||
|
|
||||||
html.append("<br>");
|
|
||||||
|
|
||||||
writer = new StringWriter();
|
|
||||||
rep.getCredentials().put("password", "REQUIRED");
|
|
||||||
//rep.setClientId("REQUIRED");
|
|
||||||
rep.setTruststore("REQUIRED");
|
|
||||||
rep.setTruststorePassword("REQUIRED");
|
|
||||||
mapper.writeValue(writer, rep);
|
|
||||||
json = writer.toString();
|
|
||||||
html.append("<h3>OAuthManagedResourceValve Json Config</h3>");
|
|
||||||
html.append("<form><textarea rows=\"20\" cols=\"80\">").append(json).append("</textarea></form>");
|
|
||||||
|
|
||||||
html.append("</body></html>");
|
|
||||||
|
|
||||||
response.setStatus(200);
|
|
||||||
response.setContentType("text/html");
|
|
||||||
response.getOutputStream().println(html.toString());
|
|
||||||
response.getOutputStream().flush();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected ManagedResourceConfig getRealmRepresentation(Request request) {
|
|
||||||
ManagedResourceConfig rep = new ManagedResourceConfig();
|
|
||||||
ResteasyUriInfo uriInfo = ServletUtil.extractUriInfo(request, null);
|
|
||||||
UriBuilder authUrl = uriInfo.getBaseUriBuilder().path(context.getLoginConfig().getLoginPage());
|
|
||||||
UriBuilder codeUrl = uriInfo.getBaseUriBuilder().path(Actions.J_OAUTH_RESOLVE_ACCESS_CODE);
|
|
||||||
rep.setRealm(skeletonKeyConfig.getRealm());
|
|
||||||
rep.setRealmKey(realmPublicKeyPem);
|
|
||||||
rep.setAuthUrl(authUrl.toTemplate());
|
|
||||||
rep.setCodeUrl(codeUrl.toTemplate());
|
|
||||||
rep.setAdminRole(skeletonKeyConfig.getAdminRole());
|
|
||||||
return rep;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean bearer(Request request, HttpServletResponse response, boolean propagate) throws IOException {
|
|
||||||
if (request.getHeader("Authorization") != null) {
|
|
||||||
CatalinaBearerTokenAuthenticator bearer = new CatalinaBearerTokenAuthenticator(resourceMetadata, false, false);
|
|
||||||
try {
|
|
||||||
if (bearer.login(request, response)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} catch (LoginException e) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void register(Request request, HttpServletResponse response, Principal principal, String authType, String username, String password) {
|
|
||||||
super.register(request, response, principal, authType, username, password);
|
|
||||||
log.debug("authenticate userSessionManage.login(): " + principal.getName());
|
|
||||||
userSessionManagement.login(request.getSessionInternal(), principal.getName());
|
|
||||||
if (!skeletonKeyConfig.isCancelPropagation()) {
|
|
||||||
GenericPrincipal gp = (GenericPrincipal) request.getPrincipal();
|
|
||||||
if (gp != null) {
|
|
||||||
SkeletonKeyToken token = buildToken(gp);
|
|
||||||
String stringToken = buildTokenString(realmPrivateKey, token);
|
|
||||||
SkeletonKeySession skSession = new SkeletonKeySession(stringToken, token, resourceMetadata);
|
|
||||||
request.setAttribute(SkeletonKeySession.class.getName(), skSession);
|
|
||||||
ResteasyProviderFactory.pushContext(SkeletonKeySession.class, skSession);
|
|
||||||
request.getSessionInternal(true).setNote(SkeletonKeySession.class.getName(), skSession);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean authenticate(Request request, HttpServletResponse response, LoginConfig config) throws IOException {
|
|
||||||
if (bearer(request, response, true)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.authenticate(request, response, config);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected void resolveAccessCode(Request request, Response response) throws IOException {
|
|
||||||
if (!request.isSecure()) {
|
|
||||||
response.sendError(400);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// always verify code and remove access code from map before authenticating user
|
|
||||||
// if user authentication fails, we want the code to be removed irreguardless just in case we're under attack
|
|
||||||
String code = request.getParameter("code");
|
|
||||||
JWSInput input = new JWSInput(code, providers);
|
|
||||||
boolean verifiedCode = false;
|
|
||||||
try {
|
|
||||||
verifiedCode = RSAProvider.verify(input, realmPublicKey);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
log.error("Failed to verify signature", ignored);
|
|
||||||
}
|
|
||||||
if (!verifiedCode) {
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put("error", "invalid_grant");
|
|
||||||
res.put("error_description", "Unable to verify code signature");
|
|
||||||
response.sendError(400);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
mapWriter.writeValue(response.getOutputStream(), res);
|
|
||||||
response.getOutputStream().flush();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
String key = input.readContent(String.class);
|
|
||||||
AccessCode accessCode = accessCodeMap.remove(key);
|
|
||||||
String redirect = request.getParameter("redirect_uri");
|
|
||||||
|
|
||||||
GenericPrincipal gp = basicAuth(request, response);
|
|
||||||
if (gp == null) {
|
|
||||||
log.error("Failed to authenticate client_id");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (accessCode == null) {
|
|
||||||
log.error("No access code: " + code);
|
|
||||||
response.sendError(400);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (accessCode.isExpired()) {
|
|
||||||
log.debug("Access code expired");
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put("error", "invalid_grant");
|
|
||||||
res.put("error_description", "Code is expired");
|
|
||||||
response.setStatus(400);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
mapWriter.writeValue(response.getOutputStream(), res);
|
|
||||||
response.getOutputStream().flush();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!accessCode.getToken().isActive()) {
|
|
||||||
log.debug("token not active");
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put("error", "invalid_grant");
|
|
||||||
res.put("error_description", "Token expired");
|
|
||||||
response.setStatus(400);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
mapWriter.writeValue(response.getOutputStream(), res);
|
|
||||||
response.getOutputStream().flush();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!gp.getName().equals(accessCode.getClient())) {
|
|
||||||
log.debug("not equal client");
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put("error", "invalid_grant");
|
|
||||||
res.put("error_description", "Auth error");
|
|
||||||
response.setStatus(400);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
mapWriter.writeValue(response.getOutputStream(), res);
|
|
||||||
response.getOutputStream().flush();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!accessCode.getRedirect().equals(redirect)) {
|
|
||||||
log.debug("not equal redirect");
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put("error", "invalid_grant");
|
|
||||||
res.put("error_description", "Auth error");
|
|
||||||
response.setStatus(400);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
mapWriter.writeValue(response.getOutputStream(), res);
|
|
||||||
response.getOutputStream().flush();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (accessCode.isSso() && !gp.hasRole(skeletonKeyConfig.getLoginRole())) {
|
|
||||||
// we did not authenticate user on an access code request because a session was already established
|
|
||||||
// but, the client_id does not have permission to bypass this on a simple grant. We want
|
|
||||||
// to always ask for credentials from a simple oath request
|
|
||||||
|
|
||||||
log.debug("does not have login permission");
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put("error", "invalid_grant");
|
|
||||||
res.put("error_description", "Auth error");
|
|
||||||
response.setStatus(400);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
mapWriter.writeValue(response.getOutputStream(), res);
|
|
||||||
response.getOutputStream().flush();
|
|
||||||
return;
|
|
||||||
} else if (!gp.hasRole(skeletonKeyConfig.getClientRole()) && !gp.hasRole(skeletonKeyConfig.getLoginRole())) {
|
|
||||||
log.debug("does not have login or client role permission for access token request");
|
|
||||||
Map<String, String> res = new HashMap<String, String>();
|
|
||||||
res.put("error", "invalid_grant");
|
|
||||||
res.put("error_description", "Auth error");
|
|
||||||
response.setStatus(400);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
mapWriter.writeValue(response.getOutputStream(), res);
|
|
||||||
response.getOutputStream().flush();
|
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
String wildcard = skeletonKeyConfig.getWildcardRole() == null ? "*" : skeletonKeyConfig.getWildcardRole();
|
|
||||||
Set<String> codeRoles = accessCode.getToken().getRealmAccess().getRoles();
|
|
||||||
if (codeRoles != null &&
|
|
||||||
(codeRoles.contains(skeletonKeyConfig.getClientRole()) || codeRoles.contains(skeletonKeyConfig.getLoginRole()))) {
|
|
||||||
// we store roles a oauth client is granted in the user role mapping, remove those roles as we don't want those clients with those
|
|
||||||
// permissions if they are logging in.
|
|
||||||
Set<String> newRoles = new HashSet<String>();
|
|
||||||
if (codeRoles.contains(skeletonKeyConfig.getClientRole())) newRoles.add(skeletonKeyConfig.getClientRole());
|
|
||||||
if (codeRoles.contains(skeletonKeyConfig.getLoginRole())) newRoles.add(skeletonKeyConfig.getLoginRole());
|
|
||||||
if (codeRoles.contains(wildcard)) newRoles.add(wildcard);
|
|
||||||
codeRoles.clear();
|
|
||||||
codeRoles.addAll(newRoles);
|
|
||||||
}
|
|
||||||
|
|
||||||
// is we have a login role, then we don't need to filter out roles, just grant all the roles the user has
|
|
||||||
// Also, if the client has the "wildcard" role, then we don't need to filter out roles
|
|
||||||
if (codeRoles != null
|
|
||||||
&& !gp.hasRole(wildcard)
|
|
||||||
&& !gp.hasRole(skeletonKeyConfig.getLoginRole())) {
|
|
||||||
Set<String> clientAllowed = new HashSet<String>();
|
|
||||||
for (String role : gp.getRoles()) {
|
|
||||||
clientAllowed.add(role);
|
|
||||||
}
|
|
||||||
Set<String> newRoles = new HashSet<String>();
|
|
||||||
newRoles.addAll(codeRoles);
|
|
||||||
for (String role : newRoles) {
|
|
||||||
if (!clientAllowed.contains(role)) {
|
|
||||||
codeRoles.remove(role);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AccessTokenResponse res = accessTokenResponse(realmPrivateKey, accessCode.getToken());
|
|
||||||
response.setStatus(200);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
accessTokenResponseWriter.writeValue(response.getOutputStream(), res);
|
|
||||||
response.getOutputStream().flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected AccessTokenResponse accessTokenResponse(PrivateKey privateKey, SkeletonKeyToken token) {
|
|
||||||
String encodedToken = buildTokenString(privateKey, token);
|
|
||||||
|
|
||||||
AccessTokenResponse res = new AccessTokenResponse();
|
|
||||||
res.setToken(encodedToken);
|
|
||||||
res.setTokenType("bearer");
|
|
||||||
if (token.getExpiration() != 0) {
|
|
||||||
long time = token.getExpiration() - (System.currentTimeMillis() / 1000);
|
|
||||||
res.setExpiresIn(time);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected String buildTokenString(PrivateKey privateKey, SkeletonKeyToken token) {
|
|
||||||
byte[] tokenBytes = null;
|
|
||||||
try {
|
|
||||||
tokenBytes = JsonSerialization.toByteArray(token, false);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
return new JWSBuilder()
|
|
||||||
.content(tokenBytes)
|
|
||||||
.rsa256(privateKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
protected void handleOAuth(Request request, Response response) throws IOException {
|
|
||||||
log.debug("<--- Begin oauthAuthenticate");
|
|
||||||
String redirect_uri = request.getParameter("redirect_uri");
|
|
||||||
String client_id = request.getParameter("client_id");
|
|
||||||
String state = request.getParameter("state");
|
|
||||||
String username = request.getParameter(Constants.FORM_USERNAME);
|
|
||||||
String password = request.getParameter(Constants.FORM_PASSWORD);
|
|
||||||
Principal principal = context.getRealm().authenticate(username, password);
|
|
||||||
if (principal == null) {
|
|
||||||
UriBuilder builder = UriBuilder.fromUri(redirect_uri).queryParam("error", "unauthorized_client");
|
|
||||||
if (state != null) builder.queryParam("state", state);
|
|
||||||
response.sendRedirect(builder.toTemplate());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GenericPrincipal gp = (GenericPrincipal) principal;
|
|
||||||
register(request, response, principal, HttpServletRequest.FORM_AUTH, username, password);
|
|
||||||
userSessionManagement.login(request.getSessionInternal(), username);
|
|
||||||
redirectAccessCode(false, response, redirect_uri, client_id, state, gp);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void tokenGrant(Request request, Response response) throws IOException {
|
|
||||||
if (!request.isSecure()) {
|
|
||||||
response.sendError(400);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GenericPrincipal gp = basicAuth(request, response);
|
|
||||||
if (gp == null) return;
|
|
||||||
SkeletonKeyToken token = buildToken(gp);
|
|
||||||
AccessTokenResponse res = accessTokenResponse(realmPrivateKey, token);
|
|
||||||
response.setStatus(200);
|
|
||||||
response.setContentType("application/json");
|
|
||||||
accessTokenResponseWriter.writeValue(response.getOutputStream(), res);
|
|
||||||
response.getOutputStream().flush();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected GenericPrincipal basicAuth(Request request, Response response) throws IOException {
|
|
||||||
String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);
|
|
||||||
if (authHeader == null) {
|
|
||||||
basicAuthError(response);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String[] creds = BasicAuthHelper.parseHeader(authHeader);
|
|
||||||
if (creds == null) {
|
|
||||||
basicAuthError(response);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
String username = creds[0];
|
|
||||||
String password = creds[1];
|
|
||||||
GenericPrincipal gp = (GenericPrincipal) context.getRealm().authenticate(username, password);
|
|
||||||
if (gp == null) {
|
|
||||||
basicAuthError(response);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return gp;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void basicAuthError(Response response) throws IOException {
|
|
||||||
response.setHeader(HttpHeaders.WWW_AUTHENTICATE, "Basic realm=\"" + context.getLoginConfig().getRealmName() + "\"");
|
|
||||||
response.sendError(401);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void redirectAccessCode(boolean sso, Response response, String redirect_uri, String client_id, String state, GenericPrincipal gp) throws IOException {
|
|
||||||
SkeletonKeyToken token = buildToken(gp);
|
|
||||||
AccessCode code = new AccessCode();
|
|
||||||
code.setToken(token);
|
|
||||||
code.setClient(client_id);
|
|
||||||
code.setSso(sso);
|
|
||||||
code.setRedirect(redirect_uri);
|
|
||||||
int expiration = skeletonKeyConfig.getAccessCodeLifetime() == 0 ? 300 : skeletonKeyConfig.getAccessCodeLifetime();
|
|
||||||
code.setExpiration((System.currentTimeMillis() / 1000) + expiration);
|
|
||||||
accessCodeMap.put(code.getId(), code);
|
|
||||||
log.debug("--- sign access code");
|
|
||||||
String accessCode = null;
|
|
||||||
try {
|
|
||||||
accessCode = new JWSBuilder().content(code.getId().getBytes("UTF-8")).rsa256(realmPrivateKey);
|
|
||||||
} catch (UnsupportedEncodingException e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
log.debug("--- build redirect");
|
|
||||||
UriBuilder redirectUri = UriBuilder.fromUri(redirect_uri).queryParam("code", accessCode);
|
|
||||||
if (state != null) redirectUri.queryParam("state", state);
|
|
||||||
response.sendRedirect(redirectUri.toTemplate());
|
|
||||||
log.debug("<--- end oauthAuthenticate");
|
|
||||||
}
|
|
||||||
|
|
||||||
protected SkeletonKeyToken buildToken(GenericPrincipal gp) {
|
|
||||||
SkeletonKeyToken token = new SkeletonKeyToken();
|
|
||||||
token.id(generateId());
|
|
||||||
token.principal(gp.getName());
|
|
||||||
token.audience(skeletonKeyConfig.getRealm());
|
|
||||||
int expiration = skeletonKeyConfig.getAccessCodeLifetime() == 0 ? 3600 : skeletonKeyConfig.getAccessCodeLifetime();
|
|
||||||
if (skeletonKeyConfig.getTokenLifetime() > 0) {
|
|
||||||
token.expiration((System.currentTimeMillis() / 1000) + expiration);
|
|
||||||
}
|
|
||||||
SkeletonKeyToken.Access realmAccess = new SkeletonKeyToken.Access();
|
|
||||||
for (String role : gp.getRoles()) {
|
|
||||||
realmAccess.addRole(role);
|
|
||||||
}
|
|
||||||
token.setRealmAccess(realmAccess);
|
|
||||||
return token;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -5,7 +5,6 @@ import org.codehaus.jackson.annotate.JsonPropertyOrder;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
|
|
@ -13,7 +13,6 @@ import org.keycloak.PemUtils;
|
||||||
import org.keycloak.ResourceMetadata;
|
import org.keycloak.ResourceMetadata;
|
||||||
import org.keycloak.representations.idm.PublishedRealmRepresentation;
|
import org.keycloak.representations.idm.PublishedRealmRepresentation;
|
||||||
|
|
||||||
import javax.ws.rs.client.WebTarget;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
package org.keycloak.models;
|
package org.keycloak.models;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 $
|
||||||
|
|
9
model/api/src/main/java/org/keycloak/models/ModelProvider.java
Executable file
9
model/api/src/main/java/org/keycloak/models/ModelProvider.java
Executable file
|
@ -0,0 +1,9 @@
|
||||||
|
package org.keycloak.models;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public interface ModelProvider {
|
||||||
|
KeycloakSessionFactory createFactory();
|
||||||
|
}
|
|
@ -1,7 +1,5 @@
|
||||||
package org.keycloak.models;
|
package org.keycloak.models;
|
||||||
|
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 $
|
||||||
|
@ -10,8 +8,4 @@ public interface OAuthClientModel {
|
||||||
String getId();
|
String getId();
|
||||||
|
|
||||||
UserModel getOAuthAgent();
|
UserModel getOAuthAgent();
|
||||||
|
|
||||||
String getBaseUrl();
|
|
||||||
|
|
||||||
void setBaseUrl(String base);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package org.keycloak.models;
|
||||||
|
|
||||||
import java.security.PrivateKey;
|
import java.security.PrivateKey;
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -138,11 +137,11 @@ public interface RealmModel extends RoleContainerModel, RoleMapperModel, ScopeMa
|
||||||
|
|
||||||
List<OAuthClientModel> getOAuthClients();
|
List<OAuthClientModel> getOAuthClients();
|
||||||
|
|
||||||
HashMap<String, String> getSmtpConfig();
|
Map<String, String> getSmtpConfig();
|
||||||
|
|
||||||
void setSmtpConfig(HashMap<String, String> smtpConfig);
|
void setSmtpConfig(Map<String, String> smtpConfig);
|
||||||
|
|
||||||
HashMap<String, String> getSocialConfig();
|
Map<String, String> getSocialConfig();
|
||||||
|
|
||||||
void setSocialConfig(HashMap<String, String> socialConfig);
|
void setSocialConfig(Map<String, String> socialConfig);
|
||||||
}
|
}
|
||||||
|
|
113
model/api/src/main/java/org/keycloak/models/utils/Base32.java
Executable file
113
model/api/src/main/java/org/keycloak/models/utils/Base32.java
Executable file
|
@ -0,0 +1,113 @@
|
||||||
|
package org.keycloak.models.utils;
|
||||||
|
|
||||||
|
|
||||||
|
/* (PD) 2006 The Bitzi Corporation
|
||||||
|
* Please see http://bitzi.com/publicdomain for more info.
|
||||||
|
*
|
||||||
|
* $Id: Base32.java,v 1.2 2006/07/14 04:58:39 gojomo Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base32 - encodes and decodes RFC3548 Base32 (see http://www.faqs.org/rfcs/rfc3548.html )
|
||||||
|
*
|
||||||
|
* @author Robert Kaye
|
||||||
|
* @author Gordon Mohr
|
||||||
|
*/
|
||||||
|
public class Base32 {
|
||||||
|
private static final String base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||||
|
private static final int[] base32Lookup = { 0xFF, 0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||||
|
0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
|
||||||
|
0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01,
|
||||||
|
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14,
|
||||||
|
0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes byte array to Base32 String.
|
||||||
|
*
|
||||||
|
* @param bytes Bytes to encode.
|
||||||
|
* @return Encoded byte array <code>bytes</code> as a String.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public static String encode(final byte[] bytes) {
|
||||||
|
int i = 0, index = 0, digit = 0;
|
||||||
|
int currByte, nextByte;
|
||||||
|
StringBuffer base32 = new StringBuffer((bytes.length + 7) * 8 / 5);
|
||||||
|
|
||||||
|
while (i < bytes.length) {
|
||||||
|
currByte = (bytes[i] >= 0) ? bytes[i] : (bytes[i] + 256);
|
||||||
|
|
||||||
|
/* Is the current digit going to span a byte boundary? */
|
||||||
|
if (index > 3) {
|
||||||
|
if ((i + 1) < bytes.length) {
|
||||||
|
nextByte = (bytes[i + 1] >= 0) ? bytes[i + 1] : (bytes[i + 1] + 256);
|
||||||
|
} else {
|
||||||
|
nextByte = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
digit = currByte & (0xFF >> index);
|
||||||
|
index = (index + 5) % 8;
|
||||||
|
digit <<= index;
|
||||||
|
digit |= nextByte >> (8 - index);
|
||||||
|
i++;
|
||||||
|
} else {
|
||||||
|
digit = (currByte >> (8 - (index + 5))) & 0x1F;
|
||||||
|
index = (index + 5) % 8;
|
||||||
|
if (index == 0)
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
base32.append(base32Chars.charAt(digit));
|
||||||
|
}
|
||||||
|
|
||||||
|
return base32.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes the given Base32 String to a raw byte array.
|
||||||
|
*
|
||||||
|
* @param base32
|
||||||
|
* @return Decoded <code>base32</code> String as a raw byte array.
|
||||||
|
*/
|
||||||
|
public static byte[] decode(final String base32) {
|
||||||
|
int i, index, lookup, offset, digit;
|
||||||
|
byte[] bytes = new byte[base32.length() * 5 / 8];
|
||||||
|
|
||||||
|
for (i = 0, index = 0, offset = 0; i < base32.length(); i++) {
|
||||||
|
lookup = base32.charAt(i) - '0';
|
||||||
|
|
||||||
|
/* Skip chars outside the lookup table */
|
||||||
|
if (lookup < 0 || lookup >= base32Lookup.length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
digit = base32Lookup[lookup];
|
||||||
|
|
||||||
|
/* If this digit is not in the table, ignore it */
|
||||||
|
if (digit == 0xFF) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index <= 3) {
|
||||||
|
index = (index + 5) % 8;
|
||||||
|
if (index == 0) {
|
||||||
|
bytes[offset] |= digit;
|
||||||
|
offset++;
|
||||||
|
if (offset >= bytes.length)
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
bytes[offset] |= digit << (8 - index);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
index = (index + 5) % 8;
|
||||||
|
bytes[offset] |= (digit >>> index);
|
||||||
|
offset++;
|
||||||
|
|
||||||
|
if (offset >= bytes.length) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bytes[offset] |= digit << (8 - index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
2282
model/api/src/main/java/org/keycloak/models/utils/Base64.java
Executable file
2282
model/api/src/main/java/org/keycloak/models/utils/Base64.java
Executable file
File diff suppressed because it is too large
Load diff
58
model/api/src/main/java/org/keycloak/models/utils/SHAPasswordEncoder.java
Executable file
58
model/api/src/main/java/org/keycloak/models/utils/SHAPasswordEncoder.java
Executable file
|
@ -0,0 +1,58 @@
|
||||||
|
package org.keycloak.models.utils;
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Password that uses SHA to encode passwords. You can always change the SHA strength by specifying a valid
|
||||||
|
* integer when creating a new instance.
|
||||||
|
* </p>
|
||||||
|
* <p>Passwords are returned with a Base64 encoding.</p>
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:psilva@redhat.com">Pedro Silva</a>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class SHAPasswordEncoder {
|
||||||
|
|
||||||
|
private int strength;
|
||||||
|
|
||||||
|
public SHAPasswordEncoder(int strength) {
|
||||||
|
this.strength = strength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String encode(String rawPassword) {
|
||||||
|
MessageDigest messageDigest = getMessageDigest();
|
||||||
|
|
||||||
|
String encodedPassword = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
byte[] digest = messageDigest.digest(rawPassword.getBytes("UTF-8"));
|
||||||
|
encodedPassword = Base64.encodeBytes(digest);
|
||||||
|
} catch (UnsupportedEncodingException e) {
|
||||||
|
throw new RuntimeException("Credential could not be encoded");
|
||||||
|
}
|
||||||
|
|
||||||
|
return encodedPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean verify(String rawPassword, String encodedPassword) {
|
||||||
|
return encode(rawPassword).equals(encodedPassword);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final MessageDigest getMessageDigest() throws IllegalArgumentException {
|
||||||
|
String algorithm = "SHA-" + this.strength;
|
||||||
|
|
||||||
|
try {
|
||||||
|
return MessageDigest.getInstance(algorithm);
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("invalid credential encoding algorithm");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStrength() {
|
||||||
|
return this.strength;
|
||||||
|
}
|
||||||
|
}
|
216
model/api/src/main/java/org/keycloak/models/utils/TimeBasedOTP.java
Executable file
216
model/api/src/main/java/org/keycloak/models/utils/TimeBasedOTP.java
Executable file
|
@ -0,0 +1,216 @@
|
||||||
|
package org.keycloak.models.utils;
|
||||||
|
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.GregorianCalendar;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TOTP: Time-based One-time Password Algorithm Based on http://tools.ietf.org/html/draft-mraihi-totp-timebased-06
|
||||||
|
*
|
||||||
|
* @author anil saldhana
|
||||||
|
* @since Sep 20, 2010
|
||||||
|
*/
|
||||||
|
public class TimeBasedOTP {
|
||||||
|
|
||||||
|
public static final String HMAC_SHA1 = "HmacSHA1";
|
||||||
|
public static final String HMAC_SHA256 = "HmacSHA256";
|
||||||
|
public static final String HMAC_SHA512 = "HmacSHA512";
|
||||||
|
|
||||||
|
public static final String DEFAULT_ALGORITHM = HMAC_SHA1;
|
||||||
|
public static final int DEFAULT_NUMBER_DIGITS = 6;
|
||||||
|
public static final int DEFAULT_INTERVAL_SECONDS = 30;
|
||||||
|
public static final int DEFAULT_DELAY_WINDOW = 1;
|
||||||
|
|
||||||
|
// 0 1 2 3 4 5 6 7 8
|
||||||
|
private static final int[] DIGITS_POWER = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
|
||||||
|
|
||||||
|
private Clock clock;
|
||||||
|
private final String algorithm;
|
||||||
|
private final int numberDigits;
|
||||||
|
private final int delayWindow;
|
||||||
|
|
||||||
|
public TimeBasedOTP() {
|
||||||
|
this(DEFAULT_ALGORITHM, DEFAULT_NUMBER_DIGITS, DEFAULT_INTERVAL_SECONDS, DEFAULT_DELAY_WINDOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param algorithm the encryption algorithm
|
||||||
|
* @param numberDigits the number of digits for tokens
|
||||||
|
* @param timeIntervalInSeconds the number of seconds a token is valid
|
||||||
|
* @param delayWindow the number of previous intervals that should be used to validate tokens.
|
||||||
|
*/
|
||||||
|
public TimeBasedOTP(String algorithm, int numberDigits, int timeIntervalInSeconds, int delayWindow) {
|
||||||
|
this.algorithm = algorithm;
|
||||||
|
this.numberDigits = numberDigits;
|
||||||
|
this.clock = new Clock(timeIntervalInSeconds);
|
||||||
|
this.delayWindow = delayWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Generates a token.</p>
|
||||||
|
*
|
||||||
|
* @param secretKey the secret key to derive the token from.
|
||||||
|
*/
|
||||||
|
public String generate(String secretKey) {
|
||||||
|
long T = this.clock.getCurrentInterval();
|
||||||
|
|
||||||
|
String steps = Long.toHexString(T).toUpperCase();
|
||||||
|
|
||||||
|
// Just get a 16 digit string
|
||||||
|
while (steps.length() < 16)
|
||||||
|
steps = "0" + steps;
|
||||||
|
|
||||||
|
return generateTOTP(secretKey, steps, this.numberDigits, this.algorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method generates an TOTP value for the given set of parameters.
|
||||||
|
*
|
||||||
|
* @param key the shared secret, HEX encoded
|
||||||
|
* @param time a value that reflects a time
|
||||||
|
* @param returnDigits number of digits to return
|
||||||
|
* @param crypto the crypto function to use
|
||||||
|
* @return A numeric String in base 10 that includes {@link truncationDigits} digits
|
||||||
|
* @throws java.security.GeneralSecurityException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public String generateTOTP(String key, String time, int returnDigits, String crypto) {
|
||||||
|
String result = null;
|
||||||
|
byte[] hash;
|
||||||
|
|
||||||
|
// Using the counter
|
||||||
|
// First 8 bytes are for the movingFactor
|
||||||
|
// Complaint with base RFC 4226 (HOTP)
|
||||||
|
while (time.length() < 16)
|
||||||
|
time = "0" + time;
|
||||||
|
|
||||||
|
// Get the HEX in a Byte[]
|
||||||
|
byte[] msg = hexStr2Bytes(time);
|
||||||
|
|
||||||
|
// Adding one byte to get the right conversion
|
||||||
|
// byte[] k = hexStr2Bytes(key);
|
||||||
|
byte[] k = key.getBytes();
|
||||||
|
|
||||||
|
hash = hmac_sha1(crypto, k, msg);
|
||||||
|
|
||||||
|
// put selected bytes into result int
|
||||||
|
int offset = hash[hash.length - 1] & 0xf;
|
||||||
|
|
||||||
|
int binary = ((hash[offset] & 0x7f) << 24) | ((hash[offset + 1] & 0xff) << 16) | ((hash[offset + 2] & 0xff) << 8)
|
||||||
|
| (hash[offset + 3] & 0xff);
|
||||||
|
|
||||||
|
int otp = binary % DIGITS_POWER[returnDigits];
|
||||||
|
|
||||||
|
result = Integer.toString(otp);
|
||||||
|
|
||||||
|
while (result.length() < returnDigits) {
|
||||||
|
result = "0" + result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>Validates a token using a secret key.</p>
|
||||||
|
*
|
||||||
|
* @param token OTP string to validate
|
||||||
|
* @param secret Shared secret
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean validate(String token, byte[] secret) {
|
||||||
|
long currentInterval = this.clock.getCurrentInterval();
|
||||||
|
|
||||||
|
for (int i = this.delayWindow; i >= 0; --i) {
|
||||||
|
String steps = Long.toHexString(currentInterval - i).toUpperCase();
|
||||||
|
|
||||||
|
// Just get a 16 digit string
|
||||||
|
while (steps.length() < 16)
|
||||||
|
steps = "0" + steps;
|
||||||
|
|
||||||
|
String candidate = generateTOTP(new String(secret), steps, this.numberDigits, this.algorithm);
|
||||||
|
|
||||||
|
if (candidate.equals(token)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCalendar(Calendar calendar) {
|
||||||
|
this.clock.setCalendar(calendar);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method uses the JCE to provide the crypto algorithm. HMAC computes a Hashed Message Authentication Code with the
|
||||||
|
* crypto hash algorithm as a parameter.
|
||||||
|
*
|
||||||
|
* @param crypto the crypto algorithm (HmacSHA1, HmacSHA256, HmacSHA512)
|
||||||
|
* @param keyBytes the bytes to use for the HMAC key
|
||||||
|
* @param text the message or text to be authenticated.
|
||||||
|
* @throws java.security.NoSuchAlgorithmException
|
||||||
|
*
|
||||||
|
* @throws java.security.InvalidKeyException
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private byte[] hmac_sha1(String crypto, byte[] keyBytes, byte[] text) {
|
||||||
|
byte[] value;
|
||||||
|
|
||||||
|
try {
|
||||||
|
Mac hmac = Mac.getInstance(crypto);
|
||||||
|
SecretKeySpec macKey = new SecretKeySpec(keyBytes, "RAW");
|
||||||
|
|
||||||
|
hmac.init(macKey);
|
||||||
|
|
||||||
|
value = hmac.doFinal(text);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method converts HEX string to Byte[]
|
||||||
|
*
|
||||||
|
* @param hex the HEX string
|
||||||
|
* @return A byte array
|
||||||
|
*/
|
||||||
|
private byte[] hexStr2Bytes(String hex) {
|
||||||
|
// Adding one byte to get the right conversion
|
||||||
|
// values starting with "0" can be converted
|
||||||
|
byte[] bArray = new BigInteger("10" + hex, 16).toByteArray();
|
||||||
|
|
||||||
|
// Copy all the REAL bytes, not the "first"
|
||||||
|
byte[] ret = new byte[bArray.length - 1];
|
||||||
|
for (int i = 0; i < ret.length; i++)
|
||||||
|
ret[i] = bArray[i + 1];
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Clock {
|
||||||
|
|
||||||
|
private final int interval;
|
||||||
|
private Calendar calendar;
|
||||||
|
|
||||||
|
public Clock(int interval) {
|
||||||
|
this.interval = interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getCurrentInterval() {
|
||||||
|
Calendar currentCalendar = this.calendar;
|
||||||
|
|
||||||
|
if (currentCalendar == null) {
|
||||||
|
currentCalendar = GregorianCalendar.getInstance(TimeZone.getTimeZone("UTC"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return (currentCalendar.getTimeInMillis() / 1000) / this.interval;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCalendar(Calendar calendar) {
|
||||||
|
this.calendar = calendar;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
275
model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java
Executable file
275
model/jpa/src/main/java/org/keycloak/models/jpa/ApplicationAdapter.java
Executable file
|
@ -0,0 +1,275 @@
|
||||||
|
package org.keycloak.models.jpa;
|
||||||
|
|
||||||
|
import org.keycloak.models.ApplicationModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.jpa.entities.ApplicationEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.ApplicationScopeMappingEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.ApplicationUserRoleMappingEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.RoleEntity;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class ApplicationAdapter implements ApplicationModel {
|
||||||
|
|
||||||
|
protected EntityManager em;
|
||||||
|
protected ApplicationEntity application;
|
||||||
|
|
||||||
|
public ApplicationAdapter(EntityManager em, ApplicationEntity application) {
|
||||||
|
this.em = em;
|
||||||
|
this.application = application;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateApplication() {
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserModel getApplicationUser() {
|
||||||
|
return new UserAdapter(application.getApplicationUser());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return application.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return application.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(String name) {
|
||||||
|
application.setName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return application.isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
application.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSurrogateAuthRequired() {
|
||||||
|
return application.isSurrogateAuthRequired();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSurrogateAuthRequired(boolean surrogateAuthRequired) {
|
||||||
|
application.setSurrogateAuthRequired(surrogateAuthRequired);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getManagementUrl() {
|
||||||
|
return application.getManagementUrl();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setManagementUrl(String url) {
|
||||||
|
application.setManagementUrl(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getBaseUrl() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBaseUrl(String url) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RoleModel getRole(String name) {
|
||||||
|
Collection<RoleEntity> roles = application.getRoles();
|
||||||
|
if (roles == null) return null;
|
||||||
|
for (RoleEntity role : roles) {
|
||||||
|
if (role.getName().equals(name)) {
|
||||||
|
return new RoleAdapter(role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RoleModel addRole(String name) {
|
||||||
|
RoleModel role = getRole(name);
|
||||||
|
if (role != null) return role;
|
||||||
|
RoleEntity entity = new RoleEntity();
|
||||||
|
entity.setName(name);
|
||||||
|
em.persist(entity);
|
||||||
|
application.getRoles().add(entity);
|
||||||
|
em.flush();
|
||||||
|
return new RoleAdapter(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RoleModel> getRoles() {
|
||||||
|
ArrayList<RoleModel> list = new ArrayList<RoleModel>();
|
||||||
|
Collection<RoleEntity> roles = application.getRoles();
|
||||||
|
if (roles == null) return list;
|
||||||
|
for (RoleEntity entity : roles) {
|
||||||
|
list.add(new RoleAdapter(entity));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RoleModel getRoleById(String id) {
|
||||||
|
RoleEntity entity = em.find(RoleEntity.class, id);
|
||||||
|
if (entity == null) return null;
|
||||||
|
return new RoleAdapter(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasRole(UserModel user, RoleModel role) {
|
||||||
|
TypedQuery<ApplicationUserRoleMappingEntity> query = getApplicationUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
|
||||||
|
return query.getResultList().size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TypedQuery<ApplicationUserRoleMappingEntity> getApplicationUserRoleMappingEntityTypedQuery(UserAdapter user, RoleAdapter role) {
|
||||||
|
TypedQuery<ApplicationUserRoleMappingEntity> query = em.createNamedQuery("userHasApplicationRole", ApplicationUserRoleMappingEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter)user).getUser());
|
||||||
|
query.setParameter("role", ((RoleAdapter)role).getRole());
|
||||||
|
query.setParameter("application", application);
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void grantRole(UserModel user, RoleModel role) {
|
||||||
|
if (hasRole(user, role)) return;
|
||||||
|
ApplicationUserRoleMappingEntity entity = new ApplicationUserRoleMappingEntity();
|
||||||
|
entity.setApplication(application);
|
||||||
|
entity.setUser(((UserAdapter) user).getUser());
|
||||||
|
entity.setRole(((RoleAdapter)role).getRole());
|
||||||
|
em.persist(entity);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RoleModel> getRoleMappings(UserModel user) {
|
||||||
|
TypedQuery<ApplicationUserRoleMappingEntity> query = em.createNamedQuery("userApplicationMappings", ApplicationUserRoleMappingEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter)user).getUser());
|
||||||
|
query.setParameter("application", application);
|
||||||
|
List<ApplicationUserRoleMappingEntity> entities = query.getResultList();
|
||||||
|
List<RoleModel> roles = new ArrayList<RoleModel>();
|
||||||
|
for (ApplicationUserRoleMappingEntity entity : entities) {
|
||||||
|
roles.add(new RoleAdapter(entity.getRole()));
|
||||||
|
}
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getRoleMappingValues(UserModel user) {
|
||||||
|
TypedQuery<ApplicationUserRoleMappingEntity> query = em.createNamedQuery("userApplicationMappings", ApplicationUserRoleMappingEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter)user).getUser());
|
||||||
|
query.setParameter("application", application);
|
||||||
|
List<ApplicationUserRoleMappingEntity> entities = query.getResultList();
|
||||||
|
Set<String> roles = new HashSet<String>();
|
||||||
|
for (ApplicationUserRoleMappingEntity entity : entities) {
|
||||||
|
roles.add(entity.getRole().getName());
|
||||||
|
}
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteRoleMapping(UserModel user, RoleModel role) {
|
||||||
|
TypedQuery<ApplicationUserRoleMappingEntity> query = getApplicationUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
|
||||||
|
List<ApplicationUserRoleMappingEntity> results = query.getResultList();
|
||||||
|
if (results.size() == 0) return;
|
||||||
|
for (ApplicationUserRoleMappingEntity entity : results) {
|
||||||
|
em.remove(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasRole(UserModel user, String roleName) {
|
||||||
|
RoleModel role = getRole(roleName);
|
||||||
|
if (role == null) return false;
|
||||||
|
return hasRole(user, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addScopeMapping(UserModel agent, String roleName) {
|
||||||
|
RoleModel role = getRole(roleName);
|
||||||
|
if (role == null) throw new RuntimeException("role does not exist");
|
||||||
|
addScopeMapping(agent, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getScopeMappingValues(UserModel agent) {
|
||||||
|
TypedQuery<ApplicationScopeMappingEntity> query = em.createNamedQuery("userApplicationScopeMappings", ApplicationScopeMappingEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter)agent).getUser());
|
||||||
|
query.setParameter("application", application);
|
||||||
|
List<ApplicationScopeMappingEntity> entities = query.getResultList();
|
||||||
|
Set<String> roles = new HashSet<String>();
|
||||||
|
for (ApplicationScopeMappingEntity entity : entities) {
|
||||||
|
roles.add(entity.getRole().getName());
|
||||||
|
}
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RoleModel> getScopeMappings(UserModel agent) {
|
||||||
|
TypedQuery<ApplicationScopeMappingEntity> query = em.createNamedQuery("userApplicationScopeMappings", ApplicationScopeMappingEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter)agent).getUser());
|
||||||
|
query.setParameter("application", application);
|
||||||
|
List<ApplicationScopeMappingEntity> entities = query.getResultList();
|
||||||
|
List<RoleModel> roles = new ArrayList<RoleModel>();
|
||||||
|
for (ApplicationScopeMappingEntity entity : entities) {
|
||||||
|
roles.add(new RoleAdapter(entity.getRole()));
|
||||||
|
}
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addScopeMapping(UserModel agent, RoleModel role) {
|
||||||
|
if (hasScope(agent, role)) return;
|
||||||
|
ApplicationScopeMappingEntity entity = new ApplicationScopeMappingEntity();
|
||||||
|
entity.setApplication(application);
|
||||||
|
entity.setUser(((UserAdapter) agent).getUser());
|
||||||
|
entity.setRole(((RoleAdapter)role).getRole());
|
||||||
|
em.persist(entity);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteScopeMapping(UserModel user, RoleModel role) {
|
||||||
|
TypedQuery<ApplicationScopeMappingEntity> query = getApplicationScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
|
||||||
|
List<ApplicationScopeMappingEntity> results = query.getResultList();
|
||||||
|
if (results.size() == 0) return;
|
||||||
|
for (ApplicationScopeMappingEntity entity : results) {
|
||||||
|
em.remove(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasScope(UserModel user, RoleModel role) {
|
||||||
|
TypedQuery<ApplicationScopeMappingEntity> query = getApplicationScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
|
||||||
|
return query.getResultList().size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected TypedQuery<ApplicationScopeMappingEntity> getApplicationScopeMappingQuery(UserAdapter user, RoleAdapter role) {
|
||||||
|
TypedQuery<ApplicationScopeMappingEntity> query = em.createNamedQuery("userHasApplicationScope", ApplicationScopeMappingEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter)user).getUser());
|
||||||
|
query.setParameter("role", ((RoleAdapter)role).getRole());
|
||||||
|
query.setParameter("application", application);
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
74
model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
Executable file
74
model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakSession.java
Executable file
|
@ -0,0 +1,74 @@
|
||||||
|
package org.keycloak.models.jpa;
|
||||||
|
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakTransaction;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.jpa.entities.RealmEntity;
|
||||||
|
import org.keycloak.models.utils.KeycloakSessionUtils;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class JpaKeycloakSession implements KeycloakSession {
|
||||||
|
protected EntityManager em;
|
||||||
|
|
||||||
|
public JpaKeycloakSession(EntityManager em) {
|
||||||
|
this.em = em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeycloakTransaction getTransaction() {
|
||||||
|
return new JpaKeycloakTransaction(em);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RealmModel createRealm(String name) {
|
||||||
|
return createRealm(KeycloakSessionUtils.generateId(), name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RealmModel createRealm(String id, String name) {
|
||||||
|
RealmEntity realm = new RealmEntity();
|
||||||
|
realm.setName(name);
|
||||||
|
realm.setId(id);
|
||||||
|
em.persist(realm);
|
||||||
|
em.flush();
|
||||||
|
return new RealmAdapter(em, realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RealmModel getRealm(String id) {
|
||||||
|
RealmEntity realm = em.find(RealmEntity.class, id);
|
||||||
|
if (realm == null) return null;
|
||||||
|
return new RealmAdapter(em, realm);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RealmModel> getRealms(UserModel admin) {
|
||||||
|
TypedQuery<RealmEntity> query = em.createQuery("select r from RealmEntity r", RealmEntity.class);
|
||||||
|
List<RealmEntity> entities = query.getResultList();
|
||||||
|
List<RealmModel> realms = new ArrayList<RealmModel>();
|
||||||
|
for (RealmEntity entity : entities) {
|
||||||
|
realms.add(new RealmAdapter(em, entity));
|
||||||
|
}
|
||||||
|
return realms;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteRealm(RealmModel realm) {
|
||||||
|
throw new RuntimeException("Not Implemented Yet");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
if (em.getTransaction().isActive()) em.getTransaction().rollback();
|
||||||
|
if (em.isOpen()) em.close();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.keycloak.models.jpa;
|
||||||
|
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class JpaKeycloakSessionFactory implements KeycloakSessionFactory {
|
||||||
|
protected EntityManagerFactory factory;
|
||||||
|
|
||||||
|
public JpaKeycloakSessionFactory(EntityManagerFactory factory) {
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public KeycloakSession createSession() {
|
||||||
|
return new JpaKeycloakSession(factory.createEntityManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() {
|
||||||
|
factory.close();
|
||||||
|
}
|
||||||
|
}
|
48
model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakTransaction.java
Executable file
48
model/jpa/src/main/java/org/keycloak/models/jpa/JpaKeycloakTransaction.java
Executable file
|
@ -0,0 +1,48 @@
|
||||||
|
package org.keycloak.models.jpa;
|
||||||
|
|
||||||
|
import org.keycloak.models.KeycloakTransaction;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class JpaKeycloakTransaction implements KeycloakTransaction {
|
||||||
|
|
||||||
|
protected EntityManager em;
|
||||||
|
|
||||||
|
public JpaKeycloakTransaction(EntityManager em) {
|
||||||
|
this.em = em;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void begin() {
|
||||||
|
em.getTransaction().begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void commit() {
|
||||||
|
em.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void rollback() {
|
||||||
|
em.getTransaction().rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRollbackOnly() {
|
||||||
|
em.getTransaction().setRollbackOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean getRollbackOnly() {
|
||||||
|
return em.getTransaction().getRollbackOnly();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isActive() {
|
||||||
|
return em.getTransaction().isActive();
|
||||||
|
}
|
||||||
|
}
|
20
model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java
Executable file
20
model/jpa/src/main/java/org/keycloak/models/jpa/JpaModelProvider.java
Executable file
|
@ -0,0 +1,20 @@
|
||||||
|
package org.keycloak.models.jpa;
|
||||||
|
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.models.ModelProvider;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
import javax.persistence.Persistence;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class JpaModelProvider implements ModelProvider {
|
||||||
|
@Override
|
||||||
|
public KeycloakSessionFactory createFactory() {
|
||||||
|
EntityManagerFactory emf = Persistence.createEntityManagerFactory("jpa-keycloak-identity-store");
|
||||||
|
return new JpaKeycloakSessionFactory(emf);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
32
model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java
Executable file
32
model/jpa/src/main/java/org/keycloak/models/jpa/OAuthClientAdapter.java
Executable file
|
@ -0,0 +1,32 @@
|
||||||
|
package org.keycloak.models.jpa;
|
||||||
|
|
||||||
|
import org.keycloak.models.OAuthClientModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.jpa.entities.OAuthClientEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class OAuthClientAdapter implements OAuthClientModel {
|
||||||
|
protected OAuthClientEntity entity;
|
||||||
|
|
||||||
|
public OAuthClientAdapter(OAuthClientEntity entity) {
|
||||||
|
this.entity = entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OAuthClientEntity getEntity() {
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return entity.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserModel getOAuthAgent() {
|
||||||
|
return new UserAdapter(entity.getAgent());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
954
model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
Executable file
954
model/jpa/src/main/java/org/keycloak/models/jpa/RealmAdapter.java
Executable file
|
@ -0,0 +1,954 @@
|
||||||
|
package org.keycloak.models.jpa;
|
||||||
|
|
||||||
|
import org.bouncycastle.openssl.PEMWriter;
|
||||||
|
import org.keycloak.PemUtils;
|
||||||
|
import org.keycloak.models.ApplicationModel;
|
||||||
|
import org.keycloak.models.OAuthClientModel;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RequiredCredentialModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.SocialLinkModel;
|
||||||
|
import org.keycloak.models.UserCredentialModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.jpa.entities.ApplicationEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.CredentialEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.OAuthClientEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.RealmEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.RealmScopeMappingEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.RealmUserRoleMappingEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.RequiredCredentialEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.RoleEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.SocialLinkEntity;
|
||||||
|
import org.keycloak.models.jpa.entities.UserEntity;
|
||||||
|
import org.keycloak.models.utils.SHAPasswordEncoder;
|
||||||
|
import org.keycloak.models.utils.TimeBasedOTP;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.TypedQuery;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class RealmAdapter implements RealmModel {
|
||||||
|
protected RealmEntity realm;
|
||||||
|
protected EntityManager em;
|
||||||
|
protected volatile transient PublicKey publicKey;
|
||||||
|
protected volatile transient PrivateKey privateKey;
|
||||||
|
|
||||||
|
public RealmAdapter(EntityManager em, RealmEntity realm) {
|
||||||
|
this.em = em;
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return realm.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return realm.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(String name) {
|
||||||
|
realm.setName(name);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return realm.isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
realm.setEnabled(enabled);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSslNotRequired() {
|
||||||
|
return realm.isSslNotRequired();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSslNotRequired(boolean sslNotRequired) {
|
||||||
|
realm.setSslNotRequired(sslNotRequired);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCookieLoginAllowed() {
|
||||||
|
return realm.isCookieLoginAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setCookieLoginAllowed(boolean cookieLoginAllowed) {
|
||||||
|
realm.setCookieLoginAllowed(cookieLoginAllowed);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isRegistrationAllowed() {
|
||||||
|
return realm.isRegistrationAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRegistrationAllowed(boolean registrationAllowed) {
|
||||||
|
realm.setRegistrationAllowed(registrationAllowed);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isVerifyEmail() {
|
||||||
|
return realm.isVerifyEmail();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setVerifyEmail(boolean verifyEmail) {
|
||||||
|
realm.setVerifyEmail(verifyEmail);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isResetPasswordAllowed() {
|
||||||
|
return realm.isResetPasswordAllowed();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
|
||||||
|
realm.setResetPasswordAllowed(resetPasswordAllowed);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getTokenLifespan() {
|
||||||
|
return realm.getTokenLifespan();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTokenLifespan(int tokenLifespan) {
|
||||||
|
realm.setTokenLifespan(tokenLifespan);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAccessCodeLifespan() {
|
||||||
|
return realm.getAccessCodeLifespan();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAccessCodeLifespan(int accessCodeLifespan) {
|
||||||
|
realm.setAccessCodeLifespan(accessCodeLifespan);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getAccessCodeLifespanUserAction() {
|
||||||
|
return realm.getAccessCodeLifespanUserAction();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
|
||||||
|
realm.setAccessCodeLifespanUserAction(accessCodeLifespanUserAction);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPublicKeyPem() {
|
||||||
|
return realm.getPublicKeyPem();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPublicKeyPem(String publicKeyPem) {
|
||||||
|
realm.setPublicKeyPem(publicKeyPem);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPrivateKeyPem() {
|
||||||
|
return realm.getPrivateKeyPem();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPrivateKeyPem(String privateKeyPem) {
|
||||||
|
realm.setPrivateKeyPem(privateKeyPem);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PublicKey getPublicKey() {
|
||||||
|
if (publicKey != null) return publicKey;
|
||||||
|
String pem = getPublicKeyPem();
|
||||||
|
if (pem != null) {
|
||||||
|
try {
|
||||||
|
publicKey = PemUtils.decodePublicKey(pem);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPublicKey(PublicKey publicKey) {
|
||||||
|
this.publicKey = publicKey;
|
||||||
|
StringWriter writer = new StringWriter();
|
||||||
|
PEMWriter pemWriter = new PEMWriter(writer);
|
||||||
|
try {
|
||||||
|
pemWriter.writeObject(publicKey);
|
||||||
|
pemWriter.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
String s = writer.toString();
|
||||||
|
setPublicKeyPem(PemUtils.removeBeginEnd(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PrivateKey getPrivateKey() {
|
||||||
|
if (privateKey != null) return privateKey;
|
||||||
|
String pem = getPrivateKeyPem();
|
||||||
|
if (pem != null) {
|
||||||
|
try {
|
||||||
|
privateKey = PemUtils.decodePrivateKey(pem);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPrivateKey(PrivateKey privateKey) {
|
||||||
|
this.privateKey = privateKey;
|
||||||
|
StringWriter writer = new StringWriter();
|
||||||
|
PEMWriter pemWriter = new PEMWriter(writer);
|
||||||
|
try {
|
||||||
|
pemWriter.writeObject(privateKey);
|
||||||
|
pemWriter.flush();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
String s = writer.toString();
|
||||||
|
setPrivateKeyPem(PemUtils.removeBeginEnd(s));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected RequiredCredentialModel initRequiredCredentialModel(String type) {
|
||||||
|
RequiredCredentialModel model = RequiredCredentialModel.BUILT_IN.get(type);
|
||||||
|
if (model == null) {
|
||||||
|
throw new RuntimeException("Unknown credential type " + type);
|
||||||
|
}
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRequiredCredential(String type) {
|
||||||
|
RequiredCredentialModel model = initRequiredCredentialModel(type);
|
||||||
|
addRequiredCredential(model);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRequiredCredential(RequiredCredentialModel model) {
|
||||||
|
RequiredCredentialEntity entity = new RequiredCredentialEntity();
|
||||||
|
entity.setInput(model.isInput());
|
||||||
|
entity.setSecret(model.isSecret());
|
||||||
|
entity.setType(model.getType());
|
||||||
|
entity.setFormLabel(model.getFormLabel());
|
||||||
|
em.persist(entity);
|
||||||
|
realm.getRequiredCredentials().add(entity);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateRequiredCredentials(Set<String> creds) {
|
||||||
|
Collection<RequiredCredentialEntity> relationships = realm.getRequiredCredentials();
|
||||||
|
if (relationships == null) relationships = new ArrayList<RequiredCredentialEntity>();
|
||||||
|
|
||||||
|
Set<String> already = new HashSet<String>();
|
||||||
|
List<RequiredCredentialEntity> remove = new ArrayList<RequiredCredentialEntity>();
|
||||||
|
for (RequiredCredentialEntity rel : relationships) {
|
||||||
|
if (!creds.contains(rel.getType())) {
|
||||||
|
remove.add(rel);
|
||||||
|
} else {
|
||||||
|
already.add(rel.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (RequiredCredentialEntity entity : remove) {
|
||||||
|
relationships.remove(entity);
|
||||||
|
em.remove(entity);
|
||||||
|
}
|
||||||
|
for (String cred : creds) {
|
||||||
|
if (!already.contains(cred)) {
|
||||||
|
addRequiredCredential(cred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RequiredCredentialModel> getRequiredCredentials() {
|
||||||
|
List<RequiredCredentialModel> requiredCredentialModels = new ArrayList<RequiredCredentialModel>();
|
||||||
|
Collection<RequiredCredentialEntity> entities = realm.getRequiredCredentials();
|
||||||
|
if (entities == null) return requiredCredentialModels;
|
||||||
|
for (RequiredCredentialEntity entity : entities) {
|
||||||
|
RequiredCredentialModel model = new RequiredCredentialModel();
|
||||||
|
model.setFormLabel(entity.getFormLabel());
|
||||||
|
model.setType(entity.getType());
|
||||||
|
model.setSecret(entity.isSecret());
|
||||||
|
model.setInput(entity.isInput());
|
||||||
|
requiredCredentialModels.add(model);
|
||||||
|
}
|
||||||
|
return requiredCredentialModels; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RequiredCredentialModel> getRequiredApplicationCredentials() {
|
||||||
|
List<RequiredCredentialModel> requiredCredentialModels = new ArrayList<RequiredCredentialModel>();
|
||||||
|
Collection<RequiredCredentialEntity> entities = realm.getRequiredApplicationCredentials();
|
||||||
|
if (entities == null) return requiredCredentialModels;
|
||||||
|
for (RequiredCredentialEntity entity : entities) {
|
||||||
|
RequiredCredentialModel model = new RequiredCredentialModel();
|
||||||
|
model.setFormLabel(entity.getFormLabel());
|
||||||
|
model.setType(entity.getType());
|
||||||
|
model.setSecret(entity.isSecret());
|
||||||
|
model.setInput(entity.isInput());
|
||||||
|
requiredCredentialModels.add(model);
|
||||||
|
}
|
||||||
|
return requiredCredentialModels; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RequiredCredentialModel> getRequiredOAuthClientCredentials() {
|
||||||
|
List<RequiredCredentialModel> requiredCredentialModels = new ArrayList<RequiredCredentialModel>();
|
||||||
|
Collection<RequiredCredentialEntity> entities = realm.getRequiredOAuthClientCredentials();
|
||||||
|
if (entities == null) return requiredCredentialModels;
|
||||||
|
for (RequiredCredentialEntity entity : entities) {
|
||||||
|
RequiredCredentialModel model = new RequiredCredentialModel();
|
||||||
|
model.setFormLabel(entity.getFormLabel());
|
||||||
|
model.setType(entity.getType());
|
||||||
|
model.setSecret(entity.isSecret());
|
||||||
|
model.setInput(entity.isInput());
|
||||||
|
requiredCredentialModels.add(model);
|
||||||
|
}
|
||||||
|
return requiredCredentialModels; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRequiredOAuthClientCredential(RequiredCredentialModel model) {
|
||||||
|
RequiredCredentialEntity entity = new RequiredCredentialEntity();
|
||||||
|
entity.setInput(model.isInput());
|
||||||
|
entity.setSecret(model.isSecret());
|
||||||
|
entity.setType(model.getType());
|
||||||
|
entity.setFormLabel(model.getFormLabel());
|
||||||
|
em.persist(entity);
|
||||||
|
realm.getRequiredOAuthClientCredentials().add(entity);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRequiredOAuthClientCredential(String type) {
|
||||||
|
RequiredCredentialModel model = initRequiredCredentialModel(type);
|
||||||
|
addRequiredOAuthClientCredential(model);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRequiredResourceCredential(RequiredCredentialModel model) {
|
||||||
|
RequiredCredentialEntity entity = new RequiredCredentialEntity();
|
||||||
|
entity.setInput(model.isInput());
|
||||||
|
entity.setSecret(model.isSecret());
|
||||||
|
entity.setType(model.getType());
|
||||||
|
entity.setFormLabel(model.getFormLabel());
|
||||||
|
em.persist(entity);
|
||||||
|
realm.getRequiredApplicationCredentials().add(entity);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRequiredResourceCredential(String type) {
|
||||||
|
RequiredCredentialModel model = initRequiredCredentialModel(type);
|
||||||
|
addRequiredResourceCredential(model);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateRequiredOAuthClientCredentials(Set<String> creds) {
|
||||||
|
Collection<RequiredCredentialEntity> relationships = realm.getRequiredOAuthClientCredentials();
|
||||||
|
if (relationships == null) relationships = new ArrayList<RequiredCredentialEntity>();
|
||||||
|
|
||||||
|
Set<String> already = new HashSet<String>();
|
||||||
|
List<RequiredCredentialEntity> remove = new ArrayList<RequiredCredentialEntity>();
|
||||||
|
for (RequiredCredentialEntity rel : relationships) {
|
||||||
|
if (!creds.contains(rel.getType())) {
|
||||||
|
remove.add(rel);
|
||||||
|
} else {
|
||||||
|
already.add(rel.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (RequiredCredentialEntity entity : remove) {
|
||||||
|
relationships.remove(entity);
|
||||||
|
em.remove(entity);
|
||||||
|
}
|
||||||
|
for (String cred : creds) {
|
||||||
|
if (!already.contains(cred)) {
|
||||||
|
addRequiredOAuthClientCredential(cred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateRequiredApplicationCredentials(Set<String> creds) {
|
||||||
|
Collection<RequiredCredentialEntity> relationships = realm.getRequiredApplicationCredentials();
|
||||||
|
if (relationships == null) relationships = new ArrayList<RequiredCredentialEntity>();
|
||||||
|
|
||||||
|
Set<String> already = new HashSet<String>();
|
||||||
|
List<RequiredCredentialEntity> remove = new ArrayList<RequiredCredentialEntity>();
|
||||||
|
for (RequiredCredentialEntity rel : relationships) {
|
||||||
|
if (!creds.contains(rel.getType())) {
|
||||||
|
remove.add(rel);
|
||||||
|
} else {
|
||||||
|
already.add(rel.getType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (RequiredCredentialEntity entity : remove) {
|
||||||
|
relationships.remove(entity);
|
||||||
|
em.remove(entity);
|
||||||
|
}
|
||||||
|
for (String cred : creds) {
|
||||||
|
if (!already.contains(cred)) {
|
||||||
|
addRequiredResourceCredential(cred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserModel getUser(String name) {
|
||||||
|
TypedQuery<UserEntity> query = em.createNamedQuery("getRealmUserByLoginName", UserEntity.class);
|
||||||
|
query.setParameter("loginName", name);
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
List<UserEntity> results = query.getResultList();
|
||||||
|
if (results.size() == 0) return null;
|
||||||
|
return new UserAdapter(results.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserModel addUser(String username) {
|
||||||
|
UserEntity entity = new UserEntity();
|
||||||
|
entity.setLoginName(username);
|
||||||
|
entity.setRealm(realm);
|
||||||
|
em.persist(entity);
|
||||||
|
em.flush();
|
||||||
|
return new UserAdapter(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RoleModel> getDefaultRoles() {
|
||||||
|
Collection<RoleEntity> entities = realm.getDefaultRoles();
|
||||||
|
List<RoleModel> roles = new ArrayList<RoleModel>();
|
||||||
|
if (entities == null) return roles;
|
||||||
|
for (RoleEntity entity : entities) {
|
||||||
|
roles.add(new RoleAdapter(entity));
|
||||||
|
}
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addDefaultRole(String name) {
|
||||||
|
RoleModel role = getRole(name);
|
||||||
|
if (role == null) {
|
||||||
|
role = addRole(name);
|
||||||
|
}
|
||||||
|
Collection<RoleEntity> entities = realm.getDefaultRoles();
|
||||||
|
for (RoleEntity entity : entities) {
|
||||||
|
if (entity.getId().equals(role.getId())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entities.add(((RoleAdapter) role).getRole());
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean contains(String str, String[] array) {
|
||||||
|
for (String s : array) {
|
||||||
|
if (str.equals(s)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateDefaultRoles(String[] defaultRoles) {
|
||||||
|
Collection<RoleEntity> entities = realm.getDefaultRoles();
|
||||||
|
Set<String> already = new HashSet<String>();
|
||||||
|
List<RoleEntity> remove = new ArrayList<RoleEntity>();
|
||||||
|
for (RoleEntity rel : entities) {
|
||||||
|
if (!contains(rel.getName(), defaultRoles)) {
|
||||||
|
remove.add(rel);
|
||||||
|
} else {
|
||||||
|
already.add(rel.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (RoleEntity entity : remove) {
|
||||||
|
entities.remove(entity);
|
||||||
|
em.remove(entity);
|
||||||
|
}
|
||||||
|
for (String roleName : defaultRoles) {
|
||||||
|
if (!already.contains(roleName)) {
|
||||||
|
addDefaultRole(roleName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, ApplicationModel> getApplicationNameMap() {
|
||||||
|
Map<String, ApplicationModel> map = new HashMap<String, ApplicationModel>();
|
||||||
|
for (ApplicationModel app : getApplications()) {
|
||||||
|
map.put(app.getName(), app);
|
||||||
|
}
|
||||||
|
return map; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ApplicationModel> getApplications() {
|
||||||
|
List<ApplicationModel> list = new ArrayList<ApplicationModel>();
|
||||||
|
if (realm.getApplications() == null) return list;
|
||||||
|
for (ApplicationEntity entity : realm.getApplications()) {
|
||||||
|
list.add(new ApplicationAdapter(em, entity));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApplicationModel addApplication(String name) {
|
||||||
|
ApplicationEntity applicationData = new ApplicationEntity();
|
||||||
|
UserEntity user = new UserEntity();
|
||||||
|
user.setLoginName(name);
|
||||||
|
user.setRealm(realm);
|
||||||
|
user.setEnabled(true);
|
||||||
|
em.persist(user);
|
||||||
|
applicationData.setApplicationUser(user);
|
||||||
|
applicationData.setName(name);
|
||||||
|
realm.getApplications().add(applicationData);
|
||||||
|
em.persist(applicationData);
|
||||||
|
em.flush();
|
||||||
|
ApplicationModel resource = new ApplicationAdapter(em, applicationData);
|
||||||
|
resource.addRole("*");
|
||||||
|
resource.addScopeMapping(new UserAdapter(user), "*");
|
||||||
|
em.flush();
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ApplicationModel getApplicationById(String id) {
|
||||||
|
ApplicationEntity app = em.find(ApplicationEntity.class, id);
|
||||||
|
if (app == null) return null;
|
||||||
|
return new ApplicationAdapter(em, app);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public UserModel getUserBySocialLink(SocialLinkModel socialLink) {
|
||||||
|
TypedQuery<UserEntity> query = em.createNamedQuery("findUserByLinkAndRealm", UserEntity.class);
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
query.setParameter("socialProvider", socialLink.getSocialProvider());
|
||||||
|
query.setParameter("socialUsername", socialLink.getSocialUsername());
|
||||||
|
List<UserEntity> results = query.getResultList();
|
||||||
|
if (results.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
} else if (results.size() > 1) {
|
||||||
|
throw new IllegalStateException("More results found for socialProvider=" + socialLink.getSocialProvider() +
|
||||||
|
", socialUsername=" + socialLink.getSocialUsername() + ", results=" + results);
|
||||||
|
} else {
|
||||||
|
UserEntity user = results.get(0);
|
||||||
|
return new UserAdapter(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<SocialLinkModel> getSocialLinks(UserModel user) {
|
||||||
|
TypedQuery<SocialLinkEntity> query = em.createNamedQuery("findSocialLinkByUser", SocialLinkEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter) user).getUser());
|
||||||
|
List<SocialLinkEntity> results = query.getResultList();
|
||||||
|
Set<SocialLinkModel> set = new HashSet<SocialLinkModel>();
|
||||||
|
for (SocialLinkEntity entity : results) {
|
||||||
|
set.add(new SocialLinkModel(entity.getSocialProvider(), entity.getSocialUsername()));
|
||||||
|
}
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addSocialLink(UserModel user, SocialLinkModel socialLink) {
|
||||||
|
SocialLinkEntity entity = new SocialLinkEntity();
|
||||||
|
entity.setRealm(realm);
|
||||||
|
entity.setSocialProvider(socialLink.getSocialProvider());
|
||||||
|
entity.setSocialUsername(socialLink.getSocialUsername());
|
||||||
|
entity.setUser(((UserAdapter) user).getUser());
|
||||||
|
em.persist(entity);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeSocialLink(UserModel user, SocialLinkModel socialLink) {
|
||||||
|
TypedQuery<SocialLinkEntity> query = em.createNamedQuery("findSocialLinkByAll", SocialLinkEntity.class);
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
query.setParameter("user", ((UserAdapter) user).getUser());
|
||||||
|
query.setParameter("socialProvider", socialLink.getSocialProvider());
|
||||||
|
query.setParameter("socialUsername", socialLink.getSocialUsername());
|
||||||
|
List<SocialLinkEntity> results = query.getResultList();
|
||||||
|
for (SocialLinkEntity entity : results) em.remove(entity);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isSocial() {
|
||||||
|
return realm.isSocial();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSocial(boolean social) {
|
||||||
|
realm.setSocial(social);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAutomaticRegistrationAfterSocialLogin() {
|
||||||
|
return realm.isAutomaticRegistrationAfterSocialLogin();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAutomaticRegistrationAfterSocialLogin(boolean automaticRegistrationAfterSocialLogin) {
|
||||||
|
realm.setAutomaticRegistrationAfterSocialLogin(automaticRegistrationAfterSocialLogin);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<UserModel> searchForUserByAttributes(Map<String, String> attributes) {
|
||||||
|
StringBuilder builder = new StringBuilder("select u from UserEntity u");
|
||||||
|
boolean first = true;
|
||||||
|
for (Map.Entry<String, String> entry : attributes.entrySet()) {
|
||||||
|
String attribute = null;
|
||||||
|
if (entry.getKey().equals(UserModel.LOGIN_NAME)) {
|
||||||
|
attribute = "loginName";
|
||||||
|
} else if (entry.getKey().equalsIgnoreCase(UserModel.FIRST_NAME)) {
|
||||||
|
attribute = "firstName";
|
||||||
|
} else if (entry.getKey().equalsIgnoreCase(UserModel.LAST_NAME)) {
|
||||||
|
attribute = "lastName";
|
||||||
|
} else if (entry.getKey().equalsIgnoreCase(UserModel.EMAIL)) {
|
||||||
|
attribute = "email";
|
||||||
|
}
|
||||||
|
if (attribute == null) continue;
|
||||||
|
if (first) {
|
||||||
|
first = false;
|
||||||
|
builder.append(" where ");
|
||||||
|
} else {
|
||||||
|
builder.append(" and ");
|
||||||
|
}
|
||||||
|
builder.append(attribute).append("='").append(entry.getValue()).append("'");
|
||||||
|
}
|
||||||
|
TypedQuery<UserEntity> query = em.createQuery(builder.toString(), UserEntity.class);
|
||||||
|
List<UserEntity> results = query.getResultList();
|
||||||
|
List<UserModel> users = new ArrayList<UserModel>();
|
||||||
|
for (UserEntity entity : results) users.add(new UserAdapter(entity));
|
||||||
|
return users;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OAuthClientModel addOAuthClient(String name) {
|
||||||
|
OAuthClientEntity data = new OAuthClientEntity();
|
||||||
|
UserEntity user = new UserEntity();
|
||||||
|
user.setLoginName(name);
|
||||||
|
user.setRealm(realm);
|
||||||
|
user.setEnabled(true);
|
||||||
|
em.persist(user);
|
||||||
|
data.setAgent(user);
|
||||||
|
data.setName(name);
|
||||||
|
data.setRealm(realm);
|
||||||
|
em.persist(data);
|
||||||
|
em.flush();
|
||||||
|
return new OAuthClientAdapter(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public OAuthClientModel getOAuthClient(String name) {
|
||||||
|
TypedQuery<OAuthClientEntity> query = em.createNamedQuery("findOAuthClientByUser", OAuthClientEntity.class);
|
||||||
|
query.setParameter("name", name);
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
List<OAuthClientEntity> entities = query.getResultList();
|
||||||
|
if (entities.size() == 0) return null;
|
||||||
|
return new OAuthClientAdapter(entities.get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<OAuthClientModel> getOAuthClients() {
|
||||||
|
TypedQuery<OAuthClientEntity> query = em.createNamedQuery("findOAuthClientByRealm", OAuthClientEntity.class);
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
List<OAuthClientEntity> entities = query.getResultList();
|
||||||
|
List<OAuthClientModel> list = new ArrayList<OAuthClientModel>();
|
||||||
|
for (OAuthClientEntity entity : entities) list.add(new OAuthClientAdapter(entity));
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getSmtpConfig() {
|
||||||
|
return realm.getSmtpConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSmtpConfig(Map<String, String> smtpConfig) {
|
||||||
|
realm.setSmtpConfig(smtpConfig);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getSocialConfig() {
|
||||||
|
return realm.getSocialConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSocialConfig(Map<String, String> socialConfig) {
|
||||||
|
realm.setSocialConfig(socialConfig);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RoleModel getRole(String name) {
|
||||||
|
Collection<RoleEntity> roles = realm.getRoles();
|
||||||
|
if (roles == null) return null;
|
||||||
|
for (RoleEntity role : roles) {
|
||||||
|
if (role.getName().equals(name)) {
|
||||||
|
return new RoleAdapter(role);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RoleModel addRole(String name) {
|
||||||
|
RoleModel role = getRole(name);
|
||||||
|
if (role != null) return role;
|
||||||
|
RoleEntity entity = new RoleEntity();
|
||||||
|
entity.setName(name);
|
||||||
|
em.persist(entity);
|
||||||
|
realm.getRoles().add(entity);
|
||||||
|
em.flush();
|
||||||
|
return new RoleAdapter(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RoleModel> getRoles() {
|
||||||
|
ArrayList<RoleModel> list = new ArrayList<RoleModel>();
|
||||||
|
Collection<RoleEntity> roles = realm.getRoles();
|
||||||
|
if (roles == null) return list;
|
||||||
|
for (RoleEntity entity : roles) {
|
||||||
|
list.add(new RoleAdapter(entity));
|
||||||
|
}
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RoleModel getRoleById(String id) {
|
||||||
|
RoleEntity entity = em.find(RoleEntity.class, id);
|
||||||
|
if (entity == null) return null;
|
||||||
|
return new RoleAdapter(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasRole(UserModel user, RoleModel role) {
|
||||||
|
TypedQuery<RealmUserRoleMappingEntity> query = getRealmUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
|
||||||
|
return query.getResultList().size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TypedQuery<RealmUserRoleMappingEntity> getRealmUserRoleMappingEntityTypedQuery(UserAdapter user, RoleAdapter role) {
|
||||||
|
TypedQuery<RealmUserRoleMappingEntity> query = em.createNamedQuery("userHasRealmRole", RealmUserRoleMappingEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter)user).getUser());
|
||||||
|
query.setParameter("role", ((RoleAdapter)role).getRole());
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void grantRole(UserModel user, RoleModel role) {
|
||||||
|
if (hasRole(user, role)) return;
|
||||||
|
RealmUserRoleMappingEntity entity = new RealmUserRoleMappingEntity();
|
||||||
|
entity.setRealm(realm);
|
||||||
|
entity.setUser(((UserAdapter) user).getUser());
|
||||||
|
entity.setRole(((RoleAdapter)role).getRole());
|
||||||
|
em.persist(entity);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RoleModel> getRoleMappings(UserModel user) {
|
||||||
|
TypedQuery<RealmUserRoleMappingEntity> query = em.createNamedQuery("userRealmMappings", RealmUserRoleMappingEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter)user).getUser());
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
List<RealmUserRoleMappingEntity> entities = query.getResultList();
|
||||||
|
List<RoleModel> roles = new ArrayList<RoleModel>();
|
||||||
|
for (RealmUserRoleMappingEntity entity : entities) {
|
||||||
|
roles.add(new RoleAdapter(entity.getRole()));
|
||||||
|
}
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getRoleMappingValues(UserModel user) {
|
||||||
|
TypedQuery<RealmUserRoleMappingEntity> query = em.createNamedQuery("userRealmMappings", RealmUserRoleMappingEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter)user).getUser());
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
List<RealmUserRoleMappingEntity> entities = query.getResultList();
|
||||||
|
Set<String> roles = new HashSet<String>();
|
||||||
|
for (RealmUserRoleMappingEntity entity : entities) {
|
||||||
|
roles.add(entity.getRole().getName());
|
||||||
|
}
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteRoleMapping(UserModel user, RoleModel role) {
|
||||||
|
TypedQuery<RealmUserRoleMappingEntity> query = getRealmUserRoleMappingEntityTypedQuery((UserAdapter) user, (RoleAdapter) role);
|
||||||
|
List<RealmUserRoleMappingEntity> results = query.getResultList();
|
||||||
|
if (results.size() == 0) return;
|
||||||
|
for (RealmUserRoleMappingEntity entity : results) {
|
||||||
|
em.remove(entity);
|
||||||
|
}
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasRole(UserModel user, String roleName) {
|
||||||
|
RoleModel role = getRole(roleName);
|
||||||
|
if (role == null) return false;
|
||||||
|
return hasRole(user, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addScopeMapping(UserModel agent, String roleName) {
|
||||||
|
RoleModel role = getRole(roleName);
|
||||||
|
if (role == null) throw new RuntimeException("role does not exist");
|
||||||
|
addScopeMapping(agent, role);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getScopeMappingValues(UserModel agent) {
|
||||||
|
TypedQuery<RealmScopeMappingEntity> query = em.createNamedQuery("userRealmScopeMappings", RealmScopeMappingEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter)agent).getUser());
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
List<RealmScopeMappingEntity> entities = query.getResultList();
|
||||||
|
Set<String> roles = new HashSet<String>();
|
||||||
|
for (RealmScopeMappingEntity entity : entities) {
|
||||||
|
roles.add(entity.getRole().getName());
|
||||||
|
}
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<RoleModel> getScopeMappings(UserModel agent) {
|
||||||
|
TypedQuery<RealmScopeMappingEntity> query = em.createNamedQuery("userRealmScopeMappings", RealmScopeMappingEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter)agent).getUser());
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
List<RealmScopeMappingEntity> entities = query.getResultList();
|
||||||
|
List<RoleModel> roles = new ArrayList<RoleModel>();
|
||||||
|
for (RealmScopeMappingEntity entity : entities) {
|
||||||
|
roles.add(new RoleAdapter(entity.getRole()));
|
||||||
|
}
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addScopeMapping(UserModel agent, RoleModel role) {
|
||||||
|
if (hasScope(agent, role)) return;
|
||||||
|
RealmScopeMappingEntity entity = new RealmScopeMappingEntity();
|
||||||
|
entity.setRealm(realm);
|
||||||
|
entity.setUser(((UserAdapter) agent).getUser());
|
||||||
|
entity.setRole(((RoleAdapter)role).getRole());
|
||||||
|
em.persist(entity);
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void deleteScopeMapping(UserModel user, RoleModel role) {
|
||||||
|
TypedQuery<RealmScopeMappingEntity> query = getRealmScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
|
||||||
|
List<RealmScopeMappingEntity> results = query.getResultList();
|
||||||
|
if (results.size() == 0) return;
|
||||||
|
for (RealmScopeMappingEntity entity : results) {
|
||||||
|
em.remove(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasScope(UserModel user, RoleModel role) {
|
||||||
|
TypedQuery<RealmScopeMappingEntity> query = getRealmScopeMappingQuery((UserAdapter) user, (RoleAdapter) role);
|
||||||
|
return query.getResultList().size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected TypedQuery<RealmScopeMappingEntity> getRealmScopeMappingQuery(UserAdapter user, RoleAdapter role) {
|
||||||
|
TypedQuery<RealmScopeMappingEntity> query = em.createNamedQuery("userHasRealmScope", RealmScopeMappingEntity.class);
|
||||||
|
query.setParameter("user", ((UserAdapter)user).getUser());
|
||||||
|
query.setParameter("role", ((RoleAdapter)role).getRole());
|
||||||
|
query.setParameter("realm", realm);
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validatePassword(UserModel user, String password) {
|
||||||
|
for (CredentialEntity cred : ((UserAdapter)user).getUser().getCredentials()) {
|
||||||
|
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||||
|
return new SHAPasswordEncoder(512).verify(password, cred.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean validateTOTP(UserModel user, String password, String token) {
|
||||||
|
if (!validatePassword(user, password)) return false;
|
||||||
|
for (CredentialEntity cred : ((UserAdapter)user).getUser().getCredentials()) {
|
||||||
|
if (cred.getType().equals(UserCredentialModel.TOTP)) {
|
||||||
|
return new TimeBasedOTP().validate(token, cred.getValue().getBytes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateCredential(UserModel user, UserCredentialModel cred) {
|
||||||
|
CredentialEntity credentialEntity = null;
|
||||||
|
UserEntity userEntity = ((UserAdapter) user).getUser();
|
||||||
|
for (CredentialEntity entity : userEntity.getCredentials()) {
|
||||||
|
if (entity.getType().equals(cred.getType())) {
|
||||||
|
credentialEntity = entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (credentialEntity == null) {
|
||||||
|
credentialEntity = new CredentialEntity();
|
||||||
|
credentialEntity.setType(cred.getType());
|
||||||
|
credentialEntity.setDevice(cred.getDevice());
|
||||||
|
credentialEntity.setUser(userEntity);
|
||||||
|
em.persist(credentialEntity);
|
||||||
|
userEntity.getCredentials().add(credentialEntity);
|
||||||
|
}
|
||||||
|
if (cred.getType().equals(UserCredentialModel.PASSWORD)) {
|
||||||
|
credentialEntity.setValue(new SHAPasswordEncoder(512).encode(cred.getValue()));
|
||||||
|
} else {
|
||||||
|
credentialEntity.setValue(cred.getValue());
|
||||||
|
}
|
||||||
|
credentialEntity.setDevice(cred.getDevice());
|
||||||
|
em.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
49
model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
Executable file
49
model/jpa/src/main/java/org/keycloak/models/jpa/RoleAdapter.java
Executable file
|
@ -0,0 +1,49 @@
|
||||||
|
package org.keycloak.models.jpa;
|
||||||
|
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.jpa.entities.RoleEntity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class RoleAdapter implements RoleModel {
|
||||||
|
protected RoleEntity role;
|
||||||
|
|
||||||
|
public RoleAdapter(RoleEntity role) {
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RoleEntity getRole() {
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRole(RoleEntity role) {
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return role.getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return role.getDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDescription(String description) {
|
||||||
|
role.setDescription(description);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getId() {
|
||||||
|
return role.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setName(String name) {
|
||||||
|
role.setName(name);
|
||||||
|
}
|
||||||
|
}
|
185
model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
Executable file
185
model/jpa/src/main/java/org/keycloak/models/jpa/UserAdapter.java
Executable file
|
@ -0,0 +1,185 @@
|
||||||
|
package org.keycloak.models.jpa;
|
||||||
|
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.jpa.entities.UserEntity;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class UserAdapter implements UserModel {
|
||||||
|
|
||||||
|
protected UserEntity user;
|
||||||
|
|
||||||
|
public UserAdapter(UserEntity user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserEntity getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLoginName() {
|
||||||
|
return user.getLoginName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return user.isEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTotp() {
|
||||||
|
return user.isTotp();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
user.setEnabled(enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAttribute(String name, String value) {
|
||||||
|
Map<String, String> attributes = user.getAttributes();
|
||||||
|
if (attributes == null) {
|
||||||
|
attributes = new HashMap<String, String>();
|
||||||
|
}
|
||||||
|
attributes.put(name, value);
|
||||||
|
user.setAttributes(attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeAttribute(String name) {
|
||||||
|
Map<String, String> attributes = user.getAttributes();
|
||||||
|
if (attributes == null) {
|
||||||
|
attributes = new HashMap<String, String>();
|
||||||
|
}
|
||||||
|
attributes.remove(name);
|
||||||
|
user.setAttributes(attributes);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAttribute(String name) {
|
||||||
|
if (user.getAttributes() == null) return null;
|
||||||
|
return user.getAttributes().get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getAttributes() {
|
||||||
|
Map<String, String> result = new HashMap<String, String>();
|
||||||
|
result.putAll(user.getAttributes());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<RequiredAction> getRequiredActions() {
|
||||||
|
Set<RequiredAction> result = new HashSet<RequiredAction>();
|
||||||
|
result.addAll(user.getRequiredActions());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRequiredAction(RequiredAction action) {
|
||||||
|
user.getRequiredActions().add(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeRequiredAction(RequiredAction action) {
|
||||||
|
user.getRequiredActions().remove(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getWebOrigins() {
|
||||||
|
Set<String> result = new HashSet<String>();
|
||||||
|
result.addAll(user.getWebOrigins());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setWebOrigins(Set<String> webOrigins) {
|
||||||
|
user.setWebOrigins(webOrigins);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addWebOrigin(String webOrigin) {
|
||||||
|
user.getWebOrigins().add(webOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeWebOrigin(String webOrigin) {
|
||||||
|
user.getWebOrigins().remove(webOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getRedirectUris() {
|
||||||
|
Set<String> result = new HashSet<String>();
|
||||||
|
result.addAll(user.getRedirectUris());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRedirectUris(Set<String> redirectUris) {
|
||||||
|
user.setRedirectUris(redirectUris);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRedirectUri(String redirectUri) {
|
||||||
|
user.getRedirectUris().add(redirectUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeRedirectUri(String redirectUri) {
|
||||||
|
user.getRedirectUris().remove(redirectUri);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFirstName() {
|
||||||
|
return user.getFirstName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
user.setFirstName(firstName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getLastName() {
|
||||||
|
return user.getLastName();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
user.setLastName(lastName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getEmail() {
|
||||||
|
return user.getEmail();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEmail(String email) {
|
||||||
|
user.setEmail(email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmailVerified() {
|
||||||
|
return user.isEmailVerified();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setEmailVerified(boolean verified) {
|
||||||
|
user.setEmailVerified(verified);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTotp(boolean totp) {
|
||||||
|
user.setTotp(totp);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,14 @@
|
||||||
package org.keycloak.models.jpa.entities;
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinTable;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -8,37 +16,27 @@ import java.util.Collection;
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
@Entity
|
@Entity
|
||||||
public class ResourceEntity {
|
public class ApplicationEntity {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
private String id;
|
private String id;
|
||||||
|
|
||||||
private String resourceName;
|
private String name;
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
private boolean surrogateAuthRequired;
|
private boolean surrogateAuthRequired;
|
||||||
private String managementUrl;
|
private String managementUrl;
|
||||||
@ManyToOne
|
|
||||||
private UserEntity resourceUser;
|
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
|
@OneToOne(fetch = FetchType.EAGER)
|
||||||
Collection<RoleEntity> roles;
|
private UserEntity applicationUser;
|
||||||
|
|
||||||
|
@OneToMany(fetch = FetchType.EAGER, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
|
||||||
|
@JoinTable(name="APPLICATION_ROLES")
|
||||||
|
Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
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() {
|
public boolean isEnabled() {
|
||||||
return enabled;
|
return enabled;
|
||||||
}
|
}
|
||||||
|
@ -63,12 +61,12 @@ public class ResourceEntity {
|
||||||
this.managementUrl = managementUrl;
|
this.managementUrl = managementUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UserEntity getResourceUser() {
|
public UserEntity getApplicationUser() {
|
||||||
return resourceUser;
|
return applicationUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setResourceUser(UserEntity resourceUser) {
|
public void setApplicationUser(UserEntity applicationUser) {
|
||||||
this.resourceUser = resourceUser;
|
this.applicationUser = applicationUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<RoleEntity> getRoles() {
|
public Collection<RoleEntity> getRoles() {
|
||||||
|
@ -78,4 +76,12 @@ public class ResourceEntity {
|
||||||
public void setRoles(Collection<RoleEntity> roles) {
|
public void setRoles(Collection<RoleEntity> roles) {
|
||||||
this.roles = roles;
|
this.roles = roles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name="userHasApplicationScope", query="select m from ApplicationScopeMappingEntity m where m.user = :user and m.role = :role and m.application = :application"),
|
||||||
|
@NamedQuery(name="userApplicationScopeMappings", query="select m from ApplicationScopeMappingEntity m where m.user = :user and m.application = :application")
|
||||||
|
})
|
||||||
|
@Entity
|
||||||
|
public class ApplicationScopeMappingEntity extends UserRoleMappingEntity {
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
protected ApplicationEntity application;
|
||||||
|
|
||||||
|
public ApplicationEntity getApplication() {
|
||||||
|
return application;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplication(ApplicationEntity application) {
|
||||||
|
this.application = application;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name="userHasApplicationRole", query="select m from ApplicationUserRoleMappingEntity m where m.user = :user and m.role = :role and m.application = :application"),
|
||||||
|
@NamedQuery(name="userApplicationMappings", query="select m from ApplicationUserRoleMappingEntity m where m.user = :user and m.application = :application")
|
||||||
|
})
|
||||||
|
@Entity
|
||||||
|
public class ApplicationUserRoleMappingEntity extends UserRoleMappingEntity {
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
protected ApplicationEntity application;
|
||||||
|
|
||||||
|
public ApplicationEntity getApplication() {
|
||||||
|
return application;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplication(ApplicationEntity application) {
|
||||||
|
this.application = application;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name="credentialByUserAndType", query="select cred from CredentialEntity cred where cred.user = :user and cred.type = :type")
|
||||||
|
})
|
||||||
|
@Entity
|
||||||
|
public class CredentialEntity {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
protected String id;
|
||||||
|
|
||||||
|
protected String type;
|
||||||
|
protected String value;
|
||||||
|
protected String device;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
protected UserEntity user;
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDevice() {
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDevice(String device) {
|
||||||
|
this.device = device;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserEntity getUser() {
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUser(UserEntity user) {
|
||||||
|
this.user = user;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name="findOAuthClientByUser", query="select o from OAuthClientEntity o where o.agent.loginName=:name and o.realm = :realm"),
|
||||||
|
@NamedQuery(name="findOAuthClientByRealm", query="select o from OAuthClientEntity o where o.realm = :realm")
|
||||||
|
|
||||||
|
})
|
||||||
|
@Entity
|
||||||
|
public class OAuthClientEntity {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@OneToOne(fetch = FetchType.EAGER)
|
||||||
|
private UserEntity agent;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
protected RealmEntity realm;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserEntity getAgent() {
|
||||||
|
return agent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAgent(UserEntity agent) {
|
||||||
|
this.agent = agent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RealmEntity getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealm(RealmEntity realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,43 +1,272 @@
|
||||||
package org.keycloak.models.jpa.entities;
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.CollectionTable;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.JoinTable;
|
||||||
|
import javax.persistence.MapKeyColumn;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
* @version $Revision: 1 $
|
* @version $Revision: 1 $
|
||||||
*/
|
*/
|
||||||
|
@Entity
|
||||||
public class RealmEntity {
|
public class RealmEntity {
|
||||||
@Id
|
@Id
|
||||||
protected String id;
|
protected String id;
|
||||||
|
|
||||||
protected String realmName;
|
protected String name;
|
||||||
protected boolean enabled;
|
protected boolean enabled;
|
||||||
protected boolean sslNotRequired;
|
protected boolean sslNotRequired;
|
||||||
protected boolean cookieLoginAllowed;
|
protected boolean cookieLoginAllowed;
|
||||||
protected boolean registrationAllowed;
|
protected boolean registrationAllowed;
|
||||||
|
protected boolean verifyEmail;
|
||||||
|
protected boolean resetPasswordAllowed;
|
||||||
|
protected boolean social;
|
||||||
|
protected boolean automaticRegistrationAfterSocialLogin;
|
||||||
|
|
||||||
protected int tokenLifespan;
|
protected int tokenLifespan;
|
||||||
protected int accessCodeLifespan;
|
protected int accessCodeLifespan;
|
||||||
|
protected int accessCodeLifespanUserAction;
|
||||||
|
|
||||||
@Column(length = 2048)
|
@Column(length = 2048)
|
||||||
protected String publicKeyPem;
|
protected String publicKeyPem;
|
||||||
@Column(length = 2048)
|
@Column(length = 2048)
|
||||||
protected String privateKeyPem;
|
protected String privateKeyPem;
|
||||||
protected String[] defaultRoles;
|
|
||||||
@Lob
|
|
||||||
protected HashMap<String, String> smtpConfig;
|
|
||||||
@Lob
|
|
||||||
protected HashMap<String, String> socialConfig;
|
|
||||||
|
|
||||||
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
|
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
|
||||||
Collection<RequiredCredentailEntity> requiredCredentials;
|
@JoinTable(name="USER_REQUIRED_CREDENTIALS")
|
||||||
|
Collection<RequiredCredentialEntity> requiredCredentials = new ArrayList<RequiredCredentialEntity>();
|
||||||
|
|
||||||
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
|
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
|
||||||
Collection<ResourceEntity> resources;
|
@JoinTable(name="APPLICATION_REQUIRED_CREDENTIALS")
|
||||||
|
Collection<RequiredCredentialEntity> requiredApplicationCredentials = new ArrayList<RequiredCredentialEntity>();
|
||||||
|
|
||||||
|
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
|
||||||
|
@JoinTable(name="OAUTH_CLIENT_REQUIRED_CREDENTIALS")
|
||||||
|
Collection<RequiredCredentialEntity> requiredOAuthClientCredentials = new ArrayList<RequiredCredentialEntity>();
|
||||||
|
|
||||||
|
@OneToMany(cascade ={CascadeType.REMOVE}, orphanRemoval = true)
|
||||||
|
Collection<ApplicationEntity> applications = new ArrayList<ApplicationEntity>();
|
||||||
|
|
||||||
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
|
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
|
||||||
Collection<RoleEntity> roles;
|
@JoinTable(name="REALM_ROLES")
|
||||||
|
Collection<RoleEntity> roles = new ArrayList<RoleEntity>();
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
@MapKeyColumn(name="name")
|
||||||
|
@Column(name="value")
|
||||||
|
@CollectionTable
|
||||||
|
protected Map<String, String> smtpConfig = new HashMap<String, String>();
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
@MapKeyColumn(name="name")
|
||||||
|
@Column(name="value")
|
||||||
|
@CollectionTable
|
||||||
|
protected Map<String, String> socialConfig = new HashMap<String, String>();
|
||||||
|
|
||||||
|
@OneToMany(fetch = FetchType.LAZY, cascade ={CascadeType.REMOVE}, orphanRemoval = true)
|
||||||
|
@JoinTable(name="REALM_DEFAULT_ROLES")
|
||||||
|
Collection<RoleEntity> defaultRoles = new ArrayList<RoleEntity>();
|
||||||
|
|
||||||
|
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 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 boolean isVerifyEmail() {
|
||||||
|
return verifyEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVerifyEmail(boolean verifyEmail) {
|
||||||
|
this.verifyEmail = verifyEmail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isResetPasswordAllowed() {
|
||||||
|
return resetPasswordAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResetPasswordAllowed(boolean resetPasswordAllowed) {
|
||||||
|
this.resetPasswordAllowed = resetPasswordAllowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSocial() {
|
||||||
|
return social;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSocial(boolean social) {
|
||||||
|
this.social = social;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isAutomaticRegistrationAfterSocialLogin() {
|
||||||
|
return automaticRegistrationAfterSocialLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAutomaticRegistrationAfterSocialLogin(boolean automaticRegistrationAfterSocialLogin) {
|
||||||
|
this.automaticRegistrationAfterSocialLogin = automaticRegistrationAfterSocialLogin;
|
||||||
|
}
|
||||||
|
|
||||||
|
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 int getAccessCodeLifespanUserAction() {
|
||||||
|
return accessCodeLifespanUserAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccessCodeLifespanUserAction(int accessCodeLifespanUserAction) {
|
||||||
|
this.accessCodeLifespanUserAction = accessCodeLifespanUserAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<RequiredCredentialEntity> getRequiredCredentials() {
|
||||||
|
return requiredCredentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequiredCredentials(Collection<RequiredCredentialEntity> requiredCredentials) {
|
||||||
|
this.requiredCredentials = requiredCredentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<RequiredCredentialEntity> getRequiredApplicationCredentials() {
|
||||||
|
return requiredApplicationCredentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequiredApplicationCredentials(Collection<RequiredCredentialEntity> requiredApplicationCredentials) {
|
||||||
|
this.requiredApplicationCredentials = requiredApplicationCredentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<RequiredCredentialEntity> getRequiredOAuthClientCredentials() {
|
||||||
|
return requiredOAuthClientCredentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequiredOAuthClientCredentials(Collection<RequiredCredentialEntity> requiredOAuthClientCredentials) {
|
||||||
|
this.requiredOAuthClientCredentials = requiredOAuthClientCredentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ApplicationEntity> getApplications() {
|
||||||
|
return applications;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setApplications(Collection<ApplicationEntity> applications) {
|
||||||
|
this.applications = applications;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<RoleEntity> getRoles() {
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRoles(Collection<RoleEntity> roles) {
|
||||||
|
this.roles = roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRole(RoleEntity role) {
|
||||||
|
if (roles == null) {
|
||||||
|
roles = new ArrayList<RoleEntity>();
|
||||||
|
}
|
||||||
|
roles.add(role);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getSmtpConfig() {
|
||||||
|
return smtpConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSmtpConfig(Map<String, String> smtpConfig) {
|
||||||
|
this.smtpConfig = smtpConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getSocialConfig() {
|
||||||
|
return socialConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSocialConfig(Map<String, String> socialConfig) {
|
||||||
|
this.socialConfig = socialConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<RoleEntity> getDefaultRoles() {
|
||||||
|
return defaultRoles;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDefaultRoles(Collection<RoleEntity> defaultRoles) {
|
||||||
|
this.defaultRoles = defaultRoles;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name="userHasRealmScope", query="select m from RealmScopeMappingEntity m where m.user = :user and m.role = :role and m.realm = :realm"),
|
||||||
|
@NamedQuery(name="userRealmScopeMappings", query="select m from RealmScopeMappingEntity m where m.user = :user and m.realm = :realm")
|
||||||
|
})
|
||||||
|
@Entity
|
||||||
|
public class RealmScopeMappingEntity extends UserRoleMappingEntity {
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
protected RealmEntity realm;
|
||||||
|
|
||||||
|
public RealmEntity getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealm(RealmEntity realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name="userHasRealmRole", query="select m from RealmUserRoleMappingEntity m where m.user = :user and m.role = :role and m.realm = :realm"),
|
||||||
|
@NamedQuery(name="userRealmMappings", query="select m from RealmUserRoleMappingEntity m where m.user = :user and m.realm = :realm")
|
||||||
|
})
|
||||||
|
@Entity
|
||||||
|
public class RealmUserRoleMappingEntity extends UserRoleMappingEntity {
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
protected RealmEntity realm;
|
||||||
|
|
||||||
|
public RealmEntity getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealm(RealmEntity realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +0,0 @@
|
||||||
package org.keycloak.models.jpa.entities;
|
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
|
||||||
* @version $Revision: 1 $
|
|
||||||
*/
|
|
||||||
@Entity
|
|
||||||
public class RequiredCredentailEntity {
|
|
||||||
}
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
package org.keycloak.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 RequiredCredentialEntity {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
protected String id;
|
||||||
|
|
||||||
|
protected String type;
|
||||||
|
protected boolean input;
|
||||||
|
protected boolean secret;
|
||||||
|
protected String formLabel;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInput() {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInput(boolean input) {
|
||||||
|
this.input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSecret() {
|
||||||
|
return secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecret(boolean secret) {
|
||||||
|
this.secret = secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFormLabel() {
|
||||||
|
return formLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFormLabel(String formLabel) {
|
||||||
|
this.formLabel = formLabel;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,46 +0,0 @@
|
||||||
package org.keycloak.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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name="findSocialLinkByUser", query="select link from SocialLinkEntity link where link.user = :user"),
|
||||||
|
@NamedQuery(name="findUserByLinkAndRealm", query="select link.user from SocialLinkEntity link where link.realm = :realm and link.socialProvider = :socialProvider and link.socialUsername = :socialUsername"),
|
||||||
|
@NamedQuery(name="findSocialLinkByAll", query="select link.user from SocialLinkEntity link where link.realm = :realm and link.socialProvider = :socialProvider and link.socialUsername = :socialUsername and link.user = :user")
|
||||||
|
})
|
||||||
|
@Entity
|
||||||
|
public class SocialLinkEntity {
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private UserEntity user;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
protected RealmEntity realm;
|
||||||
|
|
||||||
|
protected String socialProvider;
|
||||||
|
protected String socialUsername;
|
||||||
|
|
||||||
|
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 String getSocialProvider() {
|
||||||
|
return socialProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSocialProvider(String socialProvider) {
|
||||||
|
this.socialProvider = socialProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSocialUsername() {
|
||||||
|
return socialUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSocialUsername(String socialUsername) {
|
||||||
|
this.socialUsername = socialUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RealmEntity getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealm(RealmEntity realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,20 +1,72 @@
|
||||||
package org.keycloak.models.jpa.entities;
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
|
||||||
|
import javax.persistence.CollectionTable;
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.ElementCollection;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.MapKeyColumn;
|
||||||
|
import javax.persistence.NamedQueries;
|
||||||
|
import javax.persistence.NamedQuery;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 $
|
||||||
*/
|
*/
|
||||||
|
@NamedQueries({
|
||||||
|
@NamedQuery(name="getRealmUserByLoginName", query="select u from UserEntity u where u.loginName = :loginName and u.realm = :realm"),
|
||||||
|
@NamedQuery(name="getRealmUserByEmail", query="select u from UserEntity u where u.email = :email and u.realm = :realm"),
|
||||||
|
@NamedQuery(name="getRealmUserByLastName", query="select u from UserEntity u where u.lastName = :lastName and u.realm = :realm"),
|
||||||
|
@NamedQuery(name="getRealmUserByFirstLastName", query="select u from UserEntity u where u.firstName = :first and u.lastName = :last and u.realm = :realm")
|
||||||
|
})
|
||||||
@Entity
|
@Entity
|
||||||
public class UserEntity {
|
public class UserEntity {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
private String id;
|
protected String id;
|
||||||
|
|
||||||
private String loginName;
|
protected String loginName;
|
||||||
|
protected String firstName;
|
||||||
|
protected String lastName;
|
||||||
|
protected String email;
|
||||||
|
protected boolean enabled;
|
||||||
|
protected boolean totp;
|
||||||
|
protected boolean emailVerified;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
protected RealmEntity realm;
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
@MapKeyColumn(name="name")
|
||||||
|
@Column(name="value")
|
||||||
|
@CollectionTable
|
||||||
|
protected Map<String, String> attributes = new HashMap<String, String>();
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
@CollectionTable
|
||||||
|
protected Set<UserModel.RequiredAction> requiredActions = new HashSet<UserModel.RequiredAction>();
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
@CollectionTable
|
||||||
|
protected Set<String> webOrigins = new HashSet<String>();
|
||||||
|
|
||||||
|
@ElementCollection
|
||||||
|
@CollectionTable
|
||||||
|
protected Set<String> redirectUris = new HashSet<String>();
|
||||||
|
|
||||||
|
@OneToMany
|
||||||
|
protected Collection<CredentialEntity> credentials = new ArrayList<CredentialEntity>();
|
||||||
|
|
||||||
public String getId() {
|
public String getId() {
|
||||||
return id;
|
return id;
|
||||||
|
@ -31,4 +83,100 @@ public class UserEntity {
|
||||||
public void setLoginName(String loginName) {
|
public void setLoginName(String loginName) {
|
||||||
this.loginName = loginName;
|
this.loginName = loginName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getFirstName() {
|
||||||
|
return firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFirstName(String firstName) {
|
||||||
|
this.firstName = firstName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLastName() {
|
||||||
|
return lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLastName(String lastName) {
|
||||||
|
this.lastName = lastName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnabled(boolean enabled) {
|
||||||
|
this.enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTotp() {
|
||||||
|
return totp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotp(boolean totp) {
|
||||||
|
this.totp = totp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isEmailVerified() {
|
||||||
|
return emailVerified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmailVerified(boolean emailVerified) {
|
||||||
|
this.emailVerified = emailVerified;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> getAttributes() {
|
||||||
|
return attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttributes(Map<String, String> attributes) {
|
||||||
|
this.attributes = attributes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<UserModel.RequiredAction> getRequiredActions() {
|
||||||
|
return requiredActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRequiredActions(Set<UserModel.RequiredAction> requiredActions) {
|
||||||
|
this.requiredActions = requiredActions;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getWebOrigins() {
|
||||||
|
return webOrigins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWebOrigins(Set<String> webOrigins) {
|
||||||
|
this.webOrigins = webOrigins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getRedirectUris() {
|
||||||
|
return redirectUris;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRedirectUris(Set<String> redirectUris) {
|
||||||
|
this.redirectUris = redirectUris;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RealmEntity getRealm() {
|
||||||
|
return realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRealm(RealmEntity realm) {
|
||||||
|
this.realm = realm;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<CredentialEntity> getCredentials() {
|
||||||
|
return credentials;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCredentials(Collection<CredentialEntity> credentials) {
|
||||||
|
this.credentials = credentials;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
package org.keycloak.models.jpa.entities;
|
package org.keycloak.models.jpa.entities;
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
|
||||||
import javax.persistence.GeneratedValue;
|
import javax.persistence.GeneratedValue;
|
||||||
import javax.persistence.Id;
|
import javax.persistence.Id;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 $
|
||||||
*/
|
*/
|
||||||
@Entity
|
@MappedSuperclass
|
||||||
public class UserRoleMappingEntity {
|
public abstract class UserRoleMappingEntity {
|
||||||
@Id
|
@Id
|
||||||
@GeneratedValue
|
@GeneratedValue
|
||||||
private long id;
|
protected long id;
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
private UserEntity user;
|
protected UserEntity user;
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
private RoleEntity role;
|
protected RoleEntity role;
|
||||||
|
|
||||||
public long getId() {
|
public long getId() {
|
||||||
return id;
|
return id;
|
||||||
|
|
5
model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQL.java
Normal file → Executable file
5
model/mongo/src/main/java/org/keycloak/models/mongo/api/NoSQL.java
Normal file → Executable file
|
@ -1,10 +1,9 @@
|
||||||
package org.keycloak.models.mongo.api;
|
package org.keycloak.models.mongo.api;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
|
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
|
||||||
import org.picketlink.common.properties.Property;
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
|
2
model/mongo/src/main/java/org/keycloak/models/mongo/api/types/TypeConverter.java
Normal file → Executable file
2
model/mongo/src/main/java/org/keycloak/models/mongo/api/types/TypeConverter.java
Normal file → Executable file
|
@ -3,8 +3,6 @@ package org.keycloak.models.mongo.api.types;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.picketlink.common.reflection.Reflections;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registry of converters, which allow to convert application object to database objects. TypeConverter is main entry point to be used by application.
|
* Registry of converters, which allow to convert application object to database objects. TypeConverter is main entry point to be used by application.
|
||||||
* Application can create instance of TypeConverter and then register required Converter objects.
|
* Application can create instance of TypeConverter and then register required Converter objects.
|
||||||
|
|
18
model/mongo/src/main/java/org/keycloak/models/mongo/impl/MongoDBImpl.java
Normal file → Executable file
18
model/mongo/src/main/java/org/keycloak/models/mongo/impl/MongoDBImpl.java
Normal file → Executable file
|
@ -1,12 +1,5 @@
|
||||||
package org.keycloak.models.mongo.impl;
|
package org.keycloak.models.mongo.impl;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBList;
|
import com.mongodb.BasicDBList;
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
import com.mongodb.DB;
|
import com.mongodb.DB;
|
||||||
|
@ -24,10 +17,10 @@ import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
|
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
|
||||||
import org.keycloak.models.mongo.api.types.Converter;
|
import org.keycloak.models.mongo.api.types.Converter;
|
||||||
import org.keycloak.models.mongo.api.types.TypeConverter;
|
import org.keycloak.models.mongo.api.types.TypeConverter;
|
||||||
import org.keycloak.models.mongo.impl.types.EnumToStringConverter;
|
|
||||||
import org.keycloak.models.mongo.impl.types.ListConverter;
|
|
||||||
import org.keycloak.models.mongo.impl.types.BasicDBListConverter;
|
import org.keycloak.models.mongo.impl.types.BasicDBListConverter;
|
||||||
import org.keycloak.models.mongo.impl.types.BasicDBObjectConverter;
|
import org.keycloak.models.mongo.impl.types.BasicDBObjectConverter;
|
||||||
|
import org.keycloak.models.mongo.impl.types.EnumToStringConverter;
|
||||||
|
import org.keycloak.models.mongo.impl.types.ListConverter;
|
||||||
import org.keycloak.models.mongo.impl.types.NoSQLObjectConverter;
|
import org.keycloak.models.mongo.impl.types.NoSQLObjectConverter;
|
||||||
import org.keycloak.models.mongo.impl.types.SimpleConverter;
|
import org.keycloak.models.mongo.impl.types.SimpleConverter;
|
||||||
import org.keycloak.models.mongo.impl.types.StringToEnumConverter;
|
import org.keycloak.models.mongo.impl.types.StringToEnumConverter;
|
||||||
|
@ -35,6 +28,13 @@ import org.picketlink.common.properties.Property;
|
||||||
import org.picketlink.common.properties.query.AnnotatedPropertyCriteria;
|
import org.picketlink.common.properties.query.AnnotatedPropertyCriteria;
|
||||||
import org.picketlink.common.properties.query.PropertyQueries;
|
import org.picketlink.common.properties.query.PropertyQueries;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
8
model/mongo/src/main/java/org/keycloak/models/mongo/impl/MongoDBQueryBuilder.java
Normal file → Executable file
8
model/mongo/src/main/java/org/keycloak/models/mongo/impl/MongoDBQueryBuilder.java
Normal file → Executable file
|
@ -1,13 +1,13 @@
|
||||||
package org.keycloak.models.mongo.impl;
|
package org.keycloak.models.mongo.impl;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
import org.bson.types.ObjectId;
|
import org.bson.types.ObjectId;
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
|
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
6
model/mongo/src/main/java/org/keycloak/models/mongo/impl/ObjectInfo.java
Normal file → Executable file
6
model/mongo/src/main/java/org/keycloak/models/mongo/impl/ObjectInfo.java
Normal file → Executable file
|
@ -1,14 +1,14 @@
|
||||||
package org.keycloak.models.mongo.impl;
|
package org.keycloak.models.mongo.impl;
|
||||||
|
|
||||||
|
import org.keycloak.models.mongo.api.NoSQLObject;
|
||||||
|
import org.picketlink.common.properties.Property;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.keycloak.models.mongo.api.NoSQLObject;
|
|
||||||
import org.picketlink.common.properties.Property;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
4
model/mongo/src/main/java/org/keycloak/models/mongo/impl/types/BasicDBListConverter.java
Normal file → Executable file
4
model/mongo/src/main/java/org/keycloak/models/mongo/impl/types/BasicDBListConverter.java
Normal file → Executable file
|
@ -1,12 +1,12 @@
|
||||||
package org.keycloak.models.mongo.impl.types;
|
package org.keycloak.models.mongo.impl.types;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBList;
|
import com.mongodb.BasicDBList;
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
import org.keycloak.models.mongo.api.types.Converter;
|
import org.keycloak.models.mongo.api.types.Converter;
|
||||||
import org.keycloak.models.mongo.api.types.TypeConverter;
|
import org.keycloak.models.mongo.api.types.TypeConverter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
4
model/mongo/src/main/java/org/keycloak/models/mongo/impl/types/ListConverter.java
Normal file → Executable file
4
model/mongo/src/main/java/org/keycloak/models/mongo/impl/types/ListConverter.java
Normal file → Executable file
|
@ -1,12 +1,12 @@
|
||||||
package org.keycloak.models.mongo.impl.types;
|
package org.keycloak.models.mongo.impl.types;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBList;
|
import com.mongodb.BasicDBList;
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
import org.keycloak.models.mongo.api.types.Converter;
|
import org.keycloak.models.mongo.api.types.Converter;
|
||||||
import org.keycloak.models.mongo.api.types.TypeConverter;
|
import org.keycloak.models.mongo.api.types.TypeConverter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
6
model/mongo/src/main/java/org/keycloak/models/mongo/impl/types/NoSQLObjectConverter.java
Normal file → Executable file
6
model/mongo/src/main/java/org/keycloak/models/mongo/impl/types/NoSQLObjectConverter.java
Normal file → Executable file
|
@ -1,8 +1,5 @@
|
||||||
package org.keycloak.models.mongo.impl.types;
|
package org.keycloak.models.mongo.impl.types;
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import com.mongodb.BasicDBObject;
|
import com.mongodb.BasicDBObject;
|
||||||
import org.keycloak.models.mongo.api.AttributedNoSQLObject;
|
import org.keycloak.models.mongo.api.AttributedNoSQLObject;
|
||||||
import org.keycloak.models.mongo.api.NoSQLObject;
|
import org.keycloak.models.mongo.api.NoSQLObject;
|
||||||
|
@ -12,6 +9,9 @@ import org.keycloak.models.mongo.impl.MongoDBImpl;
|
||||||
import org.keycloak.models.mongo.impl.ObjectInfo;
|
import org.keycloak.models.mongo.impl.ObjectInfo;
|
||||||
import org.picketlink.common.properties.Property;
|
import org.picketlink.common.properties.Property;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
package org.keycloak.models.mongo.keycloak;
|
||||||
|
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.models.ModelProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class MongoModelProvider implements ModelProvider {
|
||||||
|
@Override
|
||||||
|
public KeycloakSessionFactory createFactory() {
|
||||||
|
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
}
|
10
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java
Normal file → Executable file
10
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/ApplicationAdapter.java
Normal file → Executable file
|
@ -1,10 +1,5 @@
|
||||||
package org.keycloak.models.mongo.keycloak.adapters;
|
package org.keycloak.models.mongo.keycloak.adapters;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.keycloak.models.ApplicationModel;
|
import org.keycloak.models.ApplicationModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
|
@ -14,6 +9,11 @@ import org.keycloak.models.mongo.keycloak.data.ApplicationData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.RoleData;
|
import org.keycloak.models.mongo.keycloak.data.RoleData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.UserData;
|
import org.keycloak.models.mongo.keycloak.data.UserData;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
6
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoDBSessionFactory.java
Normal file → Executable file
6
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/MongoDBSessionFactory.java
Normal file → Executable file
|
@ -1,7 +1,5 @@
|
||||||
package org.keycloak.models.mongo.keycloak.adapters;
|
package org.keycloak.models.mongo.keycloak.adapters;
|
||||||
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
|
|
||||||
import com.mongodb.DB;
|
import com.mongodb.DB;
|
||||||
import com.mongodb.MongoClient;
|
import com.mongodb.MongoClient;
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
|
@ -9,6 +7,7 @@ import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.mongo.api.NoSQL;
|
import org.keycloak.models.mongo.api.NoSQL;
|
||||||
import org.keycloak.models.mongo.api.NoSQLObject;
|
import org.keycloak.models.mongo.api.NoSQLObject;
|
||||||
|
import org.keycloak.models.mongo.impl.MongoDBImpl;
|
||||||
import org.keycloak.models.mongo.keycloak.data.ApplicationData;
|
import org.keycloak.models.mongo.keycloak.data.ApplicationData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.OAuthClientData;
|
import org.keycloak.models.mongo.keycloak.data.OAuthClientData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.RealmData;
|
import org.keycloak.models.mongo.keycloak.data.RealmData;
|
||||||
|
@ -16,10 +15,11 @@ import org.keycloak.models.mongo.keycloak.data.RequiredCredentialData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.RoleData;
|
import org.keycloak.models.mongo.keycloak.data.RoleData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.SocialLinkData;
|
import org.keycloak.models.mongo.keycloak.data.SocialLinkData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.UserData;
|
import org.keycloak.models.mongo.keycloak.data.UserData;
|
||||||
import org.keycloak.models.mongo.impl.MongoDBImpl;
|
|
||||||
import org.keycloak.models.mongo.keycloak.data.credentials.OTPData;
|
import org.keycloak.models.mongo.keycloak.data.credentials.OTPData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.credentials.PasswordData;
|
import org.keycloak.models.mongo.keycloak.data.credentials.PasswordData;
|
||||||
|
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* NoSQL implementation based on MongoDB
|
* NoSQL implementation based on MongoDB
|
||||||
*
|
*
|
||||||
|
|
8
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/NoSQLSession.java
Normal file → Executable file
8
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/NoSQLSession.java
Normal file → Executable file
|
@ -1,17 +1,17 @@
|
||||||
package org.keycloak.models.mongo.keycloak.adapters;
|
package org.keycloak.models.mongo.keycloak.adapters;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.keycloak.models.KeycloakSession;
|
import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakTransaction;
|
import org.keycloak.models.KeycloakTransaction;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.mongo.api.NoSQL;
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
||||||
import org.keycloak.models.mongo.keycloak.data.RealmData;
|
import org.keycloak.models.mongo.keycloak.data.RealmData;
|
||||||
import org.keycloak.models.mongo.api.NoSQL;
|
|
||||||
import org.keycloak.models.utils.KeycloakSessionUtils;
|
import org.keycloak.models.utils.KeycloakSessionUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
10
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java
Normal file → Executable file
10
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/OAuthClientAdapter.java
Normal file → Executable file
|
@ -41,14 +41,4 @@ public class OAuthClientAdapter implements OAuthClientModel {
|
||||||
return oauthAgent;
|
return oauthAgent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getBaseUrl() {
|
|
||||||
return delegate.getBaseUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBaseUrl(String base) {
|
|
||||||
delegate.setBaseUrl(base);
|
|
||||||
noSQL.saveObject(delegate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
63
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
Normal file → Executable file
63
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/RealmAdapter.java
Normal file → Executable file
|
@ -1,16 +1,5 @@
|
||||||
package org.keycloak.models.mongo.keycloak.adapters;
|
package org.keycloak.models.mongo.keycloak.adapters;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.security.PrivateKey;
|
|
||||||
import java.security.PublicKey;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.bouncycastle.openssl.PEMWriter;
|
import org.bouncycastle.openssl.PEMWriter;
|
||||||
import org.keycloak.PemUtils;
|
import org.keycloak.PemUtils;
|
||||||
import org.keycloak.models.ApplicationModel;
|
import org.keycloak.models.ApplicationModel;
|
||||||
|
@ -21,21 +10,31 @@ import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.SocialLinkModel;
|
import org.keycloak.models.SocialLinkModel;
|
||||||
import org.keycloak.models.UserCredentialModel;
|
import org.keycloak.models.UserCredentialModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
|
|
||||||
import org.keycloak.models.mongo.keycloak.data.OAuthClientData;
|
|
||||||
import org.keycloak.representations.idm.CredentialRepresentation;
|
|
||||||
import org.keycloak.models.mongo.api.NoSQL;
|
import org.keycloak.models.mongo.api.NoSQL;
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
||||||
|
import org.keycloak.models.mongo.api.query.NoSQLQueryBuilder;
|
||||||
import org.keycloak.models.mongo.keycloak.credentials.PasswordCredentialHandler;
|
import org.keycloak.models.mongo.keycloak.credentials.PasswordCredentialHandler;
|
||||||
import org.keycloak.models.mongo.keycloak.credentials.TOTPCredentialHandler;
|
import org.keycloak.models.mongo.keycloak.credentials.TOTPCredentialHandler;
|
||||||
import org.keycloak.models.mongo.keycloak.data.ApplicationData;
|
import org.keycloak.models.mongo.keycloak.data.ApplicationData;
|
||||||
|
import org.keycloak.models.mongo.keycloak.data.OAuthClientData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.RealmData;
|
import org.keycloak.models.mongo.keycloak.data.RealmData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.RequiredCredentialData;
|
import org.keycloak.models.mongo.keycloak.data.RequiredCredentialData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.RoleData;
|
import org.keycloak.models.mongo.keycloak.data.RoleData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.SocialLinkData;
|
import org.keycloak.models.mongo.keycloak.data.SocialLinkData;
|
||||||
import org.keycloak.models.mongo.keycloak.data.UserData;
|
import org.keycloak.models.mongo.keycloak.data.UserData;
|
||||||
|
import org.keycloak.representations.idm.CredentialRepresentation;
|
||||||
import org.picketlink.idm.credential.Credentials;
|
import org.picketlink.idm.credential.Credentials;
|
||||||
import org.picketlink.idm.model.sample.User;
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
|
@ -596,20 +595,6 @@ public class RealmAdapter implements RealmModel {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isRealmAdmin(UserModel agent) {
|
|
||||||
List<String> realmAdmins = realm.getRealmAdmins();
|
|
||||||
String userId = ((UserAdapter)agent).getUser().getId();
|
|
||||||
return realmAdmins.contains(userId);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addRealmAdmin(UserModel agent) {
|
|
||||||
UserData userData = ((UserAdapter)agent).getUser();
|
|
||||||
|
|
||||||
noSQL.pushItemToList(realm, "realmAdmins", userData.getId());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RoleModel getRoleById(String id) {
|
public RoleModel getRoleById(String id) {
|
||||||
RoleData role = noSQL.loadObject(RoleData.class, id);
|
RoleData role = noSQL.loadObject(RoleData.class, id);
|
||||||
|
@ -859,4 +844,24 @@ public class RealmAdapter implements RealmModel {
|
||||||
}
|
}
|
||||||
return userModels;
|
return userModels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getSmtpConfig() {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSmtpConfig(Map<String, String> smtpConfig) {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getSocialConfig() {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSocialConfig(Map<String, String> socialConfig) {
|
||||||
|
throw new RuntimeException("Not implemented");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
48
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
Normal file → Executable file
48
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/adapters/UserAdapter.java
Normal file → Executable file
|
@ -1,15 +1,15 @@
|
||||||
package org.keycloak.models.mongo.keycloak.adapters;
|
package org.keycloak.models.mongo.keycloak.adapters;
|
||||||
|
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
|
import org.keycloak.models.mongo.api.NoSQL;
|
||||||
|
import org.keycloak.models.mongo.keycloak.data.UserData;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.keycloak.models.UserModel;
|
|
||||||
import org.keycloak.models.mongo.api.NoSQL;
|
|
||||||
import org.keycloak.models.mongo.keycloak.data.UserData;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper around UserData object, which will persist wrapped object after each set operation (compatibility with picketlink based impl)
|
* Wrapper around UserData object, which will persist wrapped object after each set operation (compatibility with picketlink based impl)
|
||||||
*
|
*
|
||||||
|
@ -149,4 +149,44 @@ public class UserAdapter implements UserModel {
|
||||||
user.setTotp(totp);
|
user.setTotp(totp);
|
||||||
noSQL.saveObject(user);
|
noSQL.saveObject(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getWebOrigins() {
|
||||||
|
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setWebOrigins(Set<String> webOrigins) {
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addWebOrigin(String webOrigin) {
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeWebOrigin(String webOrigin) {
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Set<String> getRedirectUris() {
|
||||||
|
return null; //To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setRedirectUris(Set<String> redirectUris) {
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addRedirectUri(String redirectUri) {
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void removeRedirectUri(String redirectUri) {
|
||||||
|
//To change body of implemented methods use File | Settings | File Templates.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
8
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/credentials/PasswordCredentialHandler.java
Normal file → Executable file
8
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/credentials/PasswordCredentialHandler.java
Normal file → Executable file
|
@ -1,9 +1,5 @@
|
||||||
package org.keycloak.models.mongo.keycloak.credentials;
|
package org.keycloak.models.mongo.keycloak.credentials;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
|
|
||||||
import org.keycloak.models.mongo.api.NoSQL;
|
import org.keycloak.models.mongo.api.NoSQL;
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
||||||
import org.keycloak.models.mongo.keycloak.data.UserData;
|
import org.keycloak.models.mongo.keycloak.data.UserData;
|
||||||
|
@ -12,6 +8,10 @@ import org.picketlink.idm.credential.Credentials;
|
||||||
import org.picketlink.idm.credential.encoder.PasswordEncoder;
|
import org.picketlink.idm.credential.encoder.PasswordEncoder;
|
||||||
import org.picketlink.idm.credential.encoder.SHAPasswordEncoder;
|
import org.picketlink.idm.credential.encoder.SHAPasswordEncoder;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defacto forked from {@link org.picketlink.idm.credential.handler.PasswordCredentialHandler}
|
* Defacto forked from {@link org.picketlink.idm.credential.handler.PasswordCredentialHandler}
|
||||||
*
|
*
|
||||||
|
|
11
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/credentials/TOTPCredentialHandler.java
Normal file → Executable file
11
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/credentials/TOTPCredentialHandler.java
Normal file → Executable file
|
@ -1,8 +1,5 @@
|
||||||
package org.keycloak.models.mongo.keycloak.credentials;
|
package org.keycloak.models.mongo.keycloak.credentials;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.keycloak.models.mongo.api.NoSQL;
|
import org.keycloak.models.mongo.api.NoSQL;
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
||||||
import org.keycloak.models.mongo.keycloak.data.UserData;
|
import org.keycloak.models.mongo.keycloak.data.UserData;
|
||||||
|
@ -10,11 +7,11 @@ import org.keycloak.models.mongo.keycloak.data.credentials.OTPData;
|
||||||
import org.picketlink.idm.credential.Credentials;
|
import org.picketlink.idm.credential.Credentials;
|
||||||
import org.picketlink.idm.credential.util.TimeBasedOTP;
|
import org.picketlink.idm.credential.util.TimeBasedOTP;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.picketlink.common.util.StringUtil.isNullOrEmpty;
|
import static org.picketlink.common.util.StringUtil.isNullOrEmpty;
|
||||||
import static org.picketlink.idm.credential.util.TimeBasedOTP.DEFAULT_ALGORITHM;
|
import static org.picketlink.idm.credential.util.TimeBasedOTP.*;
|
||||||
import static org.picketlink.idm.credential.util.TimeBasedOTP.DEFAULT_DELAY_WINDOW;
|
|
||||||
import static org.picketlink.idm.credential.util.TimeBasedOTP.DEFAULT_INTERVAL_SECONDS;
|
|
||||||
import static org.picketlink.idm.credential.util.TimeBasedOTP.DEFAULT_NUMBER_DIGITS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defacto forked from {@link org.picketlink.idm.credential.handler.TOTPCredentialHandler}
|
* Defacto forked from {@link org.picketlink.idm.credential.handler.TOTPCredentialHandler}
|
||||||
|
|
4
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/data/RealmData.java
Normal file → Executable file
4
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/data/RealmData.java
Normal file → Executable file
|
@ -1,7 +1,5 @@
|
||||||
package org.keycloak.models.mongo.keycloak.data;
|
package org.keycloak.models.mongo.keycloak.data;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.keycloak.models.mongo.api.NoSQL;
|
import org.keycloak.models.mongo.api.NoSQL;
|
||||||
import org.keycloak.models.mongo.api.NoSQLCollection;
|
import org.keycloak.models.mongo.api.NoSQLCollection;
|
||||||
import org.keycloak.models.mongo.api.NoSQLField;
|
import org.keycloak.models.mongo.api.NoSQLField;
|
||||||
|
@ -9,6 +7,8 @@ import org.keycloak.models.mongo.api.NoSQLId;
|
||||||
import org.keycloak.models.mongo.api.NoSQLObject;
|
import org.keycloak.models.mongo.api.NoSQLObject;
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
4
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/data/RoleData.java
Normal file → Executable file
4
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/data/RoleData.java
Normal file → Executable file
|
@ -1,7 +1,5 @@
|
||||||
package org.keycloak.models.mongo.keycloak.data;
|
package org.keycloak.models.mongo.keycloak.data;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.models.mongo.api.NoSQL;
|
import org.keycloak.models.mongo.api.NoSQL;
|
||||||
import org.keycloak.models.mongo.api.NoSQLCollection;
|
import org.keycloak.models.mongo.api.NoSQLCollection;
|
||||||
|
@ -10,6 +8,8 @@ import org.keycloak.models.mongo.api.NoSQLId;
|
||||||
import org.keycloak.models.mongo.api.NoSQLObject;
|
import org.keycloak.models.mongo.api.NoSQLObject;
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
4
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/data/UserData.java
Normal file → Executable file
4
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/data/UserData.java
Normal file → Executable file
|
@ -1,7 +1,5 @@
|
||||||
package org.keycloak.models.mongo.keycloak.data;
|
package org.keycloak.models.mongo.keycloak.data;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.jboss.logging.Logger;
|
import org.jboss.logging.Logger;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.mongo.api.AbstractAttributedNoSQLObject;
|
import org.keycloak.models.mongo.api.AbstractAttributedNoSQLObject;
|
||||||
|
@ -12,6 +10,8 @@ import org.keycloak.models.mongo.api.NoSQLId;
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
||||||
import org.keycloak.models.mongo.keycloak.data.credentials.PasswordData;
|
import org.keycloak.models.mongo.keycloak.data.credentials.PasswordData;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
4
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/data/credentials/OTPData.java
Normal file → Executable file
4
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/data/credentials/OTPData.java
Normal file → Executable file
|
@ -1,11 +1,11 @@
|
||||||
package org.keycloak.models.mongo.keycloak.data.credentials;
|
package org.keycloak.models.mongo.keycloak.data.credentials;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.keycloak.models.mongo.api.AbstractNoSQLObject;
|
import org.keycloak.models.mongo.api.AbstractNoSQLObject;
|
||||||
import org.keycloak.models.mongo.api.NoSQLCollection;
|
import org.keycloak.models.mongo.api.NoSQLCollection;
|
||||||
import org.keycloak.models.mongo.api.NoSQLField;
|
import org.keycloak.models.mongo.api.NoSQLField;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
4
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/data/credentials/PasswordData.java
Normal file → Executable file
4
model/mongo/src/main/java/org/keycloak/models/mongo/keycloak/data/credentials/PasswordData.java
Normal file → Executable file
|
@ -1,11 +1,11 @@
|
||||||
package org.keycloak.models.mongo.keycloak.data.credentials;
|
package org.keycloak.models.mongo.keycloak.data.credentials;
|
||||||
|
|
||||||
import java.util.Date;
|
|
||||||
|
|
||||||
import org.keycloak.models.mongo.api.AbstractNoSQLObject;
|
import org.keycloak.models.mongo.api.AbstractNoSQLObject;
|
||||||
import org.keycloak.models.mongo.api.NoSQLCollection;
|
import org.keycloak.models.mongo.api.NoSQLCollection;
|
||||||
import org.keycloak.models.mongo.api.NoSQLField;
|
import org.keycloak.models.mongo.api.NoSQLField;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
4
model/mongo/src/test/java/org/keycloak/models/mongo/test/Address.java
Normal file → Executable file
4
model/mongo/src/test/java/org/keycloak/models/mongo/test/Address.java
Normal file → Executable file
|
@ -1,10 +1,10 @@
|
||||||
package org.keycloak.models.mongo.test;
|
package org.keycloak.models.mongo.test;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.keycloak.models.mongo.api.AbstractNoSQLObject;
|
import org.keycloak.models.mongo.api.AbstractNoSQLObject;
|
||||||
import org.keycloak.models.mongo.api.NoSQLField;
|
import org.keycloak.models.mongo.api.NoSQLField;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
10
model/mongo/src/test/java/org/keycloak/models/mongo/test/MongoDBModelTest.java
Normal file → Executable file
10
model/mongo/src/test/java/org/keycloak/models/mongo/test/MongoDBModelTest.java
Normal file → Executable file
|
@ -1,10 +1,5 @@
|
||||||
package org.keycloak.models.mongo.test;
|
package org.keycloak.models.mongo.test;
|
||||||
|
|
||||||
import java.net.UnknownHostException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.mongodb.DB;
|
import com.mongodb.DB;
|
||||||
import com.mongodb.MongoClient;
|
import com.mongodb.MongoClient;
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
|
@ -15,6 +10,11 @@ import org.keycloak.models.mongo.api.NoSQLObject;
|
||||||
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
import org.keycloak.models.mongo.api.query.NoSQLQuery;
|
||||||
import org.keycloak.models.mongo.impl.MongoDBImpl;
|
import org.keycloak.models.mongo.impl.MongoDBImpl;
|
||||||
|
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
4
model/mongo/src/test/java/org/keycloak/models/mongo/test/Person.java
Normal file → Executable file
4
model/mongo/src/test/java/org/keycloak/models/mongo/test/Person.java
Normal file → Executable file
|
@ -1,12 +1,12 @@
|
||||||
package org.keycloak.models.mongo.test;
|
package org.keycloak.models.mongo.test;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.keycloak.models.mongo.api.AbstractNoSQLObject;
|
import org.keycloak.models.mongo.api.AbstractNoSQLObject;
|
||||||
import org.keycloak.models.mongo.api.NoSQLCollection;
|
import org.keycloak.models.mongo.api.NoSQLCollection;
|
||||||
import org.keycloak.models.mongo.api.NoSQLField;
|
import org.keycloak.models.mongo.api.NoSQLField;
|
||||||
import org.keycloak.models.mongo.api.NoSQLId;
|
import org.keycloak.models.mongo.api.NoSQLId;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
* @author <a href="mailto:mposolda@redhat.com">Marek Posolda</a>
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -31,14 +31,4 @@ public class OAuthClientAdapter implements OAuthClientModel {
|
||||||
return new UserAdapter(delegate.getOauthAgent(), idm);
|
return new UserAdapter(delegate.getOauthAgent(), idm);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getBaseUrl() {
|
|
||||||
return delegate.getBaseUrl();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setBaseUrl(String base) {
|
|
||||||
delegate.setBaseUrl(base);
|
|
||||||
relationshipManager.update(delegate);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@ import org.keycloak.models.KeycloakTransaction;
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.picketlink.mappings.RealmData;
|
import org.keycloak.models.picketlink.mappings.RealmData;
|
||||||
import org.keycloak.models.picketlink.relationships.RealmAdminRelationship;
|
|
||||||
import org.keycloak.models.picketlink.relationships.RealmListingRelationship;
|
import org.keycloak.models.picketlink.relationships.RealmListingRelationship;
|
||||||
import org.keycloak.models.utils.KeycloakSessionUtils;
|
import org.keycloak.models.utils.KeycloakSessionUtils;
|
||||||
import org.picketlink.idm.PartitionManager;
|
import org.picketlink.idm.PartitionManager;
|
||||||
|
@ -15,7 +14,6 @@ import org.picketlink.idm.query.RelationshipQuery;
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
|
|
@ -0,0 +1,77 @@
|
||||||
|
package org.keycloak.models.picketlink;
|
||||||
|
|
||||||
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
|
import org.keycloak.models.ModelProvider;
|
||||||
|
import org.keycloak.models.picketlink.mappings.ApplicationEntity;
|
||||||
|
import org.keycloak.models.picketlink.mappings.RealmEntity;
|
||||||
|
import org.picketlink.idm.PartitionManager;
|
||||||
|
import org.picketlink.idm.config.IdentityConfigurationBuilder;
|
||||||
|
import org.picketlink.idm.internal.DefaultPartitionManager;
|
||||||
|
import org.picketlink.idm.jpa.internal.JPAContextInitializer;
|
||||||
|
import org.picketlink.idm.jpa.model.sample.simple.AccountTypeEntity;
|
||||||
|
import org.picketlink.idm.jpa.model.sample.simple.AttributeTypeEntity;
|
||||||
|
import org.picketlink.idm.jpa.model.sample.simple.AttributedTypeEntity;
|
||||||
|
import org.picketlink.idm.jpa.model.sample.simple.DigestCredentialTypeEntity;
|
||||||
|
import org.picketlink.idm.jpa.model.sample.simple.GroupTypeEntity;
|
||||||
|
import org.picketlink.idm.jpa.model.sample.simple.IdentityTypeEntity;
|
||||||
|
import org.picketlink.idm.jpa.model.sample.simple.OTPCredentialTypeEntity;
|
||||||
|
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.persistence.EntityManager;
|
||||||
|
import javax.persistence.EntityManagerFactory;
|
||||||
|
import javax.persistence.Persistence;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
* @version $Revision: 1 $
|
||||||
|
*/
|
||||||
|
public class PicketlinkModelProvider implements ModelProvider {
|
||||||
|
@Override
|
||||||
|
public KeycloakSessionFactory createFactory() {
|
||||||
|
EntityManagerFactory emf = Persistence.createEntityManagerFactory("picketlink-keycloak-identity-store");
|
||||||
|
return new PicketlinkKeycloakSessionFactory(emf, buildPartitionManager());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PartitionManager buildPartitionManager() {
|
||||||
|
IdentityConfigurationBuilder builder = new IdentityConfigurationBuilder();
|
||||||
|
|
||||||
|
builder
|
||||||
|
.named("KEYCLOAK_JPA_CONFIG")
|
||||||
|
.stores()
|
||||||
|
.jpa()
|
||||||
|
.mappedEntity(
|
||||||
|
AttributedTypeEntity.class,
|
||||||
|
AccountTypeEntity.class,
|
||||||
|
RoleTypeEntity.class,
|
||||||
|
GroupTypeEntity.class,
|
||||||
|
IdentityTypeEntity.class,
|
||||||
|
RelationshipTypeEntity.class,
|
||||||
|
RelationshipIdentityTypeEntity.class,
|
||||||
|
PartitionTypeEntity.class,
|
||||||
|
PasswordCredentialTypeEntity.class,
|
||||||
|
DigestCredentialTypeEntity.class,
|
||||||
|
X509CredentialTypeEntity.class,
|
||||||
|
OTPCredentialTypeEntity.class,
|
||||||
|
AttributeTypeEntity.class,
|
||||||
|
RealmEntity.class,
|
||||||
|
ApplicationEntity.class
|
||||||
|
)
|
||||||
|
.supportGlobalRelationship(org.picketlink.idm.model.Relationship.class)
|
||||||
|
.addContextInitializer(new JPAContextInitializer(null) {
|
||||||
|
@Override
|
||||||
|
public EntityManager getEntityManager() {
|
||||||
|
return PicketlinkKeycloakSession.currentEntityManager.get();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.supportAllFeatures();
|
||||||
|
|
||||||
|
DefaultPartitionManager partitionManager = new DefaultPartitionManager(builder.buildAll());
|
||||||
|
return partitionManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,11 +2,25 @@ package org.keycloak.models.picketlink;
|
||||||
|
|
||||||
import org.bouncycastle.openssl.PEMWriter;
|
import org.bouncycastle.openssl.PEMWriter;
|
||||||
import org.keycloak.PemUtils;
|
import org.keycloak.PemUtils;
|
||||||
import org.keycloak.models.*;
|
import org.keycloak.models.ApplicationModel;
|
||||||
import org.keycloak.models.picketlink.mappings.RealmData;
|
import org.keycloak.models.IdGenerator;
|
||||||
|
import org.keycloak.models.KeycloakSession;
|
||||||
|
import org.keycloak.models.OAuthClientModel;
|
||||||
|
import org.keycloak.models.RealmModel;
|
||||||
|
import org.keycloak.models.RequiredCredentialModel;
|
||||||
|
import org.keycloak.models.RoleModel;
|
||||||
|
import org.keycloak.models.SocialLinkModel;
|
||||||
|
import org.keycloak.models.UserCredentialModel;
|
||||||
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.models.picketlink.mappings.ApplicationData;
|
import org.keycloak.models.picketlink.mappings.ApplicationData;
|
||||||
import org.keycloak.models.picketlink.relationships.*;
|
import org.keycloak.models.picketlink.mappings.RealmData;
|
||||||
|
import org.keycloak.models.picketlink.relationships.ApplicationRelationship;
|
||||||
|
import org.keycloak.models.picketlink.relationships.OAuthClientRelationship;
|
||||||
|
import org.keycloak.models.picketlink.relationships.OAuthClientRequiredCredentialRelationship;
|
||||||
import org.keycloak.models.picketlink.relationships.RequiredApplicationCredentialRelationship;
|
import org.keycloak.models.picketlink.relationships.RequiredApplicationCredentialRelationship;
|
||||||
|
import org.keycloak.models.picketlink.relationships.RequiredCredentialRelationship;
|
||||||
|
import org.keycloak.models.picketlink.relationships.ScopeRelationship;
|
||||||
|
import org.keycloak.models.picketlink.relationships.SocialLinkRelationship;
|
||||||
import org.picketlink.idm.IdentityManager;
|
import org.picketlink.idm.IdentityManager;
|
||||||
import org.picketlink.idm.PartitionManager;
|
import org.picketlink.idm.PartitionManager;
|
||||||
import org.picketlink.idm.RelationshipManager;
|
import org.picketlink.idm.RelationshipManager;
|
||||||
|
@ -601,7 +615,6 @@ public class RealmAdapter implements RealmModel {
|
||||||
idm.add(resourceUser);
|
idm.add(resourceUser);
|
||||||
applicationData.setResourceUser(resourceUser);
|
applicationData.setResourceUser(resourceUser);
|
||||||
applicationData.setResourceName(name);
|
applicationData.setResourceName(name);
|
||||||
applicationData.setResourceUser(resourceUser);
|
|
||||||
partitionManager.add(applicationData);
|
partitionManager.add(applicationData);
|
||||||
ApplicationRelationship resourceRelationship = new ApplicationRelationship();
|
ApplicationRelationship resourceRelationship = new ApplicationRelationship();
|
||||||
resourceRelationship.setRealm(realm.getName());
|
resourceRelationship.setRealm(realm.getName());
|
||||||
|
@ -875,23 +888,23 @@ public class RealmAdapter implements RealmModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashMap<String, String> getSmtpConfig() {
|
public Map<String, String> getSmtpConfig() {
|
||||||
return realm.getSmtpConfig();
|
return realm.getSmtpConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSmtpConfig(HashMap<String, String> smtpConfig) {
|
public void setSmtpConfig(Map<String, String> smtpConfig) {
|
||||||
realm.setSmtpConfig(smtpConfig);
|
realm.setSmtpConfig(smtpConfig);
|
||||||
updateRealm();
|
updateRealm();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public HashMap<String, String> getSocialConfig() {
|
public Map<String, String> getSocialConfig() {
|
||||||
return realm.getSocialConfig();
|
return realm.getSocialConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSocialConfig(HashMap<String, String> socialConfig) {
|
public void setSocialConfig(Map<String, String> socialConfig) {
|
||||||
realm.setSocialConfig(socialConfig);
|
realm.setSocialConfig(socialConfig);
|
||||||
updateRealm();
|
updateRealm();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,16 @@
|
||||||
package org.keycloak.models.picketlink;
|
package org.keycloak.models.picketlink;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.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.sample.User;
|
import org.picketlink.idm.model.sample.User;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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 $
|
||||||
|
|
|
@ -3,8 +3,7 @@ package org.keycloak.models.picketlink.mappings;
|
||||||
import org.picketlink.idm.model.AbstractPartition;
|
import org.picketlink.idm.model.AbstractPartition;
|
||||||
import org.picketlink.idm.model.annotation.AttributeProperty;
|
import org.picketlink.idm.model.annotation.AttributeProperty;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.util.Map;
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
* @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
|
||||||
|
@ -26,8 +25,8 @@ public class RealmData extends AbstractPartition {
|
||||||
private String publicKeyPem;
|
private String publicKeyPem;
|
||||||
private String privateKeyPem;
|
private String privateKeyPem;
|
||||||
private String[] defaultRoles;
|
private String[] defaultRoles;
|
||||||
private HashMap<String, String> smtpConfig;
|
private Map<String, String> smtpConfig;
|
||||||
private HashMap<String, String> socialConfig;
|
private Map<String, String> socialConfig;
|
||||||
|
|
||||||
public RealmData() {
|
public RealmData() {
|
||||||
super(null);
|
super(null);
|
||||||
|
@ -170,20 +169,20 @@ public class RealmData extends AbstractPartition {
|
||||||
}
|
}
|
||||||
|
|
||||||
@AttributeProperty
|
@AttributeProperty
|
||||||
public HashMap<String, String> getSmtpConfig() {
|
public Map<String, String> getSmtpConfig() {
|
||||||
return smtpConfig;
|
return smtpConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSmtpConfig(HashMap<String, String> smtpConfig) {
|
public void setSmtpConfig(Map<String, String> smtpConfig) {
|
||||||
this.smtpConfig = smtpConfig;
|
this.smtpConfig = smtpConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@AttributeProperty
|
@AttributeProperty
|
||||||
public HashMap<String, String> getSocialConfig() {
|
public Map<String, String> getSocialConfig() {
|
||||||
return socialConfig;
|
return socialConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSocialConfig(HashMap<String, String> socialConfig) {
|
public void setSocialConfig(Map<String, String> socialConfig) {
|
||||||
this.socialConfig = socialConfig;
|
this.socialConfig = socialConfig;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,11 @@ import org.picketlink.idm.jpa.annotations.OwnerReference;
|
||||||
import org.picketlink.idm.jpa.annotations.entity.IdentityManaged;
|
import org.picketlink.idm.jpa.annotations.entity.IdentityManaged;
|
||||||
import org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity;
|
import org.picketlink.idm.jpa.model.sample.simple.PartitionTypeEntity;
|
||||||
|
|
||||||
import javax.persistence.*;
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.Lob;
|
||||||
|
import javax.persistence.OneToOne;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,7 @@ package org.keycloak.models.picketlink.relationships;
|
||||||
import org.picketlink.idm.model.AbstractAttributedType;
|
import org.picketlink.idm.model.AbstractAttributedType;
|
||||||
import org.picketlink.idm.model.Attribute;
|
import org.picketlink.idm.model.Attribute;
|
||||||
import org.picketlink.idm.model.Relationship;
|
import org.picketlink.idm.model.Relationship;
|
||||||
import org.picketlink.idm.model.sample.User;
|
|
||||||
import org.picketlink.idm.query.AttributeParameter;
|
import org.picketlink.idm.query.AttributeParameter;
|
||||||
import org.picketlink.idm.query.RelationshipQueryParameter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Picketlink doesn't allow you to query for all partitions, thus this stupid relationship...
|
* Picketlink doesn't allow you to query for all partitions, thus this stupid relationship...
|
||||||
|
|
|
@ -37,6 +37,6 @@
|
||||||
<module>api</module>
|
<module>api</module>
|
||||||
<module>picketlink</module>
|
<module>picketlink</module>
|
||||||
<module>jpa</module>
|
<module>jpa</module>
|
||||||
<!--<module>mongo</module>-->
|
<module>mongo</module>
|
||||||
</modules>
|
</modules>
|
||||||
</project>
|
</project>
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -9,7 +9,7 @@
|
||||||
<packaging>pom</packaging>
|
<packaging>pom</packaging>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<resteasy.version>3.0.4.Final</resteasy.version>
|
<resteasy.version>3.0.5.Final</resteasy.version>
|
||||||
<undertow.version>1.0.0.Beta12</undertow.version>
|
<undertow.version>1.0.0.Beta12</undertow.version>
|
||||||
<picketlink.version>2.5.0.Beta6</picketlink.version>
|
<picketlink.version>2.5.0.Beta6</picketlink.version>
|
||||||
<mongo.driver.version>2.11.2</mongo.driver.version>
|
<mongo.driver.version>2.11.2</mongo.driver.version>
|
||||||
|
|
|
@ -33,6 +33,12 @@
|
||||||
<groupId>org.keycloak</groupId>
|
<groupId>org.keycloak</groupId>
|
||||||
<artifactId>keycloak-model-picketlink</artifactId>
|
<artifactId>keycloak-model-picketlink</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.keycloak</groupId>
|
||||||
|
<artifactId>keycloak-model-jpa</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--<dependency>
|
<!--<dependency>
|
||||||
|
|
|
@ -21,21 +21,20 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.services;
|
package org.keycloak.services;
|
||||||
|
|
||||||
import java.net.URI;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import javax.imageio.spi.ServiceRegistry;
|
|
||||||
import javax.ws.rs.core.MultivaluedMap;
|
|
||||||
|
|
||||||
import org.keycloak.models.RealmModel;
|
import org.keycloak.models.RealmModel;
|
||||||
import org.keycloak.models.RoleModel;
|
import org.keycloak.models.RoleModel;
|
||||||
import org.keycloak.models.UserModel;
|
import org.keycloak.models.UserModel;
|
||||||
import org.keycloak.services.resources.flows.FormFlows;
|
import org.keycloak.services.resources.flows.FormFlows;
|
||||||
import org.keycloak.social.SocialProvider;
|
import org.keycloak.social.SocialProvider;
|
||||||
|
|
||||||
|
import javax.imageio.spi.ServiceRegistry;
|
||||||
|
import javax.ws.rs.core.MultivaluedMap;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
|
* @author <a href="mailto:vrockai@redhat.com">Viliam Rockai</a>
|
||||||
*/
|
*/
|
||||||
|
@ -95,7 +94,7 @@ public interface FormService {
|
||||||
this.message = message;
|
this.message = message;
|
||||||
|
|
||||||
socialProviders = new LinkedList<SocialProvider>();
|
socialProviders = new LinkedList<SocialProvider>();
|
||||||
HashMap<String, String> socialConfig = realm.getSocialConfig();
|
Map<String, String> socialConfig = realm.getSocialConfig();
|
||||||
if (socialConfig != null) {
|
if (socialConfig != null) {
|
||||||
for (Iterator<SocialProvider> itr = ServiceRegistry.lookupProviders(org.keycloak.social.SocialProvider.class); itr.hasNext(); ) {
|
for (Iterator<SocialProvider> itr = ServiceRegistry.lookupProviders(org.keycloak.social.SocialProvider.class); itr.hasNext(); ) {
|
||||||
SocialProvider p = itr.next();
|
SocialProvider p = itr.next();
|
||||||
|
|
|
@ -21,28 +21,25 @@
|
||||||
*/
|
*/
|
||||||
package org.keycloak.services.email;
|
package org.keycloak.services.email;
|
||||||
|
|
||||||
import java.net.URI;
|
import org.jboss.resteasy.logging.Logger;
|
||||||
import java.util.Map;
|
import org.keycloak.models.RealmModel;
|
||||||
import java.util.Map.Entry;
|
import org.keycloak.models.UserModel;
|
||||||
import java.util.Properties;
|
import org.keycloak.services.managers.AccessCodeEntry;
|
||||||
import java.util.concurrent.TimeUnit;
|
import org.keycloak.services.resources.flows.Urls;
|
||||||
|
|
||||||
import javax.mail.Message;
|
import javax.mail.Message;
|
||||||
import javax.mail.MessagingException;
|
import javax.mail.MessagingException;
|
||||||
import javax.mail.Session;
|
import javax.mail.Session;
|
||||||
import javax.mail.Transport;
|
import javax.mail.Transport;
|
||||||
import javax.mail.internet.AddressException;
|
|
||||||
import javax.mail.internet.InternetAddress;
|
import javax.mail.internet.InternetAddress;
|
||||||
import javax.mail.internet.MimeMessage;
|
import javax.mail.internet.MimeMessage;
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
import javax.ws.rs.core.UriInfo;
|
import javax.ws.rs.core.UriInfo;
|
||||||
|
import java.net.URI;
|
||||||
import org.jboss.resteasy.logging.Logger;
|
import java.util.Map;
|
||||||
import org.keycloak.services.managers.AccessCodeEntry;
|
import java.util.Map.Entry;
|
||||||
import org.keycloak.models.RealmModel;
|
import java.util.Properties;
|
||||||
import org.keycloak.models.UserModel;
|
import java.util.concurrent.TimeUnit;
|
||||||
import org.keycloak.services.resources.AccountService;
|
|
||||||
import org.keycloak.services.resources.flows.Urls;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
* @author <a href="mailto:sthorger@redhat.com">Stian Thorgersen</a>
|
||||||
|
|
|
@ -5,7 +5,12 @@ import org.keycloak.models.KeycloakSession;
|
||||||
import org.keycloak.models.KeycloakSessionFactory;
|
import org.keycloak.models.KeycloakSessionFactory;
|
||||||
import org.keycloak.models.KeycloakTransaction;
|
import org.keycloak.models.KeycloakTransaction;
|
||||||
|
|
||||||
import javax.servlet.*;
|
import javax.servlet.Filter;
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.FilterConfig;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.ServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue