diff --git a/core/pom.xml b/core/pom.xml index 56f2396f4f..760584f736 100755 --- a/core/pom.xml +++ b/core/pom.xml @@ -29,15 +29,10 @@ provided - javax.servlet - servlet-api + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec provided - - org.jboss.resteasy - tjws - test - junit junit diff --git a/examples/as7-eap-demo/customer-app/pom.xml b/examples/as7-eap-demo/customer-app/pom.xml index bdd517d293..fb580bf344 100755 --- a/examples/as7-eap-demo/customer-app/pom.xml +++ b/examples/as7-eap-demo/customer-app/pom.xml @@ -23,9 +23,9 @@ - - javax.servlet - servlet-api + + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec provided diff --git a/examples/as7-eap-demo/product-app/pom.xml b/examples/as7-eap-demo/product-app/pom.xml index 92563e77b1..7172325095 100755 --- a/examples/as7-eap-demo/product-app/pom.xml +++ b/examples/as7-eap-demo/product-app/pom.xml @@ -24,8 +24,8 @@ - javax.servlet - servlet-api + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec provided diff --git a/examples/as7-eap-demo/server/src/main/java/org/keycloak/example/demo/DemoApplication.java b/examples/as7-eap-demo/server/src/main/java/org/keycloak/example/demo/DemoApplication.java index 29045058d7..b7c11f217b 100755 --- a/examples/as7-eap-demo/server/src/main/java/org/keycloak/example/demo/DemoApplication.java +++ b/examples/as7-eap-demo/server/src/main/java/org/keycloak/example/demo/DemoApplication.java @@ -11,6 +11,8 @@ import org.keycloak.services.resources.KeycloakApplication; import org.keycloak.services.resources.SaasService; import org.keycloak.services.resources.SaasService; +import javax.servlet.ServletContext; +import javax.ws.rs.core.Context; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -20,8 +22,8 @@ import java.io.InputStream; */ public class DemoApplication extends KeycloakApplication { - public DemoApplication() { - super(); + public DemoApplication(@Context ServletContext servletContext) { + super(servletContext); KeycloakSession session = factory.createSession(); session.getTransaction().begin(); RealmManager realmManager = new RealmManager(session); diff --git a/examples/as7-eap-demo/server/src/main/webapp/WEB-INF/web.xml b/examples/as7-eap-demo/server/src/main/webapp/WEB-INF/web.xml index 4c6404bb9c..6829b0e56e 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/WEB-INF/web.xml +++ b/examples/as7-eap-demo/server/src/main/webapp/WEB-INF/web.xml @@ -21,6 +21,16 @@ true + + Keycloak Session Management + org.keycloak.services.filters.KeycloakSessionServletFilter + + + + Keycloak Session Management + /rest/* + + Resteasy /rest/* diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js index 6afcfedcca..ca2382613d 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js +++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/app.js @@ -55,11 +55,8 @@ module.config([ '$routeProvider', function($routeProvider) { resolve : { realm : function(RealmLoader) { return RealmLoader(); - }, - users : function(UserListLoader) { - return UserListLoader(); } - }, + }, controller : 'UserListCtrl' }) diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js index 868099055a..edfa8d915e 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js +++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/controllers.js @@ -181,15 +181,39 @@ module.controller('RealmDetailCtrl', function($scope, Current, Realm, realm, $ht }); -module.controller('UserListCtrl', function($scope, realm, users) { +module.controller('UserListCtrl', function($scope, realm, User) { $scope.realm = realm; - $scope.users = users; + $scope.users = []; + $scope.query = "*"; + $scope.attribute = {}; + var params = {}; + + $scope.addAttribute = function() { + console.log('queryAttribute'); + params[$scope.attribute.name] = $scope.attribute.value; + for (var key in params) { + $scope.query = " " + key + "=" +params[key]; + } + }; + + $scope.executeQuery = function() { + console.log('executeQuery'); + var parameters = angular.copy(params); + parameters["realm"] = realm.id; + $scope.users = User.query(parameters); + }; + + $scope.clearQuery = function() { + params = {}; + $scopre.query = "*"; + $scope.users = []; + }; }); module.controller('UserDetailCtrl', function($scope, realm, user, User, $location, Dialog, Notifications) { $scope.realm = realm; $scope.user = angular.copy(user); - $scope.create = !user.userId; + $scope.create = !user.username; $scope.changed = $scope.create; @@ -201,23 +225,28 @@ module.controller('UserDetailCtrl', function($scope, realm, user, User, $locatio $scope.save = function() { if ($scope.userForm.$valid) { + if ($scope.create) { + User.save({ + realm: realm.id + }, $scope.user, function () { + $scope.changed = false; + user = angular.copy($scope.user); + $location.url("/realms/" + realm.id + "/users/" + $scope.user.username); + Notifications.success("Created user"); + }); + } else { + User.update({ + realm: realm.id, + userId: $scope.user.username + }, $scope.user, function () { + $scope.changed = false; + user = angular.copy($scope.user); + Notifications.success("Saved changes to user"); + }); - - User.save({ - realm : realm.id - }, $scope.user, function() { - $scope.changed = false; - user = angular.copy($scope.user); - - if ($scope.create) { - $location.url("/realms/" + realm.id + "/users/" + $scope.user.userId); - Notifications.success("Created user"); - } else { - Notifications.success("Saved changes to user"); - } - }); - } else { + } + } else { $scope.userForm.showErrors = true; } }; @@ -236,7 +265,7 @@ module.controller('UserDetailCtrl', function($scope, realm, user, User, $locatio Dialog.confirmDelete($scope.user.userId, 'user', function() { $scope.user.$remove({ realm : realm.id, - userId : $scope.user.userId + userId : $scope.user.username }, function() { $location.url("/realms/" + realm.id + "/users"); Notifications.success("Deleted user"); diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js index b3cd88f479..1b70951623 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js +++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/js/services.js @@ -110,11 +110,11 @@ module.factory('RoleMapping', function($resource) { }); module.factory('User', function($resource) { - return $resource('/keycloak-server/ui/api/realms/:realm/users/:userId', { + return $resource('/auth-server/rest/saas/admin/realms/:realm/users/:userId', { realm : '@realm', userId : '@userId' }, { - save : { + update : { method : 'PUT' } }); diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-menu.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-menu.html index fc10132619..ae5217a1d3 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-menu.html +++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/realm-menu.html @@ -6,7 +6,7 @@
  • New User
  • Find User
  • + href="#/realms/{{realm.id}}/users">Find User
  • Roles diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-detail.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-detail.html index a2ea839fcd..0c68075d40 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-detail.html +++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/role-detail.html @@ -13,13 +13,13 @@
    Please fill in all required fields
    -

    * Required fields

    +

    * Required fields

    Details
    - +
    - Add Role -

    Realm Roles

    diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/user-detail.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/user-detail.html index 67af006519..bcd7d20f6d 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/user-detail.html +++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/user-detail.html @@ -7,26 +7,35 @@

    New User

    - {{user.userId}} configuration + User {{user.username}}

    Please fill in all required fields
    -

    * Required fields

    +

    * Required fields

    Details
    - +
    -
    +
    + + +
    + +
    +
    +
    @@ -52,15 +61,6 @@
    - -
    - - -
    - -
    -
    @@ -94,7 +94,6 @@ - View users » diff --git a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/user-list.html b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/user-list.html index 43957a735a..59dd555185 100755 --- a/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/user-list.html +++ b/examples/as7-eap-demo/server/src/main/webapp/saas/admin/partials/user-list.html @@ -3,13 +3,42 @@
    +
    - Add User + +
    + -

    - {{realm.name}} users -

    +
    + + +
    +
    + +
    +
    +
    + + +
    + + + +
    +
    +
    +
    @@ -20,7 +49,7 @@ - + diff --git a/integration/as7-eap6/adapter/pom.xml b/integration/as7-eap6/adapter/pom.xml index 69c4ff1188..11e11e95b2 100755 --- a/integration/as7-eap6/adapter/pom.xml +++ b/integration/as7-eap6/adapter/pom.xml @@ -33,7 +33,6 @@ org.jboss.spec.javax.servlet jboss-servlet-api_3.0_spec - 1.0.0.Final provided diff --git a/pom.xml b/pom.xml index 9a1da75b5c..6310d17829 100755 --- a/pom.xml +++ b/pom.xml @@ -9,7 +9,8 @@ pom - 3.0.2.Final + 3.0.4.Final + 1.0.0.Beta12 2.5.0.Beta6 @@ -108,7 +109,21 @@ org.jboss.resteasy tjws ${resteasy.version} - provided + + + org.jboss.resteasy + resteasy-undertow + ${resteasy.version} + + + io.undertow + undertow-servlet + ${undertow.version} + + + io.undertow + undertow-core + ${undertow.version} org.codehaus.jackson @@ -131,9 +146,9 @@ 1.9.12 - javax.servlet - servlet-api - 2.5 + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec + 1.0.1.Final org.jboss.resteasy diff --git a/services/pom.xml b/services/pom.xml index 74452e2074..02f2c8ae9a 100755 --- a/services/pom.xml +++ b/services/pom.xml @@ -79,12 +79,7 @@ - - org.jboss.resteasy - tjws - test - - + org.jboss.resteasy jaxrs-api provided @@ -105,13 +100,18 @@ provided - javax.servlet - servlet-api + org.jboss.resteasy + resteasy-undertow test - org.jboss.resteasy - tjws + io.undertow + undertow-servlet + test + + + io.undertow + undertow-core test @@ -124,6 +124,11 @@ jackson-mapper-asl provided + + org.jboss.spec.javax.servlet + jboss-servlet-api_3.0_spec + provided + org.codehaus.jackson jackson-xc diff --git a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionCreateFilter.java b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionCreateFilter.java index 870aec9772..cc0eb284e4 100755 --- a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionCreateFilter.java +++ b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionCreateFilter.java @@ -7,8 +7,6 @@ import org.keycloak.services.models.KeycloakSessionFactory; import javax.ws.rs.container.ContainerRequestContext; import javax.ws.rs.container.ContainerRequestFilter; -import javax.ws.rs.container.ContainerResponseContext; -import javax.ws.rs.container.ContainerResponseFilter; import javax.ws.rs.container.PreMatching; import java.io.IOException; diff --git a/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java new file mode 100755 index 0000000000..6506300a21 --- /dev/null +++ b/services/src/main/java/org/keycloak/services/filters/KeycloakSessionServletFilter.java @@ -0,0 +1,56 @@ +package org.keycloak.services.filters; + +import org.jboss.resteasy.spi.ResteasyProviderFactory; +import org.keycloak.services.models.KeycloakSession; +import org.keycloak.services.models.KeycloakSessionFactory; +import org.keycloak.services.models.KeycloakTransaction; + +import javax.servlet.*; +import java.io.IOException; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class KeycloakSessionServletFilter implements Filter { + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + KeycloakSessionFactory factory = (KeycloakSessionFactory)servletRequest.getServletContext().getAttribute(KeycloakSessionFactory.class.getName()); + if (factory == null) throw new ServletException("Factory was null"); + KeycloakSession session = factory.createSession(); + ResteasyProviderFactory.pushContext(KeycloakSession.class, session); + KeycloakTransaction tx = session.getTransaction(); + ResteasyProviderFactory.pushContext(KeycloakTransaction.class, tx); + tx.begin(); + try { + filterChain.doFilter(servletRequest, servletResponse); + if (tx.isActive()) { + if (tx.getRollbackOnly()) tx.rollback(); + else tx.commit(); + } + } catch (IOException ex) { + if (tx.isActive()) tx.rollback(); + throw ex; + } catch (ServletException ex) { + if (tx.isActive()) tx.rollback(); + throw ex; + } + catch (RuntimeException ex) { + if (tx.isActive()) tx.rollback(); + throw ex; + } finally { + session.close(); + ResteasyProviderFactory.clearContextData(); + } + + } + + @Override + public void destroy() { + } +} diff --git a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java index 728df77484..aef5b36d16 100755 --- a/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java +++ b/services/src/main/java/org/keycloak/services/managers/AuthenticationManager.java @@ -16,11 +16,7 @@ import org.keycloak.services.resources.RealmsResource; import org.keycloak.services.resources.SaasService; import javax.ws.rs.NotAuthorizedException; -import javax.ws.rs.core.Cookie; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.NewCookie; -import javax.ws.rs.core.UriInfo; +import javax.ws.rs.core.*; import java.net.URI; import java.util.HashSet; import java.util.List; diff --git a/services/src/main/java/org/keycloak/services/managers/RealmManager.java b/services/src/main/java/org/keycloak/services/managers/RealmManager.java index 603fc56786..cdbed7f54f 100755 --- a/services/src/main/java/org/keycloak/services/managers/RealmManager.java +++ b/services/src/main/java/org/keycloak/services/managers/RealmManager.java @@ -7,7 +7,10 @@ import org.keycloak.services.models.*; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.NoSuchAlgorithmException; -import java.util.*; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.concurrent.atomic.AtomicLong; /** diff --git a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java index fb1d342f81..fd06088b6a 100755 --- a/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java +++ b/services/src/main/java/org/keycloak/services/managers/ResourceAdminManager.java @@ -5,8 +5,8 @@ import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; import org.jboss.resteasy.logging.Logger; import org.keycloak.TokenIdGenerator; import org.keycloak.representations.idm.admin.LogoutAction; -import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.ApplicationModel; +import org.keycloak.services.models.RealmModel; import javax.ws.rs.client.Entity; import javax.ws.rs.core.Form; diff --git a/services/src/main/java/org/keycloak/services/managers/ResourceManager.java b/services/src/main/java/org/keycloak/services/managers/ResourceManager.java index 85c2a7a42a..5da6c8c06c 100755 --- a/services/src/main/java/org/keycloak/services/managers/ResourceManager.java +++ b/services/src/main/java/org/keycloak/services/managers/ResourceManager.java @@ -1,12 +1,7 @@ package org.keycloak.services.managers; import org.keycloak.representations.idm.*; -import org.keycloak.representations.idm.ApplicationRepresentation; -import org.keycloak.services.models.RealmModel; -import org.keycloak.services.models.ApplicationModel; -import org.keycloak.services.models.RoleModel; -import org.keycloak.services.models.UserCredentialModel; -import org.keycloak.services.models.UserModel; +import org.keycloak.services.models.*; /** * @author Bill Burke diff --git a/services/src/main/java/org/keycloak/services/managers/TokenManager.java b/services/src/main/java/org/keycloak/services/managers/TokenManager.java index 9557cb76ae..c195e8306f 100755 --- a/services/src/main/java/org/keycloak/services/managers/TokenManager.java +++ b/services/src/main/java/org/keycloak/services/managers/TokenManager.java @@ -5,8 +5,8 @@ import org.jboss.resteasy.jose.jws.JWSBuilder; import org.jboss.resteasy.jwt.JsonSerialization; import org.keycloak.representations.SkeletonKeyScope; import org.keycloak.representations.SkeletonKeyToken; -import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.ApplicationModel; +import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.RoleModel; import org.keycloak.services.models.UserModel; diff --git a/services/src/main/java/org/keycloak/services/managers/UserManager.java b/services/src/main/java/org/keycloak/services/managers/UserManager.java new file mode 100755 index 0000000000..677301663d --- /dev/null +++ b/services/src/main/java/org/keycloak/services/managers/UserManager.java @@ -0,0 +1,89 @@ +package org.keycloak.services.managers; + +import org.keycloak.representations.idm.CredentialRepresentation; +import org.keycloak.representations.idm.UserRepresentation; +import org.keycloak.services.models.RealmModel; +import org.keycloak.services.models.UserCredentialModel; +import org.keycloak.services.models.UserModel; + +import java.util.Map; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class UserManager { + + public static UserRepresentation toRepresentation(UserModel user) { + UserRepresentation rep = new UserRepresentation(); + rep.setEmail(user.getEmail()); + rep.setLastName(user.getLastName()); + rep.setFirstName(user.getFirstName()); + rep.setEnabled(user.isEnabled()); + rep.setUsername(user.getLoginName()); + for (Map.Entry entry : user.getAttributes().entrySet()) { + rep.attribute(entry.getKey(), entry.getValue()); + } + return rep; + } + + public UserModel createUser(RealmModel newRealm, UserRepresentation userRep) { + UserModel user = newRealm.addUser(userRep.getUsername()); + user.setEnabled(userRep.isEnabled()); + user.setEmail(userRep.getEmail()); + user.setFirstName(userRep.getFirstName()); + user.setLastName(userRep.getLastName()); + if (userRep.getAttributes() != null) { + for (Map.Entry entry : userRep.getAttributes().entrySet()) { + user.setAttribute(entry.getKey(), entry.getValue()); + } + } + if (userRep.getCredentials() != null) { + for (CredentialRepresentation cred : userRep.getCredentials()) { + UserCredentialModel credential = new UserCredentialModel(); + credential.setType(cred.getType()); + credential.setValue(cred.getValue()); + newRealm.updateCredential(user, credential); + } + } + return user; + } + + /** + * Doesn't allow you to change loginname. + * + * @param user + * @param userRep + */ + public void updateUserAsAdmin(UserModel user, UserRepresentation userRep) { + user.setEnabled(userRep.isEnabled()); + user.setEmail(userRep.getEmail()); + user.setFirstName(userRep.getFirstName()); + user.setLastName(userRep.getLastName()); + if (userRep.getAttributes() != null) { + for (Map.Entry entry : userRep.getAttributes().entrySet()) { + user.setAttribute(entry.getKey(), entry.getValue()); + } + } + } + + /** + * Doesn't allow you to change loginname. + * Doesn't allow you to change enable + * + * @param user + * @param userRep + */ + public void updateUserAsUser(UserModel user, UserRepresentation userRep) { + user.setEmail(userRep.getEmail()); + user.setFirstName(userRep.getFirstName()); + user.setLastName(userRep.getLastName()); + if (userRep.getAttributes() != null) { + for (Map.Entry entry : userRep.getAttributes().entrySet()) { + user.setAttribute(entry.getKey(), entry.getValue()); + } + } + } + + +} diff --git a/services/src/main/java/org/keycloak/services/models/UserModel.java b/services/src/main/java/org/keycloak/services/models/UserModel.java index f6eccf2572..83585debd2 100755 --- a/services/src/main/java/org/keycloak/services/models/UserModel.java +++ b/services/src/main/java/org/keycloak/services/models/UserModel.java @@ -7,6 +7,10 @@ import java.util.Map; * @version $Revision: 1 $ */ public interface UserModel { + public static final String LAST_NAME = "lastName"; + public static final String FIRST_NAME = "firstName"; + public static final String EMAIL = "email"; + String getLoginName(); boolean isEnabled(); diff --git a/services/src/main/java/org/keycloak/services/models/jpa/entities/RealmEntity.java b/services/src/main/java/org/keycloak/services/models/jpa/entities/RealmEntity.java index bb55046c0c..a199f86409 100755 --- a/services/src/main/java/org/keycloak/services/models/jpa/entities/RealmEntity.java +++ b/services/src/main/java/org/keycloak/services/models/jpa/entities/RealmEntity.java @@ -1,13 +1,7 @@ package org.keycloak.services.models.jpa.entities; -import javax.persistence.CascadeType; -import javax.persistence.Column; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.MapKey; -import javax.persistence.OneToMany; +import javax.persistence.*; import java.util.Collection; /** diff --git a/services/src/main/java/org/keycloak/services/models/jpa/entities/ResourceEntity.java b/services/src/main/java/org/keycloak/services/models/jpa/entities/ResourceEntity.java index 1dfca39e8d..fa3b3c2234 100755 --- a/services/src/main/java/org/keycloak/services/models/jpa/entities/ResourceEntity.java +++ b/services/src/main/java/org/keycloak/services/models/jpa/entities/ResourceEntity.java @@ -1,13 +1,6 @@ package org.keycloak.services.models.jpa.entities; -import javax.persistence.CascadeType; -import javax.persistence.Entity; -import javax.persistence.FetchType; -import javax.persistence.GeneratedValue; -import javax.persistence.Id; -import javax.persistence.ManyToOne; -import javax.persistence.OneToMany; -import javax.persistence.OneToOne; +import javax.persistence.*; import java.util.Collection; /** diff --git a/services/src/main/java/org/keycloak/services/models/jpa/entities/UserRoleMappingEntity.java b/services/src/main/java/org/keycloak/services/models/jpa/entities/UserRoleMappingEntity.java index b7f2d111d2..ae68f9720c 100755 --- a/services/src/main/java/org/keycloak/services/models/jpa/entities/UserRoleMappingEntity.java +++ b/services/src/main/java/org/keycloak/services/models/jpa/entities/UserRoleMappingEntity.java @@ -4,7 +4,6 @@ import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; import javax.persistence.ManyToOne; -import javax.persistence.OneToOne; /** * @author Bill Burke diff --git a/services/src/main/java/org/keycloak/services/models/picketlink/UserAdapter.java b/services/src/main/java/org/keycloak/services/models/picketlink/UserAdapter.java index be85c88d30..6fc083512c 100755 --- a/services/src/main/java/org/keycloak/services/models/picketlink/UserAdapter.java +++ b/services/src/main/java/org/keycloak/services/models/picketlink/UserAdapter.java @@ -3,7 +3,6 @@ package org.keycloak.services.models.picketlink; import org.keycloak.services.models.UserModel; import org.picketlink.idm.IdentityManager; import org.picketlink.idm.model.Attribute; -import org.picketlink.idm.model.annotation.AttributeProperty; import org.picketlink.idm.model.sample.User; import java.util.HashMap; diff --git a/services/src/main/java/org/keycloak/services/models/picketlink/mappings/ApplicationData.java b/services/src/main/java/org/keycloak/services/models/picketlink/mappings/ApplicationData.java index 9157ae39dd..f515f2875d 100755 --- a/services/src/main/java/org/keycloak/services/models/picketlink/mappings/ApplicationData.java +++ b/services/src/main/java/org/keycloak/services/models/picketlink/mappings/ApplicationData.java @@ -1,6 +1,5 @@ package org.keycloak.services.models.picketlink.mappings; -import org.picketlink.idm.jpa.annotations.AttributeValue; import org.picketlink.idm.model.AbstractPartition; import org.picketlink.idm.model.annotation.AttributeProperty; import org.picketlink.idm.model.sample.User; diff --git a/services/src/main/java/org/keycloak/services/models/picketlink/mappings/RealmData.java b/services/src/main/java/org/keycloak/services/models/picketlink/mappings/RealmData.java index aeb0ad75a2..d95e7ea6c1 100755 --- a/services/src/main/java/org/keycloak/services/models/picketlink/mappings/RealmData.java +++ b/services/src/main/java/org/keycloak/services/models/picketlink/mappings/RealmData.java @@ -1,6 +1,5 @@ package org.keycloak.services.models.picketlink.mappings; -import org.picketlink.idm.jpa.annotations.AttributeValue; import org.picketlink.idm.model.AbstractPartition; import org.picketlink.idm.model.annotation.AttributeProperty; diff --git a/services/src/main/java/org/keycloak/services/models/picketlink/relationships/RealmAdminRelationship.java b/services/src/main/java/org/keycloak/services/models/picketlink/relationships/RealmAdminRelationship.java index 59da8f881d..ab284ba425 100755 --- a/services/src/main/java/org/keycloak/services/models/picketlink/relationships/RealmAdminRelationship.java +++ b/services/src/main/java/org/keycloak/services/models/picketlink/relationships/RealmAdminRelationship.java @@ -1,10 +1,8 @@ package org.keycloak.services.models.picketlink.relationships; -import org.keycloak.services.models.picketlink.mappings.RealmData; import org.picketlink.idm.model.AbstractAttributedType; import org.picketlink.idm.model.Attribute; import org.picketlink.idm.model.Relationship; -import org.picketlink.idm.model.annotation.AttributeProperty; import org.picketlink.idm.model.sample.User; import org.picketlink.idm.query.AttributeParameter; import org.picketlink.idm.query.RelationshipQueryParameter; diff --git a/services/src/main/java/org/keycloak/services/resources/AccountService.java b/services/src/main/java/org/keycloak/services/resources/AccountService.java old mode 100644 new mode 100755 index 96f8564761..60faa761d5 --- a/services/src/main/java/org/keycloak/services/resources/AccountService.java +++ b/services/src/main/java/org/keycloak/services/resources/AccountService.java @@ -21,18 +21,6 @@ */ package org.keycloak.services.resources; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriInfo; -import javax.ws.rs.core.Response.Status; - import org.jboss.resteasy.spi.HttpRequest; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.services.managers.AuthenticationManager; @@ -45,6 +33,13 @@ import org.keycloak.services.resources.flows.FormFlows; import org.keycloak.services.validation.Validation; import org.picketlink.idm.credential.util.TimeBasedOTP; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.core.*; +import javax.ws.rs.core.Response.Status; + /** * @author Stian Thorgersen */ @@ -70,184 +65,151 @@ public class AccountService { @Path("access") @GET public Response accessPage() { - return new Transaction() { - protected Response callImpl() { - UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); - if (user != null) { - return Flows.forms(realm, request).setUser(user).forwardToAccess(); - } else { - return Response.status(Status.FORBIDDEN).build(); - } - } - }.call(); + UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); + if (user != null) { + return Flows.forms(realm, request).setUser(user).forwardToAccess(); + } else { + return Response.status(Status.FORBIDDEN).build(); + } } @Path("") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processAccountUpdate(final MultivaluedMap formData) { - return new Transaction() { - protected Response callImpl() { - UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); - if (user != null) { - user.setFirstName(formData.getFirst("firstName")); - user.setLastName(formData.getFirst("lastName")); - user.setEmail(formData.getFirst("email")); + UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); + if (user != null) { + user.setFirstName(formData.getFirst("firstName")); + user.setLastName(formData.getFirst("lastName")); + user.setEmail(formData.getFirst("email")); - return Flows.forms(realm, request).setUser(user).forwardToAccount(); - } else { - return Response.status(Status.FORBIDDEN).build(); - } - } - }.call(); + return Flows.forms(realm, request).setUser(user).forwardToAccount(); + } else { + return Response.status(Status.FORBIDDEN).build(); + } } @Path("totp") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processTotpUpdate(final MultivaluedMap formData) { - return new Transaction() { - protected Response callImpl() { - UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); - if (user != null) { - FormFlows forms = Flows.forms(realm, request); + UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); + if (user != null) { + FormFlows forms = Flows.forms(realm, request); - String totp = formData.getFirst("totp"); - String totpSecret = formData.getFirst("totpSecret"); + String totp = formData.getFirst("totp"); + String totpSecret = formData.getFirst("totpSecret"); - String error = null; + String error = null; - if (Validation.isEmpty(totp)) { - error = Messages.MISSING_TOTP; - } else if (!new TimeBasedOTP().validate(totp, totpSecret.getBytes())) { - error = Messages.INVALID_TOTP; - } - - if (error != null) { - return forms.setError(error).forwardToTotp(); - } - - UserCredentialModel credentials = new UserCredentialModel(); - credentials.setType(CredentialRepresentation.TOTP); - credentials.setValue(formData.getFirst("totpSecret")); - realm.updateCredential(user, credentials); - - if (!user.isEnabled() && "REQUIRED".equals(user.getAttribute("KEYCLOAK_TOTP"))) { - user.setEnabled(true); - } - - user.setAttribute("KEYCLOAK_TOTP", "ENABLED"); - - return Flows.forms(realm, request).setUser(user).forwardToTotp(); - } else { - return Response.status(Status.FORBIDDEN).build(); - } + if (Validation.isEmpty(totp)) { + error = Messages.MISSING_TOTP; + } else if (!new TimeBasedOTP().validate(totp, totpSecret.getBytes())) { + error = Messages.INVALID_TOTP; } - }.call(); + + if (error != null) { + return forms.setError(error).forwardToTotp(); + } + + UserCredentialModel credentials = new UserCredentialModel(); + credentials.setType(CredentialRepresentation.TOTP); + credentials.setValue(formData.getFirst("totpSecret")); + realm.updateCredential(user, credentials); + + if (!user.isEnabled() && "REQUIRED".equals(user.getAttribute("KEYCLOAK_TOTP"))) { + user.setEnabled(true); + } + + user.setAttribute("KEYCLOAK_TOTP", "ENABLED"); + + return Flows.forms(realm, request).setUser(user).forwardToTotp(); + } else { + return Response.status(Status.FORBIDDEN).build(); + } } @Path("password") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processPasswordUpdate(final MultivaluedMap formData) { - return new Transaction() { - protected Response callImpl() { - UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); - if (user != null) { - FormFlows forms = Flows.forms(realm, request).setUser(user); + UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); + if (user != null) { + FormFlows forms = Flows.forms(realm, request).setUser(user); - String password = formData.getFirst("password"); - String passwordNew = formData.getFirst("password-new"); - String passwordConfirm = formData.getFirst("password-confirm"); + String password = formData.getFirst("password"); + String passwordNew = formData.getFirst("password-new"); + String passwordConfirm = formData.getFirst("password-confirm"); - String error = null; + String error = null; - if (Validation.isEmpty(password)) { - error = Messages.MISSING_PASSWORD; - } else if (Validation.isEmpty(passwordNew)) { - error = Messages.MISSING_PASSWORD; - } else if (!passwordNew.equals(passwordConfirm)) { - error = Messages.INVALID_PASSWORD_CONFIRM; - } else if (!realm.validatePassword(user, password)) { - error = Messages.INVALID_PASSWORD_EXISTING; - } - - if (error != null) { - return forms.setError(error).forwardToPassword(); - } - - UserCredentialModel credentials = new UserCredentialModel(); - credentials.setType(CredentialRepresentation.PASSWORD); - credentials.setValue(passwordNew); - - realm.updateCredential(user, credentials); - - return Flows.forms(realm, request).setUser(user).forwardToPassword(); - } else { - return Response.status(Status.FORBIDDEN).build(); - } + if (Validation.isEmpty(password)) { + error = Messages.MISSING_PASSWORD; + } else if (Validation.isEmpty(passwordNew)) { + error = Messages.MISSING_PASSWORD; + } else if (!passwordNew.equals(passwordConfirm)) { + error = Messages.INVALID_PASSWORD_CONFIRM; + } else if (!realm.validatePassword(user, password)) { + error = Messages.INVALID_PASSWORD_EXISTING; } - }.call(); + + if (error != null) { + return forms.setError(error).forwardToPassword(); + } + + UserCredentialModel credentials = new UserCredentialModel(); + credentials.setType(CredentialRepresentation.PASSWORD); + credentials.setValue(passwordNew); + + realm.updateCredential(user, credentials); + + return Flows.forms(realm, request).setUser(user).forwardToPassword(); + } else { + return Response.status(Status.FORBIDDEN).build(); + } } @Path("") @GET public Response accountPage() { - return new Transaction() { - protected Response callImpl() { - UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); - if (user != null) { - return Flows.forms(realm, request).setUser(user).forwardToAccount(); - } else { - return Response.status(Status.FORBIDDEN).build(); - } - } - }.call(); + UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); + if (user != null) { + return Flows.forms(realm, request).setUser(user).forwardToAccount(); + } else { + return Response.status(Status.FORBIDDEN).build(); + } } @Path("social") @GET public Response socialPage() { - return new Transaction() { - protected Response callImpl() { - UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); - if (user != null) { - return Flows.forms(realm, request).setUser(user).forwardToSocial(); - } else { - return Response.status(Status.FORBIDDEN).build(); - } - } - }.call(); + UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); + if (user != null) { + return Flows.forms(realm, request).setUser(user).forwardToSocial(); + } else { + return Response.status(Status.FORBIDDEN).build(); + } } @Path("totp") @GET public Response totpPage() { - return new Transaction() { - protected Response callImpl() { - UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); - if (user != null) { - return Flows.forms(realm, request).setUser(user).forwardToTotp(); - } else { - return Response.status(Status.FORBIDDEN).build(); - } - } - }.call(); + UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); + if (user != null) { + return Flows.forms(realm, request).setUser(user).forwardToTotp(); + } else { + return Response.status(Status.FORBIDDEN).build(); + } } @Path("password") @GET public Response passwordPage() { - return new Transaction() { - protected Response callImpl() { - UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); - if (user != null) { - return Flows.forms(realm, request).setUser(user).forwardToPassword(); - } else { - return Response.status(Status.FORBIDDEN).build(); - } - } - }.call(); + UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); + if (user != null) { + return Flows.forms(realm, request).setUser(user).forwardToPassword(); + } else { + return Response.status(Status.FORBIDDEN).build(); + } } - } diff --git a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java index cd464248f7..104803ca39 100755 --- a/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java +++ b/services/src/main/java/org/keycloak/services/resources/KeycloakApplication.java @@ -1,7 +1,6 @@ package org.keycloak.services.resources; import org.keycloak.SkeletonKeyContextResolver; -import org.keycloak.services.filters.KeycloakSessionCleanupFilter; import org.keycloak.services.managers.TokenManager; import org.keycloak.services.models.KeycloakSessionFactory; import org.keycloak.services.models.picketlink.PicketlinkKeycloakSession; @@ -13,25 +12,15 @@ 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 org.picketlink.idm.jpa.model.sample.simple.*; import javax.annotation.PreDestroy; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; +import javax.servlet.ServletContext; import javax.ws.rs.core.Application; +import javax.ws.rs.core.Context; import java.util.HashSet; import java.util.Set; @@ -45,10 +34,11 @@ public class KeycloakApplication extends Application { protected KeycloakSessionFactory factory; - public KeycloakApplication() { + public KeycloakApplication(@Context ServletContext context) { KeycloakSessionFactory f = createSessionFactory(); this.factory = f; - classes.add(KeycloakSessionCleanupFilter.class); + context.setAttribute(KeycloakSessionFactory.class.getName(), factory); + //classes.add(KeycloakSessionCleanupFilter.class); TokenManager tokenManager = new TokenManager(); @@ -56,6 +46,7 @@ public class KeycloakApplication extends Application { singletons.add(new SocialResource(tokenManager, new SocialRequestManager())); classes.add(SkeletonKeyContextResolver.class); classes.add(SaasService.class); + } protected KeycloakSessionFactory createSessionFactory() { diff --git a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java index 7085eab839..e5550a0734 100755 --- a/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java +++ b/services/src/main/java/org/keycloak/services/resources/PublicRealmResource.java @@ -3,7 +3,6 @@ package org.keycloak.services.resources; import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.logging.Logger; import org.keycloak.representations.idm.PublishedRealmRepresentation; -import org.keycloak.services.models.KeycloakSession; import org.keycloak.services.models.RealmModel; import javax.ws.rs.GET; @@ -41,11 +40,7 @@ public class PublicRealmResource { @NoCache @Produces("application/json") public PublishedRealmRepresentation getRealm(@PathParam("realm") String id) { - return new Transaction() { - protected PublishedRealmRepresentation callImpl() { - return realmRep(realm, uriInfo); - } - }.call(); + return realmRep(realm, uriInfo); } @GET @@ -53,26 +48,22 @@ public class PublicRealmResource { @Path("html") @Produces("text/html") public String getRealmHtml(@PathParam("realm") String id) { - return new Transaction() { - protected String callImpl() { - StringBuffer html = new StringBuffer(); + StringBuffer html = new StringBuffer(); - String authUri = TokenService.loginPageUrl(uriInfo).build(realm.getId()).toString(); - String codeUri = TokenService.accessCodeToTokenUrl(uriInfo).build(realm.getId()).toString(); - String grantUrl = TokenService.grantAccessTokenUrl(uriInfo).build(realm.getId()).toString(); - String idGrantUrl = TokenService.grantIdentityTokenUrl(uriInfo).build(realm.getId()).toString(); + String authUri = TokenService.loginPageUrl(uriInfo).build(realm.getId()).toString(); + String codeUri = TokenService.accessCodeToTokenUrl(uriInfo).build(realm.getId()).toString(); + String grantUrl = TokenService.grantAccessTokenUrl(uriInfo).build(realm.getId()).toString(); + String idGrantUrl = TokenService.grantIdentityTokenUrl(uriInfo).build(realm.getId()).toString(); - html.append("

    Realm: ").append(realm.getName()).append("

    "); - html.append("

    auth: ").append(authUri).append("

    "); - html.append("

    code: ").append(codeUri).append("

    "); - html.append("

    grant: ").append(grantUrl).append("

    "); - html.append("

    identity grant: ").append(idGrantUrl).append("

    "); - html.append("

    public key: ").append(realm.getPublicKeyPem()).append("

    "); - html.append(""); + html.append("

    Realm: ").append(realm.getName()).append("

    "); + html.append("

    auth: ").append(authUri).append("

    "); + html.append("

    code: ").append(codeUri).append("

    "); + html.append("

    grant: ").append(grantUrl).append("

    "); + html.append("

    identity grant: ").append(idGrantUrl).append("

    "); + html.append("

    public key: ").append(realm.getPublicKeyPem()).append("

    "); + html.append(""); - return html.toString(); - } - }.call(); + return html.toString(); } diff --git a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java index b580484ea2..7ed4c14908 100755 --- a/services/src/main/java/org/keycloak/services/resources/RealmsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/RealmsResource.java @@ -1,26 +1,17 @@ package org.keycloak.services.resources; import org.jboss.resteasy.logging.Logger; -import org.keycloak.representations.idm.RealmRepresentation; -import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.TokenManager; +import org.keycloak.services.models.KeycloakSession; import org.keycloak.services.models.RealmModel; -import org.keycloak.services.models.RoleModel; -import org.keycloak.services.models.UserModel; -import org.keycloak.social.SocialRequestManager; -import javax.ws.rs.Consumes; -import javax.ws.rs.NotAuthorizedException; import javax.ws.rs.NotFoundException; -import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.container.ResourceContext; import javax.ws.rs.core.Context; import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; import javax.ws.rs.core.UriBuilder; import javax.ws.rs.core.UriInfo; @@ -39,7 +30,10 @@ public class RealmsResource { protected HttpHeaders headers; @Context - ResourceContext resourceContext; + protected ResourceContext resourceContext; + + @Context + protected KeycloakSession session; protected TokenManager tokenManager; @@ -53,57 +47,41 @@ public class RealmsResource { @Path("{realm}/tokens") public TokenService getTokenService(final @PathParam("realm") String id) { - return new Transaction(false) { - @Override - protected TokenService callImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.getRealm(id); - if (realm == null) { - logger.debug("realm not found"); - throw new NotFoundException(); - } - TokenService tokenService = new TokenService(realm, tokenManager); - resourceContext.initResource(tokenService); - return tokenService; - } - }.call(); - + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.getRealm(id); + if (realm == null) { + logger.debug("realm not found"); + throw new NotFoundException(); + } + TokenService tokenService = new TokenService(realm, tokenManager); + resourceContext.initResource(tokenService); + return tokenService; } @Path("{realm}/account") public AccountService getAccountService(final @PathParam("realm") String id) { - return new Transaction(false) { - @Override - protected AccountService callImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.getRealm(id); - if (realm == null) { - logger.debug("realm not found"); - throw new NotFoundException(); - } - AccountService accountService = new AccountService(realm); - resourceContext.initResource(accountService); - return accountService; - } - }.call(); + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.getRealm(id); + if (realm == null) { + logger.debug("realm not found"); + throw new NotFoundException(); + } + AccountService accountService = new AccountService(realm); + resourceContext.initResource(accountService); + return accountService; } @Path("{realm}") public PublicRealmResource getRealmResource(final @PathParam("realm") String id) { - return new Transaction(false) { - @Override - protected PublicRealmResource callImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.getRealm(id); - if (realm == null) { - logger.debug("realm not found"); - throw new NotFoundException(); - } - PublicRealmResource realmResource = new PublicRealmResource(realm); - resourceContext.initResource(realmResource); - return realmResource; - } - }.call(); + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.getRealm(id); + if (realm == null) { + logger.debug("realm not found"); + throw new NotFoundException(); + } + PublicRealmResource realmResource = new PublicRealmResource(realm); + resourceContext.initResource(realmResource); + return realmResource; } diff --git a/services/src/main/java/org/keycloak/services/resources/SaasService.java b/services/src/main/java/org/keycloak/services/resources/SaasService.java index 7b5a151a66..c1c7758aae 100755 --- a/services/src/main/java/org/keycloak/services/resources/SaasService.java +++ b/services/src/main/java/org/keycloak/services/resources/SaasService.java @@ -10,18 +10,14 @@ import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.messages.Messages; -import org.keycloak.services.models.RealmModel; -import org.keycloak.services.models.RequiredCredentialModel; -import org.keycloak.services.models.RoleModel; -import org.keycloak.services.models.UserCredentialModel; -import org.keycloak.services.models.UserModel; +import org.keycloak.services.models.*; import org.keycloak.services.resources.admin.RealmsAdminResource; import org.keycloak.services.resources.flows.Flows; import org.keycloak.services.validation.Validation; import javax.ws.rs.*; +import javax.ws.rs.container.ResourceContext; import javax.ws.rs.core.*; - import java.net.URI; import java.util.LinkedList; import java.util.List; @@ -44,7 +40,13 @@ public class SaasService { protected HttpRequest request; @Context - HttpResponse response; + protected HttpResponse response; + + @Context + protected KeycloakSession session; + + @Context + protected ResourceContext resourceContext; protected String adminPath = "/saas/admin/index.html"; protected AuthenticationManager authManager = new AuthenticationManager(); @@ -82,22 +84,17 @@ public class SaasService { @GET @NoCache public Response keepalive(final @Context HttpHeaders headers) { - logger.info("keepalive"); - return new Transaction() { - @Override - public Response callImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.defaultRealm(); - if (realm == null) - throw new NotFoundException(); - UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers); - if (user == null) { - return Response.status(401).build(); - } - NewCookie refreshCookie = authManager.createSaasIdentityCookie(realm, user, uriInfo); - return Response.noContent().cookie(refreshCookie).build(); - } - }.call(); + logger.debug("keepalive"); + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.defaultRealm(); + if (realm == null) + throw new NotFoundException(); + UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers); + if (user == null) { + return Response.status(401).build(); + } + NewCookie refreshCookie = authManager.createSaasIdentityCookie(realm, user, uriInfo); + return Response.noContent().cookie(refreshCookie).build(); } @Path("whoami") @@ -105,20 +102,15 @@ public class SaasService { @Produces("application/json") @NoCache public Response whoAmI(final @Context HttpHeaders headers) { - return new Transaction() { - @Override - public Response callImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.defaultRealm(); - if (realm == null) - throw new NotFoundException(); - UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers); - if (user == null) { - return Response.status(401).build(); - } - return Response.ok(new WhoAmI(user.getLoginName(), user.getFirstName() + " " + user.getLastName())).build(); - } - }.call(); + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.defaultRealm(); + if (realm == null) + throw new NotFoundException(); + UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers); + if (user == null) { + return Response.status(401).build(); + } + return Response.ok(new WhoAmI(user.getLoginName(), user.getFirstName() + " " + user.getLastName())).build(); } @Path("isLoggedIn.js") @@ -126,24 +118,19 @@ public class SaasService { @Produces("application/javascript") @NoCache public String isLoggedIn(final @Context HttpHeaders headers) { - return new Transaction() { - @Override - public String callImpl() { - logger.info("WHOAMI Javascript start."); - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.defaultRealm(); - if (realm == null) { - return "var keycloakCookieLoggedIn = false;"; + logger.debug("WHOAMI Javascript start."); + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.defaultRealm(); + if (realm == null) { + return "var keycloakCookieLoggedIn = false;"; - } - UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers); - if (user == null) { - return "var keycloakCookieLoggedIn = false;"; - } - logger.info("WHOAMI: " + user.getLoginName()); - return "var keycloakCookieLoggedIn = true;"; - } - }.call(); + } + UserModel user = authManager.authenticateSaasIdentityCookie(realm, uriInfo, headers); + if (user == null) { + return "var keycloakCookieLoggedIn = false;"; + } + logger.debug("WHOAMI: " + user.getLoginName()); + return "var keycloakCookieLoggedIn = true;"; } public static UriBuilder contextRoot(UriInfo uriInfo) { @@ -156,86 +143,63 @@ public class SaasService { @Path("admin/realms") public RealmsAdminResource getRealmsAdmin(@Context final HttpHeaders headers) { - return new Transaction(false) { - @Override - protected RealmsAdminResource callImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel saasRealm = realmManager.defaultRealm(); - if (saasRealm == null) - throw new NotFoundException(); - UserModel admin = authManager.authenticateSaasIdentity(saasRealm, uriInfo, headers); - if (admin == null) { - throw new NotAuthorizedException("Bearer"); - } - RoleModel creatorRole = saasRealm.getRole(SaasService.REALM_CREATOR_ROLE); - if (!saasRealm.hasRole(admin, creatorRole)) { - logger.warn("not a Realm creator"); - throw new NotAuthorizedException("Bearer"); - } - return new RealmsAdminResource(admin); - } - }.call(); + RealmManager realmManager = new RealmManager(session); + RealmModel saasRealm = realmManager.defaultRealm(); + if (saasRealm == null) + throw new NotFoundException(); + UserModel admin = authManager.authenticateSaasIdentity(saasRealm, uriInfo, headers); + if (admin == null) { + throw new NotAuthorizedException("Bearer"); + } + RoleModel creatorRole = saasRealm.getRole(SaasService.REALM_CREATOR_ROLE); + if (!saasRealm.hasRole(admin, creatorRole)) { + logger.warn("not a Realm creator"); + throw new NotAuthorizedException("Bearer"); + } + RealmsAdminResource adminResource = new RealmsAdminResource(admin); + resourceContext.initResource(adminResource); + return adminResource; } @Path("login") @GET @NoCache public void loginPage() { - new Transaction() { - @Override - protected void runImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.defaultRealm(); - authManager.expireSaasIdentityCookie(uriInfo); + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.defaultRealm(); + authManager.expireSaasIdentityCookie(uriInfo); - Flows.forms(realm, request).forwardToLogin(); - } - }.run(); + Flows.forms(realm, request).forwardToLogin(); } @Path("registrations") @GET @NoCache public void registerPage() { - new Transaction() { - @Override - protected void runImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.defaultRealm(); - authManager.expireSaasIdentityCookie(uriInfo); + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.defaultRealm(); + authManager.expireSaasIdentityCookie(uriInfo); - Flows.forms(realm, request).forwardToRegistration(); - } - }.run(); + Flows.forms(realm, request).forwardToRegistration(); } @Path("logout") @GET @NoCache public void logout() { - new Transaction() { - @Override - protected void runImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.defaultRealm(); - authManager.expireSaasIdentityCookie(uriInfo); + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.defaultRealm(); + authManager.expireSaasIdentityCookie(uriInfo); - Flows.forms(realm, request).forwardToLogin(); - } - }.run(); + Flows.forms(realm, request).forwardToLogin(); } @Path("logout-cookie") @GET @NoCache public void logoutCookie() { - logger.info("*** logoutCookie"); - new Transaction() { - @Override - protected void runImpl() { - authManager.expireSaasIdentityCookie(uriInfo); - } - }.run(); + logger.debug("*** logoutCookie"); + authManager.expireSaasIdentityCookie(uriInfo); } @Path("login") @@ -243,132 +207,117 @@ public class SaasService { @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processLogin(final MultivaluedMap formData) { logger.info("processLogin start"); - return new Transaction() { - @Override - protected Response callImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.defaultRealm(); - if (realm == null) - throw new NotFoundException(); + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.defaultRealm(); + if (realm == null) + throw new NotFoundException(); - if (!realm.isEnabled()) { - throw new NotImplementedYetException(); - } - String username = formData.getFirst("username"); - UserModel user = realm.getUser(username); - if (user == null) { - logger.info("Not Authenticated! Incorrect user name"); + if (!realm.isEnabled()) { + throw new NotImplementedYetException(); + } + String username = formData.getFirst("username"); + UserModel user = realm.getUser(username); + if (user == null) { + logger.info("Not Authenticated! Incorrect user name"); - return Flows.forms(realm, request).setError(Messages.INVALID_USER).setFormData(formData) - .forwardToLogin(); - } - if (!user.isEnabled()) { - logger.info("Account is disabled, contact admin."); + return Flows.forms(realm, request).setError(Messages.INVALID_USER).setFormData(formData) + .forwardToLogin(); + } + if (!user.isEnabled()) { + logger.info("Account is disabled, contact admin."); - return Flows.forms(realm, request).setError(Messages.ACCOUNT_DISABLED) - .setFormData(formData).forwardToLogin(); - } + return Flows.forms(realm, request).setError(Messages.ACCOUNT_DISABLED) + .setFormData(formData).forwardToLogin(); + } - boolean authenticated = authManager.authenticateForm(realm, user, formData); - if (!authenticated) { - logger.info("Not Authenticated! Invalid credentials"); + boolean authenticated = authManager.authenticateForm(realm, user, formData); + if (!authenticated) { + logger.info("Not Authenticated! Invalid credentials"); - return Flows.forms(realm, request).setError(Messages.INVALID_PASSWORD).setFormData(formData) - .forwardToLogin(); - } + return Flows.forms(realm, request).setError(Messages.INVALID_PASSWORD).setFormData(formData) + .forwardToLogin(); + } - NewCookie cookie = authManager.createSaasIdentityCookie(realm, user, uriInfo); - return Response.status(302).cookie(cookie).location(contextRoot(uriInfo).path(adminPath).build()).build(); - } - }.call(); + NewCookie cookie = authManager.createSaasIdentityCookie(realm, user, uriInfo); + return Response.status(302).cookie(cookie).location(contextRoot(uriInfo).path(adminPath).build()).build(); } @Path("registrations") @POST @Consumes(MediaType.APPLICATION_JSON) public Response register(final UserRepresentation newUser) { - return new Transaction() { - @Override - protected Response callImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel defaultRealm = realmManager.defaultRealm(); - UserModel user = registerMe(defaultRealm, newUser); - if (user == null) { - return Response.status(400).type("text/plain").entity("Already exists").build(); - } - URI uri = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(user.getLoginName()).build(); - return Response.created(uri).build(); - } - }.call(); + RealmManager realmManager = new RealmManager(session); + RealmModel defaultRealm = realmManager.defaultRealm(); + UserModel user = registerMe(defaultRealm, newUser); + if (user == null) { + return Response.status(400).type("text/plain").entity("Already exists").build(); + } + URI uri = uriInfo.getBaseUriBuilder().path(RealmsResource.class).path(user.getLoginName()).build(); + return Response.created(uri).build(); } @Path("registrations") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processRegister(final MultivaluedMap formData) { - return new Transaction() { - @Override - protected Response callImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel defaultRealm = realmManager.defaultRealm(); + RealmManager realmManager = new RealmManager(session); + RealmModel defaultRealm = realmManager.defaultRealm(); - List requiredCredentialTypes = new LinkedList(); - for (RequiredCredentialModel m : defaultRealm.getRequiredCredentials()) { - requiredCredentialTypes.add(m.getType()); - } + List requiredCredentialTypes = new LinkedList(); + for (RequiredCredentialModel m : defaultRealm.getRequiredCredentials()) { + requiredCredentialTypes.add(m.getType()); + } - String error = Validation.validateRegistrationForm(formData, requiredCredentialTypes); - if (error != null) { - return Flows.forms(defaultRealm, request).setError(error).setFormData(formData) - .forwardToRegistration(); - } + String error = Validation.validateRegistrationForm(formData, requiredCredentialTypes); + if (error != null) { + return Flows.forms(defaultRealm, request).setError(error).setFormData(formData) + .forwardToRegistration(); + } - UserRepresentation newUser = new UserRepresentation(); - newUser.setUsername(formData.getFirst("username")); - newUser.setEmail(formData.getFirst("email")); + UserRepresentation newUser = new UserRepresentation(); + newUser.setUsername(formData.getFirst("username")); + newUser.setEmail(formData.getFirst("email")); - String fullname = formData.getFirst("name"); - if (fullname != null) { - StringTokenizer tokenizer = new StringTokenizer(fullname, " "); - StringBuffer first = null; - String last = ""; - while (tokenizer.hasMoreTokens()) { - String token = tokenizer.nextToken(); - if (tokenizer.hasMoreTokens()) { - if (first == null) { - first = new StringBuffer(); - } else { - first.append(" "); - } - first.append(token); - } else { - last = token; - } - } - if (first == null) + String fullname = formData.getFirst("name"); + if (fullname != null) { + StringTokenizer tokenizer = new StringTokenizer(fullname, " "); + StringBuffer first = null; + String last = ""; + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + if (tokenizer.hasMoreTokens()) { + if (first == null) { first = new StringBuffer(); - newUser.setFirstName(first.toString()); - newUser.setLastName(last); + } else { + first.append(" "); + } + first.append(token); + } else { + last = token; } - - if (requiredCredentialTypes.contains(CredentialRepresentation.PASSWORD)) { - newUser.credential(CredentialRepresentation.PASSWORD, formData.getFirst("password")); - } - - if (requiredCredentialTypes.contains(CredentialRepresentation.TOTP)) { - newUser.credential(CredentialRepresentation.TOTP, formData.getFirst("password")); - } - - UserModel user = registerMe(defaultRealm, newUser); - if (user == null) { - return Flows.forms(defaultRealm, request).setError(Messages.USERNAME_EXISTS) - .setFormData(formData).forwardToRegistration(); - - } - NewCookie cookie = authManager.createSaasIdentityCookie(defaultRealm, user, uriInfo); - return Response.status(302).location(contextRoot(uriInfo).path(adminPath).build()).cookie(cookie).build(); } - }.call(); + if (first == null) + first = new StringBuffer(); + newUser.setFirstName(first.toString()); + newUser.setLastName(last); + } + + if (requiredCredentialTypes.contains(CredentialRepresentation.PASSWORD)) { + newUser.credential(CredentialRepresentation.PASSWORD, formData.getFirst("password")); + } + + if (requiredCredentialTypes.contains(CredentialRepresentation.TOTP)) { + newUser.credential(CredentialRepresentation.TOTP, formData.getFirst("password")); + } + + UserModel user = registerMe(defaultRealm, newUser); + if (user == null) { + return Flows.forms(defaultRealm, request).setError(Messages.USERNAME_EXISTS) + .setFormData(formData).forwardToRegistration(); + + } + NewCookie cookie = authManager.createSaasIdentityCookie(defaultRealm, user, uriInfo); + return Response.status(302).location(contextRoot(uriInfo).path(adminPath).build()).cookie(cookie).build(); } protected UserModel registerMe(RealmModel defaultRealm, UserRepresentation newUser) { diff --git a/services/src/main/java/org/keycloak/services/resources/SocialResource.java b/services/src/main/java/org/keycloak/services/resources/SocialResource.java old mode 100644 new mode 100755 index 178d803431..b260262093 --- a/services/src/main/java/org/keycloak/services/resources/SocialResource.java +++ b/services/src/main/java/org/keycloak/services/resources/SocialResource.java @@ -56,10 +56,7 @@ import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.TokenManager; import org.keycloak.services.messages.Messages; -import org.keycloak.services.models.RealmModel; -import org.keycloak.services.models.RoleModel; -import org.keycloak.services.models.SocialLinkModel; -import org.keycloak.services.models.UserModel; +import org.keycloak.services.models.*; import org.keycloak.services.resources.flows.Flows; import org.keycloak.services.resources.flows.OAuthFlows; import org.keycloak.services.resources.flows.PageFlows; @@ -98,6 +95,10 @@ public class SocialResource { @Context ResourceContext resourceContext; + @Context + protected KeycloakSession session; + + private SocialRequestManager socialRequestManager; private TokenManager tokenManager; @@ -112,111 +113,107 @@ public class SocialResource { @GET @Path("callback") public Response callback() throws URISyntaxException { - return new Transaction() { - protected Response callImpl() { - Map queryParams = getQueryParams(); + Map queryParams = getQueryParams(); - RequestDetails requestData = getRequestDetails(queryParams); - SocialProvider provider = getProvider(requestData.getProviderId()); + RequestDetails requestData = getRequestDetails(queryParams); + SocialProvider provider = getProvider(requestData.getProviderId()); - String realmId = requestData.getClientAttribute("realmId"); + String realmId = requestData.getClientAttribute("realmId"); - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.getRealm(realmId); + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.getRealm(realmId); - OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager); + OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager); - if (!realm.isEnabled()) { - return oauth.forwardToSecurityFailure("Realm not enabled."); - } + if (!realm.isEnabled()) { + return oauth.forwardToSecurityFailure("Realm not enabled."); + } - String clientId = requestData.getClientAttributes().get("clientId"); + String clientId = requestData.getClientAttributes().get("clientId"); - UserModel client = realm.getUser(clientId); - if (client == null) { - return oauth.forwardToSecurityFailure("Unknown login requester."); - } - if (!client.isEnabled()) { - return oauth.forwardToSecurityFailure("Login requester not enabled."); - } + UserModel client = realm.getUser(clientId); + if (client == null) { + return oauth.forwardToSecurityFailure("Unknown login requester."); + } + if (!client.isEnabled()) { + return oauth.forwardToSecurityFailure("Login requester not enabled."); + } - String key = System.getProperty("keycloak.social." + requestData.getProviderId() + ".key"); - String secret = System.getProperty("keycloak.social." + requestData.getProviderId() + ".secret"); - String callbackUri = Urls.socialCallback(uriInfo.getBaseUri()).toString(); - SocialProviderConfig config = new SocialProviderConfig(key, secret, callbackUri); + String key = System.getProperty("keycloak.social." + requestData.getProviderId() + ".key"); + String secret = System.getProperty("keycloak.social." + requestData.getProviderId() + ".secret"); + String callbackUri = Urls.socialCallback(uriInfo.getBaseUri()).toString(); + SocialProviderConfig config = new SocialProviderConfig(key, secret, callbackUri); - AuthCallback callback = new AuthCallback(requestData.getSocialAttributes(), queryParams); + AuthCallback callback = new AuthCallback(requestData.getSocialAttributes(), queryParams); - SocialUser socialUser = null; - try { - socialUser = provider.processCallback(config, callback); - } catch (SocialProviderException e) { - logger.warn("Failed to process social callback", e); - return oauth.forwardToSecurityFailure("Failed to process social callback"); - } + SocialUser socialUser = null; + try { + socialUser = provider.processCallback(config, callback); + } catch (SocialProviderException e) { + logger.warn("Failed to process social callback", e); + return oauth.forwardToSecurityFailure("Failed to process social callback"); + } - SocialLinkModel socialLink = new SocialLinkModel(provider.getId(), socialUser.getUsername()); - UserModel user = realm.getUserBySocialLink(socialLink); + SocialLinkModel socialLink = new SocialLinkModel(provider.getId(), socialUser.getUsername()); + UserModel user = realm.getUserBySocialLink(socialLink); - if (user == null) { - if (!realm.isRegistrationAllowed()) { - return oauth.forwardToSecurityFailure("Registration not allowed"); - } - - // Automatically register user into realm with his social username (don't redirect to registration screen) - if (realm.isAutomaticRegistrationAfterSocialLogin()) { - - if (realm.getUser(socialUser.getUsername()) != null) { - // TODO: Username is already in realm. Show message and let user to bind accounts after he re-authenticate - throw new IllegalStateException("Username " + socialUser.getUsername() + - " already registered in the realm. TODO: bind accounts..."); - - // TODO: Maybe we should search also by email and bind accounts if user with this email is - // already registered. But actually Keycloak allows duplicate emails - } else { - user = realm.addUser(socialUser.getUsername()); - user.setFirstName(socialUser.getFirstName()); - user.setLastName(socialUser.getLastName()); - user.setEmail(socialUser.getEmail()); - } - - realm.addSocialLink(user, socialLink); - - for (RoleModel role : realm.getDefaultRoles()) { - realm.grantRole(user, role); - } - } else { - // Redirect user to registration screen with prefilled data from social provider - MultivaluedMap formData = fillRegistrationFormWithSocialData(socialUser); - - RequestDetailsBuilder reqDetailsBuilder = RequestDetailsBuilder.createFromRequestDetails(requestData); - reqDetailsBuilder.putSocialAttribute(SocialConstants.ATTR_SOCIAL_LINK, socialLink); - - String requestId = UUID.randomUUID().toString(); - socialRequestManager.addRequest(requestId, reqDetailsBuilder.build()); - boolean secureOnly = !realm.isSslNotRequired(); - String cookiePath = Urls.socialBase(uriInfo.getBaseUri()).build().getPath(); - logger.info("creating cookie for social registration - name: " + SocialConstants.SOCIAL_REGISTRATION_COOKIE - + " path: " + cookiePath); - NewCookie newCookie = new NewCookie(SocialConstants.SOCIAL_REGISTRATION_COOKIE, requestId, - cookiePath, null, "Added social cookie", NewCookie.DEFAULT_MAX_AGE, secureOnly); - response.addNewCookie(newCookie); - - return Flows.forms(realm, request).setFormData(formData).setSocialRegistration(true).forwardToRegistration(); - } - } - - if (!user.isEnabled()) { - return oauth.forwardToSecurityFailure("Your account is not enabled."); - } - - String scope = requestData.getClientAttributes().get("scope"); - String state = requestData.getClientAttributes().get("state"); - String redirectUri = requestData.getClientAttributes().get("redirectUri"); - - return oauth.processAccessCode(scope, state, redirectUri, client, user); + if (user == null) { + if (!realm.isRegistrationAllowed()) { + return oauth.forwardToSecurityFailure("Registration not allowed"); } - }.call(); + + // Automatically register user into realm with his social username (don't redirect to registration screen) + if (realm.isAutomaticRegistrationAfterSocialLogin()) { + + if (realm.getUser(socialUser.getUsername()) != null) { + // TODO: Username is already in realm. Show message and let user to bind accounts after he re-authenticate + throw new IllegalStateException("Username " + socialUser.getUsername() + + " already registered in the realm. TODO: bind accounts..."); + + // TODO: Maybe we should search also by email and bind accounts if user with this email is + // already registered. But actually Keycloak allows duplicate emails + } else { + user = realm.addUser(socialUser.getUsername()); + user.setFirstName(socialUser.getFirstName()); + user.setLastName(socialUser.getLastName()); + user.setEmail(socialUser.getEmail()); + } + + realm.addSocialLink(user, socialLink); + + for (RoleModel role : realm.getDefaultRoles()) { + realm.grantRole(user, role); + } + } else { + // Redirect user to registration screen with prefilled data from social provider + MultivaluedMap formData = fillRegistrationFormWithSocialData(socialUser); + + RequestDetailsBuilder reqDetailsBuilder = RequestDetailsBuilder.createFromRequestDetails(requestData); + reqDetailsBuilder.putSocialAttribute(SocialConstants.ATTR_SOCIAL_LINK, socialLink); + + String requestId = UUID.randomUUID().toString(); + socialRequestManager.addRequest(requestId, reqDetailsBuilder.build()); + boolean secureOnly = !realm.isSslNotRequired(); + String cookiePath = Urls.socialBase(uriInfo.getBaseUri()).build().getPath(); + logger.info("creating cookie for social registration - name: " + SocialConstants.SOCIAL_REGISTRATION_COOKIE + + " path: " + cookiePath); + NewCookie newCookie = new NewCookie(SocialConstants.SOCIAL_REGISTRATION_COOKIE, requestId, + cookiePath, null, "Added social cookie", NewCookie.DEFAULT_MAX_AGE, secureOnly); + response.addNewCookie(newCookie); + + return Flows.forms(realm, request).setFormData(formData).setSocialRegistration(true).forwardToRegistration(); + } + } + + if (!user.isEnabled()) { + return oauth.forwardToSecurityFailure("Your account is not enabled."); + } + + String scope = requestData.getClientAttributes().get("scope"); + String state = requestData.getClientAttributes().get("state"); + String redirectUri = requestData.getClientAttributes().get("redirectUri"); + + return oauth.processAccessCode(scope, state, redirectUri, client, user); } @GET @@ -257,63 +254,59 @@ public class SocialResource { @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response socialRegistration(@PathParam("realm") final String realmId, final MultivaluedMap formData) { - return new Transaction() { - protected Response callImpl() { - PageFlows pageFlows = Flows.pages(request); - Cookie cookie = headers.getCookies().get(SocialConstants.SOCIAL_REGISTRATION_COOKIE); - if (cookie == null) { - return pageFlows.forwardToSecurityFailure("Social registration cookie not found"); - } + PageFlows pageFlows = Flows.pages(request); + Cookie cookie = headers.getCookies().get(SocialConstants.SOCIAL_REGISTRATION_COOKIE); + if (cookie == null) { + return pageFlows.forwardToSecurityFailure("Social registration cookie not found"); + } - String requestId = cookie.getValue(); - if (!socialRequestManager.isRequestId(requestId)) { - logger.error("Unknown requestId found in cookie. Maybe it's expired. requestId=" + requestId); - return pageFlows.forwardToSecurityFailure("Unknown requestId found in cookie. Maybe it's expired."); - } + String requestId = cookie.getValue(); + if (!socialRequestManager.isRequestId(requestId)) { + logger.error("Unknown requestId found in cookie. Maybe it's expired. requestId=" + requestId); + return pageFlows.forwardToSecurityFailure("Unknown requestId found in cookie. Maybe it's expired."); + } - RequestDetails requestData = socialRequestManager.getData(requestId); + RequestDetails requestData = socialRequestManager.getData(requestId); - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.getRealm(realmId); - if (realm == null || !realm.isEnabled()) { - return pageFlows.forwardToSecurityFailure("Realm doesn't exists or is not enabled."); - } - TokenService tokenService = new TokenService(realm, tokenManager); - resourceContext.initResource(tokenService); + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.getRealm(realmId); + if (realm == null || !realm.isEnabled()) { + return pageFlows.forwardToSecurityFailure("Realm doesn't exists or is not enabled."); + } + TokenService tokenService = new TokenService(realm, tokenManager); + resourceContext.initResource(tokenService); - String clientId = requestData.getClientAttribute("clientId"); - String scope = requestData.getClientAttribute("scope"); - String state = requestData.getClientAttribute("state"); - String redirectUri = requestData.getClientAttribute("redirectUri"); - SocialLinkModel socialLink = (SocialLinkModel)requestData.getSocialAttribute(SocialConstants.ATTR_SOCIAL_LINK); + String clientId = requestData.getClientAttribute("clientId"); + String scope = requestData.getClientAttribute("scope"); + String state = requestData.getClientAttribute("state"); + String redirectUri = requestData.getClientAttribute("redirectUri"); + SocialLinkModel socialLink = (SocialLinkModel)requestData.getSocialAttribute(SocialConstants.ATTR_SOCIAL_LINK); - Response response1 = tokenService.processRegisterImpl(clientId, scope, state, redirectUri, formData, true); + Response response1 = tokenService.processRegisterImpl(clientId, scope, state, redirectUri, formData, true); - // Some error occured during registration - if (response1 != null || request.wasForwarded()) { - logger.warn("Registration attempt wasn't successful. Request already forwarded or redirected."); - return response1; - } + // Some error occured during registration + if (response1 != null || request.wasForwarded()) { + logger.warn("Registration attempt wasn't successful. Request already forwarded or redirected."); + return response1; + } - String username = formData.getFirst("username"); - UserModel user = realm.getUser(username); - if (user == null) { - // Normally shouldn't happen - throw new IllegalStateException("User " + username + " not found in the realm"); - } - realm.addSocialLink(user, socialLink); + String username = formData.getFirst("username"); + UserModel user = realm.getUser(username); + if (user == null) { + // Normally shouldn't happen + throw new IllegalStateException("User " + username + " not found in the realm"); + } + realm.addSocialLink(user, socialLink); - // Expire cookie and invalidate requestData - String cookiePath = Urls.socialBase(uriInfo.getBaseUri()).build().getPath(); - NewCookie newCookie = new NewCookie(SocialConstants.SOCIAL_REGISTRATION_COOKIE, "", cookiePath, null, - "Expire social cookie", 0, false); - logger.info("Expiring social registration cookie: " + SocialConstants.SOCIAL_REGISTRATION_COOKIE + ", path: " + cookiePath); - response.addNewCookie(newCookie); - socialRequestManager.retrieveData(requestId); + // Expire cookie and invalidate requestData + String cookiePath = Urls.socialBase(uriInfo.getBaseUri()).build().getPath(); + NewCookie newCookie = new NewCookie(SocialConstants.SOCIAL_REGISTRATION_COOKIE, "", cookiePath, null, + "Expire social cookie", 0, false); + logger.info("Expiring social registration cookie: " + SocialConstants.SOCIAL_REGISTRATION_COOKIE + ", path: " + cookiePath); + response.addNewCookie(newCookie); + socialRequestManager.retrieveData(requestId); - return tokenService.processLogin(clientId, scope, state, redirectUri, formData); - } - }.call(); + return tokenService.processLogin(clientId, scope, state, redirectUri, formData); } private RequestDetails getRequestDetails(Map queryParams) { diff --git a/services/src/main/java/org/keycloak/services/resources/TokenService.java b/services/src/main/java/org/keycloak/services/resources/TokenService.java index 41c01a9715..00b37ad5fd 100755 --- a/services/src/main/java/org/keycloak/services/resources/TokenService.java +++ b/services/src/main/java/org/keycloak/services/resources/TokenService.java @@ -18,11 +18,7 @@ import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.ResourceAdminManager; import org.keycloak.services.managers.TokenManager; import org.keycloak.services.messages.Messages; -import org.keycloak.services.models.RealmModel; -import org.keycloak.services.models.RequiredCredentialModel; -import org.keycloak.services.models.RoleModel; -import org.keycloak.services.models.UserCredentialModel; -import org.keycloak.services.models.UserModel; +import org.keycloak.services.models.*; import org.keycloak.services.resources.flows.Flows; import org.keycloak.services.resources.flows.OAuthFlows; import org.keycloak.services.validation.Validation; @@ -75,9 +71,14 @@ public class TokenService { @Context protected HttpHeaders headers; @Context - HttpRequest request; + protected HttpRequest request; @Context - HttpResponse response; + protected HttpResponse response; + @Context + protected KeycloakSession session; + @Context + protected KeycloakTransaction transaction; + private ResourceAdminManager resourceAdminManager = new ResourceAdminManager(); @@ -123,32 +124,28 @@ public class TokenService { @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Produces(MediaType.APPLICATION_JSON) public Response grantIdentityToken(final MultivaluedMap form) { - return new Transaction() { - protected Response callImpl() { - String username = form.getFirst(AuthenticationManager.FORM_USERNAME); - if (username == null) { - throw new NotAuthorizedException("No user"); - } - if (!realm.isEnabled()) { - throw new NotAuthorizedException("Disabled realm"); - } - UserModel user = realm.getUser(username); - if (user == null) { - throw new NotAuthorizedException("No user"); - } - if (!user.isEnabled()) { - throw new NotAuthorizedException("Disabled user."); - } - if (!authManager.authenticateForm(realm, user, form)) { - throw new NotAuthorizedException("FORM"); - } - tokenManager = new TokenManager(); - SkeletonKeyToken token = authManager.createIdentityToken(realm, username); - String encoded = tokenManager.encodeToken(realm, token); - AccessTokenResponse res = accessTokenResponse(token, encoded); - return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build(); - } - }.call(); + String username = form.getFirst(AuthenticationManager.FORM_USERNAME); + if (username == null) { + throw new NotAuthorizedException("No user"); + } + if (!realm.isEnabled()) { + throw new NotAuthorizedException("Disabled realm"); + } + UserModel user = realm.getUser(username); + if (user == null) { + throw new NotAuthorizedException("No user"); + } + if (!user.isEnabled()) { + throw new NotAuthorizedException("Disabled user."); + } + if (!authManager.authenticateForm(realm, user, form)) { + throw new NotAuthorizedException("FORM"); + } + tokenManager = new TokenManager(); + SkeletonKeyToken token = authManager.createIdentityToken(realm, username); + String encoded = tokenManager.encodeToken(realm, token); + AccessTokenResponse res = accessTokenResponse(token, encoded); + return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build(); } @Path("grants/access") @@ -156,32 +153,27 @@ public class TokenService { @Consumes(MediaType.APPLICATION_FORM_URLENCODED) @Produces(MediaType.APPLICATION_JSON) public Response grantAccessToken(final MultivaluedMap form) { - return new Transaction() { - protected Response callImpl() { - String username = form.getFirst(AuthenticationManager.FORM_USERNAME); - if (username == null) { - throw new NotAuthorizedException("No user"); - } - if (!realm.isEnabled()) { - throw new NotAuthorizedException("Disabled realm"); - } - UserModel user = realm.getUser(username); - if (user == null) { - throw new NotAuthorizedException("No user"); - } - if (!user.isEnabled()) { - throw new NotAuthorizedException("Disabled user."); - } - if (authManager.authenticateForm(realm, user, form)) { - throw new NotAuthorizedException("Auth failed"); - } - SkeletonKeyToken token = tokenManager.createAccessToken(realm, user); - String encoded = tokenManager.encodeToken(realm, token); - AccessTokenResponse res = accessTokenResponse(token, encoded); - return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build(); - } - }.call(); - + String username = form.getFirst(AuthenticationManager.FORM_USERNAME); + if (username == null) { + throw new NotAuthorizedException("No user"); + } + if (!realm.isEnabled()) { + throw new NotAuthorizedException("Disabled realm"); + } + UserModel user = realm.getUser(username); + if (user == null) { + throw new NotAuthorizedException("No user"); + } + if (!user.isEnabled()) { + throw new NotAuthorizedException("Disabled user."); + } + if (authManager.authenticateForm(realm, user, form)) { + throw new NotAuthorizedException("Auth failed"); + } + SkeletonKeyToken token = tokenManager.createAccessToken(realm, user); + String encoded = tokenManager.encodeToken(realm, token); + AccessTokenResponse res = accessTokenResponse(token, encoded); + return Response.ok(res, MediaType.APPLICATION_JSON_TYPE).build(); } @Path("auth/request/login") @@ -190,54 +182,50 @@ public class TokenService { public Response processLogin(@QueryParam("client_id") final String clientId, @QueryParam("scope") final String scopeParam, @QueryParam("state") final String state, @QueryParam("redirect_uri") final String redirect, final MultivaluedMap formData) { - return new Transaction() { - protected Response callImpl() { - OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager); + OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager); - if (!realm.isEnabled()) { - return oauth.forwardToSecurityFailure("Realm not enabled."); - } - UserModel client = realm.getUser(clientId); - if (client == null) { - return oauth.forwardToSecurityFailure("Unknown login requester."); - } - if (!client.isEnabled()) { - return oauth.forwardToSecurityFailure("Login requester not enabled."); - } - String username = formData.getFirst("username"); - UserModel user = realm.getUser(username); - if (user == null) { - logger.error("Incorrect user name."); + if (!realm.isEnabled()) { + return oauth.forwardToSecurityFailure("Realm not enabled."); + } + UserModel client = realm.getUser(clientId); + if (client == null) { + return oauth.forwardToSecurityFailure("Unknown login requester."); + } + if (!client.isEnabled()) { + return oauth.forwardToSecurityFailure("Login requester not enabled."); + } + String username = formData.getFirst("username"); + UserModel user = realm.getUser(username); + if (user == null) { + logger.error("Incorrect user name."); - return Flows.forms(realm, request).setError(Messages.INVALID_USER).setFormData(formData) - .forwardToLogin(); + return Flows.forms(realm, request).setError(Messages.INVALID_USER).setFormData(formData) + .forwardToLogin(); + } + + if (!user.isEnabled()) { + return oauth.forwardToSecurityFailure("Your account is not enabled."); + } + + if ("ENABLED".equals(user.getAttribute("KEYCLOAK_TOTP")) && Validation.isEmpty(formData.getFirst("totp"))) { + return Flows.forms(realm, request).setFormData(formData).forwardToLoginTotp(); + } else { + for (RequiredCredentialModel c : realm.getRequiredCredentials()) { + if (c.getType().equals(CredentialRepresentation.TOTP)) { + return Flows.forms(realm, request).forwardToTotp(); } - - if (!user.isEnabled()) { - return oauth.forwardToSecurityFailure("Your account is not enabled."); - } - - if ("ENABLED".equals(user.getAttribute("KEYCLOAK_TOTP")) && Validation.isEmpty(formData.getFirst("totp"))) { - return Flows.forms(realm, request).setFormData(formData).forwardToLoginTotp(); - } else { - for (RequiredCredentialModel c : realm.getRequiredCredentials()) { - if (c.getType().equals(CredentialRepresentation.TOTP)) { - return Flows.forms(realm, request).forwardToTotp(); - } - } - } - - boolean authenticated = authManager.authenticateForm(realm, user, formData); - if (!authenticated) { - logger.error("Authentication failed"); - - return Flows.forms(realm, request).setError(Messages.INVALID_PASSWORD).setFormData(formData) - .forwardToLogin(); - } - - return oauth.processAccessCode(scopeParam, state, redirect, client, user); } - }.call(); + } + + boolean authenticated = authManager.authenticateForm(realm, user, formData); + if (!authenticated) { + logger.error("Authentication failed"); + + return Flows.forms(realm, request).setError(Messages.INVALID_PASSWORD).setFormData(formData) + .forwardToLogin(); + } + + return oauth.processAccessCode(scopeParam, state, redirect, client, user); } @Path("registrations") @@ -246,20 +234,15 @@ public class TokenService { public Response processRegister(@QueryParam("client_id") final String clientId, @QueryParam("scope") final String scopeParam, @QueryParam("state") final String state, @QueryParam("redirect_uri") final String redirect, final MultivaluedMap formData) { - return new Transaction() { - @Override - protected Response callImpl() { - Response registrationResponse = processRegisterImpl(clientId, scopeParam, state, redirect, formData, false); + Response registrationResponse = processRegisterImpl(clientId, scopeParam, state, redirect, formData, false); - // If request has been already forwarded (either due to security or validation error) then we won't continue with login - if (registrationResponse != null || request.wasForwarded()) { - logger.warn("Registration attempt wasn't successful. Request already forwarded or redirected."); - return registrationResponse; - } else { - return processLogin(clientId, scopeParam, state, redirect, formData); - } - } - }.call(); + // If request has been already forwarded (either due to security or validation error) then we won't continue with login + if (registrationResponse != null || request.wasForwarded()) { + logger.warn("Registration attempt wasn't successful. Request already forwarded or redirected."); + return registrationResponse; + } else { + return processLogin(clientId, scopeParam, state, redirect, formData); + } } public Response processRegisterImpl(String clientId, String scopeParam, String state, String redirect, @@ -347,104 +330,99 @@ public class TokenService { @POST @Produces("application/json") public Response accessCodeToToken(final MultivaluedMap formData) { - return new Transaction() { - protected Response callImpl() { - logger.info("accessRequest <---"); - if (!realm.isEnabled()) { - throw new NotAuthorizedException("Realm not enabled"); - } + logger.info("accessRequest <---"); + if (!realm.isEnabled()) { + throw new NotAuthorizedException("Realm not enabled"); + } - String code = formData.getFirst("code"); - if (code == null) { - logger.debug("code not specified"); - Map error = new HashMap(); - error.put("error", "invalid_request"); - error.put("error_description", "code not specified"); - return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); + String code = formData.getFirst("code"); + if (code == null) { + logger.debug("code not specified"); + Map error = new HashMap(); + error.put("error", "invalid_request"); + error.put("error_description", "code not specified"); + return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); - } - String client_id = formData.getFirst("client_id"); - if (client_id == null) { - logger.debug("client_id not specified"); - Map error = new HashMap(); - error.put("error", "invalid_request"); - error.put("error_description", "client_id not specified"); - return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); - } - UserModel client = realm.getUser(client_id); - if (client == null) { - logger.debug("Could not find user"); - Map error = new HashMap(); - error.put("error", "invalid_client"); - error.put("error_description", "Could not find user"); - return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); - } + } + String client_id = formData.getFirst("client_id"); + if (client_id == null) { + logger.debug("client_id not specified"); + Map error = new HashMap(); + error.put("error", "invalid_request"); + error.put("error_description", "client_id not specified"); + return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); + } + UserModel client = realm.getUser(client_id); + if (client == null) { + logger.debug("Could not find user"); + Map error = new HashMap(); + error.put("error", "invalid_client"); + error.put("error_description", "Could not find user"); + return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); + } - if (!client.isEnabled()) { - logger.debug("user is not enabled"); - Map error = new HashMap(); - error.put("error", "invalid_client"); - error.put("error_description", "User is not enabled"); - return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); - } + if (!client.isEnabled()) { + logger.debug("user is not enabled"); + Map error = new HashMap(); + error.put("error", "invalid_client"); + error.put("error_description", "User is not enabled"); + return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); + } - boolean authenticated = authManager.authenticateForm(realm, client, formData); - if (!authenticated) { - Map error = new HashMap(); - error.put("error", "unauthorized_client"); - return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); - } - - JWSInput input = new JWSInput(code, providers); - boolean verifiedCode = false; - try { - verifiedCode = RSAProvider.verify(input, realm.getPublicKey()); - } catch (Exception ignored) { - logger.debug("Failed to verify signature", ignored); - } - if (!verifiedCode) { - Map res = new HashMap(); - res.put("error", "invalid_grant"); - res.put("error_description", "Unable to verify code signature"); - return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res) - .build(); - } - String key = input.readContent(String.class); - AccessCodeEntry accessCode = tokenManager.pullAccessCode(key); - if (accessCode == null) { - Map res = new HashMap(); - res.put("error", "invalid_grant"); - res.put("error_description", "Code not found"); - return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res) - .build(); - } - if (accessCode.isExpired()) { - Map res = new HashMap(); - res.put("error", "invalid_grant"); - res.put("error_description", "Code is expired"); - return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res) - .build(); - } - if (!accessCode.getToken().isActive()) { - Map res = new HashMap(); - res.put("error", "invalid_grant"); - res.put("error_description", "Token expired"); - return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res) - .build(); - } - if (!client.getLoginName().equals(accessCode.getClient().getLoginName())) { - Map res = new HashMap(); - res.put("error", "invalid_grant"); - res.put("error_description", "Auth error"); - return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res) - .build(); - } - logger.info("accessRequest SUCCESS"); - AccessTokenResponse res = accessTokenResponse(realm.getPrivateKey(), accessCode.getToken()); - return Response.ok(res).build(); - } - }.call(); + boolean authenticated = authManager.authenticateForm(realm, client, formData); + if (!authenticated) { + Map error = new HashMap(); + error.put("error", "unauthorized_client"); + return Response.status(Response.Status.BAD_REQUEST).entity(error).type("application/json").build(); + } + JWSInput input = new JWSInput(code, providers); + boolean verifiedCode = false; + try { + verifiedCode = RSAProvider.verify(input, realm.getPublicKey()); + } catch (Exception ignored) { + logger.debug("Failed to verify signature", ignored); + } + if (!verifiedCode) { + Map res = new HashMap(); + res.put("error", "invalid_grant"); + res.put("error_description", "Unable to verify code signature"); + return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res) + .build(); + } + String key = input.readContent(String.class); + AccessCodeEntry accessCode = tokenManager.pullAccessCode(key); + if (accessCode == null) { + Map res = new HashMap(); + res.put("error", "invalid_grant"); + res.put("error_description", "Code not found"); + return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res) + .build(); + } + if (accessCode.isExpired()) { + Map res = new HashMap(); + res.put("error", "invalid_grant"); + res.put("error_description", "Code is expired"); + return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res) + .build(); + } + if (!accessCode.getToken().isActive()) { + Map res = new HashMap(); + res.put("error", "invalid_grant"); + res.put("error_description", "Token expired"); + return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res) + .build(); + } + if (!client.getLoginName().equals(accessCode.getClient().getLoginName())) { + Map res = new HashMap(); + res.put("error", "invalid_grant"); + res.put("error_description", "Auth error"); + return Response.status(Response.Status.BAD_REQUEST).type(MediaType.APPLICATION_JSON_TYPE).entity(res) + .build(); + } + logger.info("accessRequest SUCCESS"); + AccessTokenResponse res = accessTokenResponse(realm.getPrivateKey(), accessCode.getToken()); + return Response.ok(res).build(); } protected AccessTokenResponse accessTokenResponse(PrivateKey privateKey, SkeletonKeyToken token) { @@ -475,47 +453,43 @@ public class TokenService { public Response loginPage(final @QueryParam("response_type") String responseType, final @QueryParam("redirect_uri") String redirect, final @QueryParam("client_id") String clientId, final @QueryParam("scope") String scopeParam, final @QueryParam("state") String state) { - return new Transaction() { - protected Response callImpl() { - OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager); + OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager); - if (!realm.isEnabled()) { - oauth.forwardToSecurityFailure("Realm not enabled"); - return null; - } - UserModel client = realm.getUser(clientId); - if (client == null) { - oauth.forwardToSecurityFailure("Unknown login requester."); - transaction.rollback(); - return null; - } + if (!realm.isEnabled()) { + oauth.forwardToSecurityFailure("Realm not enabled"); + return null; + } + UserModel client = realm.getUser(clientId); + if (client == null) { + oauth.forwardToSecurityFailure("Unknown login requester."); + transaction.rollback(); + return null; + } - if (!client.isEnabled()) { - oauth.forwardToSecurityFailure("Login requester not enabled."); - transaction.rollback(); - session.close(); - return null; - } + if (!client.isEnabled()) { + oauth.forwardToSecurityFailure("Login requester not enabled."); + transaction.rollback(); + session.close(); + return null; + } - RoleModel resourceRole = realm.getRole(RealmManager.RESOURCE_ROLE); - RoleModel identityRequestRole = realm.getRole(RealmManager.IDENTITY_REQUESTER_ROLE); - boolean isResource = realm.hasRole(client, resourceRole); - if (!isResource && !realm.hasRole(client, identityRequestRole)) { - oauth.forwardToSecurityFailure("Login requester not allowed to request login."); - transaction.rollback(); - session.close(); - return null; - } + RoleModel resourceRole = realm.getRole(RealmManager.RESOURCE_ROLE); + RoleModel identityRequestRole = realm.getRole(RealmManager.IDENTITY_REQUESTER_ROLE); + boolean isResource = realm.hasRole(client, resourceRole); + if (!isResource && !realm.hasRole(client, identityRequestRole)) { + oauth.forwardToSecurityFailure("Login requester not allowed to request login."); + transaction.rollback(); + session.close(); + return null; + } - UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); - if (user != null) { - logger.info(user.getLoginName() + " already logged in."); - return oauth.processAccessCode(scopeParam, state, redirect, client, user); - } + UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); + if (user != null) { + logger.info(user.getLoginName() + " already logged in."); + return oauth.processAccessCode(scopeParam, state, redirect, client, user); + } - return Flows.forms(realm, request).forwardToLogin(); - } - }.call(); + return Flows.forms(realm, request).forwardToLogin(); } @Path("registrations") @@ -523,88 +497,76 @@ public class TokenService { public Response registerPage(final @QueryParam("response_type") String responseType, final @QueryParam("redirect_uri") String redirect, final @QueryParam("client_id") String clientId, final @QueryParam("scope") String scopeParam, final @QueryParam("state") String state) { - return new Transaction() { - protected Response callImpl() { - OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager); + OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager); - if (!realm.isEnabled()) { - return oauth.forwardToSecurityFailure("Realm not enabled"); - } - UserModel client = realm.getUser(clientId); - if (client == null) { - return oauth.forwardToSecurityFailure("Unknown login requester."); - } + if (!realm.isEnabled()) { + return oauth.forwardToSecurityFailure("Realm not enabled"); + } + UserModel client = realm.getUser(clientId); + if (client == null) { + return oauth.forwardToSecurityFailure("Unknown login requester."); + } - if (!client.isEnabled()) { - return oauth.forwardToSecurityFailure("Login requester not enabled."); - } + if (!client.isEnabled()) { + return oauth.forwardToSecurityFailure("Login requester not enabled."); + } - if (!realm.isRegistrationAllowed()) { - return oauth.forwardToSecurityFailure("Registration not allowed"); - } + if (!realm.isRegistrationAllowed()) { + return oauth.forwardToSecurityFailure("Registration not allowed"); + } - authManager.expireIdentityCookie(realm, uriInfo); + authManager.expireIdentityCookie(realm, uriInfo); - return Flows.forms(realm, request).forwardToRegistration(); - } - }.call(); + return Flows.forms(realm, request).forwardToRegistration(); } @Path("logout") @GET @NoCache public Response logout(final @QueryParam("redirect_uri") String redirectUri) { - return new Transaction() { - protected Response callImpl() { - // todo do we care if anybody can trigger this? + // todo do we care if anybody can trigger this? - UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); - if (user != null) { - logger.info("Logging out: " + user.getLoginName()); - authManager.expireIdentityCookie(realm, uriInfo); - resourceAdminManager.singleLogOut(realm, user.getLoginName()); - } - // todo manage legal redirects - return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build(); - } - }.call(); + UserModel user = authManager.authenticateIdentityCookie(realm, uriInfo, headers); + if (user != null) { + logger.info("Logging out: " + user.getLoginName()); + authManager.expireIdentityCookie(realm, uriInfo); + resourceAdminManager.singleLogOut(realm, user.getLoginName()); + } + // todo manage legal redirects + return Response.status(302).location(UriBuilder.fromUri(redirectUri).build()).build(); } @Path("oauth/grant") @POST @Consumes(MediaType.APPLICATION_FORM_URLENCODED) public Response processOAuth(final MultivaluedMap formData) { - return new Transaction() { - protected Response callImpl() { - OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager); + OAuthFlows oauth = Flows.oauth(realm, request, uriInfo, authManager, tokenManager); - String code = formData.getFirst("code"); - JWSInput input = new JWSInput(code, providers); - boolean verifiedCode = false; - try { - verifiedCode = RSAProvider.verify(input, realm.getPublicKey()); - } catch (Exception ignored) { - logger.debug("Failed to verify signature", ignored); - } - if (!verifiedCode) { - return oauth.forwardToSecurityFailure("Illegal access code."); - } - String key = input.readContent(String.class); - AccessCodeEntry accessCodeEntry = tokenManager.getAccessCode(key); - if (accessCodeEntry == null) { - return oauth.forwardToSecurityFailure("Unknown access code."); - } + String code = formData.getFirst("code"); + JWSInput input = new JWSInput(code, providers); + boolean verifiedCode = false; + try { + verifiedCode = RSAProvider.verify(input, realm.getPublicKey()); + } catch (Exception ignored) { + logger.debug("Failed to verify signature", ignored); + } + if (!verifiedCode) { + return oauth.forwardToSecurityFailure("Illegal access code."); + } + String key = input.readContent(String.class); + AccessCodeEntry accessCodeEntry = tokenManager.getAccessCode(key); + if (accessCodeEntry == null) { + return oauth.forwardToSecurityFailure("Unknown access code."); + } - String redirect = accessCodeEntry.getRedirectUri(); - String state = accessCodeEntry.getState(); + String redirect = accessCodeEntry.getRedirectUri(); + String state = accessCodeEntry.getState(); - if (formData.containsKey("cancel")) { - return redirectAccessDenied(redirect, state); - } + if (formData.containsKey("cancel")) { + return redirectAccessDenied(redirect, state); + } - return oauth.redirectAccessCode(accessCodeEntry, state, redirect); - } - }.call(); + return oauth.redirectAccessCode(accessCodeEntry, state, redirect); } protected Response redirectAccessDenied(String redirect, String state) { diff --git a/services/src/main/java/org/keycloak/services/resources/Transaction.java b/services/src/main/java/org/keycloak/services/resources/Transaction.java index d88cc050b7..69188420bb 100755 --- a/services/src/main/java/org/keycloak/services/resources/Transaction.java +++ b/services/src/main/java/org/keycloak/services/resources/Transaction.java @@ -2,17 +2,15 @@ package org.keycloak.services.resources; import org.jboss.resteasy.spi.ResteasyProviderFactory; import org.keycloak.services.models.KeycloakSession; -import org.keycloak.services.models.KeycloakSessionFactory; import org.keycloak.services.models.KeycloakTransaction; -import javax.ws.rs.core.Application; - /** * Meant to be used as an inner class wrapper (I forget the pattern name, its been awhile). * * @author Bill Burke * @version $Revision: 1 $ */ +@Deprecated public class Transaction { protected KeycloakSession session; protected KeycloakTransaction transaction; @@ -36,6 +34,8 @@ public class Transaction { */ public Transaction(boolean close) { this.session = ResteasyProviderFactory.getContextData(KeycloakSession.class); + this.transaction = session.getTransaction(); + /* if (session == null) { KeycloakApplication app = (KeycloakApplication)ResteasyProviderFactory.getContextData(Application.class); session = app.getFactory().createSession(); @@ -44,20 +44,10 @@ public class Transaction { } transaction = session.getTransaction(); closeSession = close; + */ } - /** - * Creates and manages its own session. - * - * @param factory - */ - public Transaction(KeycloakSessionFactory factory) { - this.closeSession = true; - this.session = factory.createSession(); - this.transaction = session.getTransaction(); - } - protected void runImpl() { } @@ -67,20 +57,20 @@ public class Transaction { * */ public void run() { - boolean wasActive = transaction.isActive(); - if (!wasActive) transaction.begin(); - try { +// boolean wasActive = transaction.isActive(); +// if (!wasActive) transaction.begin(); +// try { runImpl(); - if (!wasActive && transaction.isActive()) transaction.commit(); - } catch (RuntimeException e) { - if (!wasActive && transaction.isActive()) transaction.rollback(); - if (created) closeSession = true; - throw e; - } finally { - if (!wasActive && closeSession) { - session.close(); - } - } +// if (!wasActive && transaction.isActive()) transaction.commit(); +// } catch (RuntimeException e) { +// if (!wasActive && transaction.isActive()) transaction.rollback(); +// if (created) closeSession = true; +// throw e; +// } finally { +// if (!wasActive && closeSession) { +// session.close(); +// } +// } } protected T callImpl() { @@ -92,18 +82,18 @@ public class Transaction { * */ public T call() { - boolean wasActive = transaction.isActive(); - if (!wasActive) transaction.begin(); - try { +// boolean wasActive = transaction.isActive(); +// if (!wasActive) transaction.begin(); +// try { T rtn = callImpl(); - if (!wasActive && transaction.isActive()) transaction.commit(); +// if (!wasActive && transaction.isActive()) transaction.commit(); return rtn; - } catch (RuntimeException e) { - if (!wasActive && transaction.isActive()) transaction.rollback(); - if (created) closeSession = true; // close if there was a failure - throw e; - } finally { - if (!wasActive && closeSession) session.close(); - } +// } catch (RuntimeException e) { +// if (!wasActive && transaction.isActive()) transaction.rollback(); +// if (created) closeSession = true; // close if there was a failure +// throw e; +// } finally { +// if (!wasActive && closeSession) session.close(); +// } } } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java index 36540ac1b1..191fb240e6 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationResource.java @@ -5,16 +5,13 @@ import org.jboss.resteasy.logging.Logger; import org.keycloak.representations.idm.ApplicationRepresentation; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.ResourceManager; -import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.ApplicationModel; +import org.keycloak.services.models.KeycloakSession; +import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.UserModel; -import org.keycloak.services.resources.Transaction; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.PUT; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; +import javax.ws.rs.*; +import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; /** @@ -27,6 +24,9 @@ public class ApplicationResource { protected RealmModel realm; protected ApplicationModel applicationModel; + @Context + protected KeycloakSession session; + public ApplicationResource(UserModel admin, RealmModel realm, ApplicationModel applicationModel) { this.admin = admin; this.realm = realm; @@ -36,13 +36,8 @@ public class ApplicationResource { @PUT @Consumes(MediaType.APPLICATION_JSON) public void update(final ApplicationRepresentation rep) { - new Transaction() { - @Override - protected void runImpl() { - ResourceManager resourceManager = new ResourceManager(new RealmManager(session)); - resourceManager.updateResource(rep, applicationModel); - } - }.run(); + ResourceManager resourceManager = new ResourceManager(new RealmManager(session)); + resourceManager.updateResource(rep, applicationModel); } @@ -50,12 +45,7 @@ public class ApplicationResource { @NoCache @Produces(MediaType.APPLICATION_JSON) public ApplicationRepresentation getResource(final @PathParam("id") String id) { - return new Transaction() { - @Override - protected ApplicationRepresentation callImpl() { - ResourceManager resourceManager = new ResourceManager(new RealmManager(session)); - return resourceManager.toRepresentation(applicationModel); - } - }.call(); + ResourceManager resourceManager = new ResourceManager(new RealmManager(session)); + return resourceManager.toRepresentation(applicationModel); } } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java index 9be8bbdc7e..549c4c1b67 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/ApplicationsResource.java @@ -5,18 +5,13 @@ import org.jboss.resteasy.logging.Logger; import org.keycloak.representations.idm.ApplicationRepresentation; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.managers.ResourceManager; -import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.ApplicationModel; +import org.keycloak.services.models.KeycloakSession; +import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.UserModel; -import org.keycloak.services.resources.Transaction; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.NotFoundException; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; +import javax.ws.rs.*; +import javax.ws.rs.container.ResourceContext; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; @@ -33,6 +28,12 @@ public class ApplicationsResource { protected UserModel admin; protected RealmModel realm; + @Context + protected ResourceContext resourceContext; + + @Context + protected KeycloakSession session; + public ApplicationsResource(UserModel admin, RealmModel realm) { this.admin = admin; this.realm = realm; @@ -42,46 +43,32 @@ public class ApplicationsResource { @Produces(MediaType.APPLICATION_JSON) @NoCache public List getResources() { - return new Transaction>() { - @Override - protected List callImpl() { - List rep = new ArrayList(); - List applicationModels = realm.getApplications(); - ResourceManager resourceManager = new ResourceManager(new RealmManager(session)); - for (ApplicationModel applicationModel : applicationModels) { - rep.add(resourceManager.toRepresentation(applicationModel)); - } - return rep; - } - }.call(); + List rep = new ArrayList(); + List applicationModels = realm.getApplications(); + ResourceManager resourceManager = new ResourceManager(new RealmManager(session)); + for (ApplicationModel applicationModel : applicationModels) { + rep.add(resourceManager.toRepresentation(applicationModel)); + } + return rep; } @POST @Consumes(MediaType.APPLICATION_JSON) public Response createResource(final @Context UriInfo uriInfo, final ApplicationRepresentation rep) { - return new Transaction() { - @Override - protected Response callImpl() { - ResourceManager resourceManager = new ResourceManager(new RealmManager(session)); - ApplicationModel applicationModel = resourceManager.createResource(realm, rep); - return Response.created(uriInfo.getAbsolutePathBuilder().path(applicationModel.getId()).build()).build(); - } - }.call(); + ResourceManager resourceManager = new ResourceManager(new RealmManager(session)); + ApplicationModel applicationModel = resourceManager.createResource(realm, rep); + return Response.created(uriInfo.getAbsolutePathBuilder().path(applicationModel.getId()).build()).build(); } @Path("{id}") public ApplicationResource getResource(final @PathParam("id") String id) { - return new Transaction(false) { - @Override - protected ApplicationResource callImpl() { - ApplicationModel applicationModel = realm.getApplicationById(id); - if (applicationModel == null) { - throw new NotFoundException(); - } - return new ApplicationResource(admin, realm, applicationModel); - } - }.call(); - + ApplicationModel applicationModel = realm.getApplicationById(id); + if (applicationModel == null) { + throw new NotFoundException(); + } + ApplicationResource applicationResource = new ApplicationResource(admin, realm, applicationModel); + resourceContext.initResource(applicationResource); + return applicationResource; } } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java index c8309cbd1e..5ed6520407 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java @@ -6,20 +6,13 @@ import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.representations.idm.RoleRepresentation; import org.keycloak.representations.idm.UserRepresentation; import org.keycloak.services.managers.RealmManager; +import org.keycloak.services.models.KeycloakSession; import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.RoleModel; import org.keycloak.services.models.UserModel; -import org.keycloak.services.resources.Transaction; -import javax.ws.rs.Consumes; -import javax.ws.rs.GET; -import javax.ws.rs.InternalServerErrorException; -import javax.ws.rs.NotFoundException; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; +import javax.ws.rs.*; +import javax.ws.rs.container.ResourceContext; import javax.ws.rs.core.Context; import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; @@ -35,6 +28,12 @@ public class RealmAdminResource { protected UserModel admin; protected RealmModel realm; + @Context + protected ResourceContext resourceContext; + + @Context + protected KeycloakSession session; + public RealmAdminResource(UserModel admin, RealmModel realm) { this.admin = admin; this.realm = realm; @@ -42,19 +41,16 @@ public class RealmAdminResource { @Path("applications") public ApplicationsResource getResources() { - return new ApplicationsResource(admin, realm); + ApplicationsResource applicationsResource = new ApplicationsResource(admin, realm); + resourceContext.initResource(applicationsResource); + return applicationsResource; } @GET @NoCache @Produces("application/json") public RealmRepresentation getRealm() { - return new Transaction() { - @Override - protected RealmRepresentation callImpl() { - return new RealmManager(session).toRepresentation(realm); - } - }.call(); + return new RealmManager(session).toRepresentation(realm); } @@ -63,31 +59,20 @@ public class RealmAdminResource { @NoCache @Produces("application/json") public List getRoles() { - return new Transaction>() { - @Override - protected List callImpl() { - List roleModels = realm.getRoles(); - List roles = new ArrayList(); - for (RoleModel roleModel : roleModels) { - RoleRepresentation role = new RoleRepresentation(roleModel.getName(), roleModel.getDescription()); - roles.add(role); - } - return roles; - } - }.call(); + List roleModels = realm.getRoles(); + List roles = new ArrayList(); + for (RoleModel roleModel : roleModels) { + RoleRepresentation role = new RoleRepresentation(roleModel.getName(), roleModel.getDescription()); + roles.add(role); + } + return roles; } @PUT @Consumes("application/json") public void updateRealm(final RealmRepresentation rep) { - new Transaction() { - @Override - protected void runImpl() { - logger.info("updating realm: " + rep.getRealm()); - new RealmManager(session).updateRealm(rep, realm); - } - }.run(); - + logger.info("updating realm: " + rep.getRealm()); + new RealmManager(session).updateRealm(rep, realm); } @Path("roles/{id}") @@ -95,18 +80,13 @@ public class RealmAdminResource { @NoCache @Produces("application/json") public RoleRepresentation getRole(final @PathParam("id") String id) { - return new Transaction() { - @Override - protected RoleRepresentation callImpl() { - RoleModel roleModel = realm.getRoleById(id); - if (roleModel == null) { - throw new NotFoundException(); - } - RoleRepresentation rep = new RoleRepresentation(roleModel.getName(), roleModel.getDescription()); - rep.setId(roleModel.getId()); - return rep; - } - }.call(); + RoleModel roleModel = realm.getRoleById(id); + if (roleModel == null) { + throw new NotFoundException(); + } + RoleRepresentation rep = new RoleRepresentation(roleModel.getName(), roleModel.getDescription()); + rep.setId(roleModel.getId()); + return rep; } @@ -114,39 +94,27 @@ public class RealmAdminResource { @PUT @Consumes("application/json") public void updateRole(final @PathParam("id") String id, final RoleRepresentation rep) { - new Transaction() { - @Override - protected void runImpl() { - RoleModel role = realm.getRoleById(id); - if (role == null) { - throw new NotFoundException(); - } - role.setName(rep.getName()); - role.setDescription(rep.getDescription()); - } - }.run(); - + RoleModel role = realm.getRoleById(id); + if (role == null) { + throw new NotFoundException(); + } + role.setName(rep.getName()); + role.setDescription(rep.getDescription()); } @Path("roles") @POST @Consumes("application/json") public Response createRole(final @Context UriInfo uriInfo, final RoleRepresentation rep) { - return new Transaction() { - @Override - protected Response callImpl() { - if (realm.getRole(rep.getName()) != null) { - throw new InternalServerErrorException(); // todo appropriate status here. - } - RoleModel role = realm.addRole(rep.getName()); - if (role == null) { - throw new NotFoundException(); - } - role.setDescription(rep.getDescription()); - return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getId()).build()).build(); - } - }.call(); - + if (realm.getRole(rep.getName()) != null) { + throw new InternalServerErrorException(); // todo appropriate status here. + } + RoleModel role = realm.addRole(rep.getName()); + if (role == null) { + throw new NotFoundException(); + } + role.setDescription(rep.getDescription()); + return Response.created(uriInfo.getAbsolutePathBuilder().path(role.getId()).build()).build(); } diff --git a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java index 1082f69a04..dc3b5124dd 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/RealmsAdminResource.java @@ -4,34 +4,17 @@ import org.jboss.resteasy.annotations.cache.NoCache; import org.jboss.resteasy.logging.Logger; import org.keycloak.representations.idm.RealmRepresentation; import org.keycloak.services.managers.RealmManager; +import org.keycloak.services.models.KeycloakSession; import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.UserModel; -import org.keycloak.services.resources.PublicRealmResource; import org.keycloak.services.resources.SaasService; -import org.keycloak.services.resources.Transaction; -import javax.ws.rs.Consumes; -import javax.ws.rs.ForbiddenException; -import javax.ws.rs.GET; -import javax.ws.rs.NotAuthorizedException; -import javax.ws.rs.NotFoundException; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.Produces; -import javax.ws.rs.core.CacheControl; -import javax.ws.rs.core.Context; -import javax.ws.rs.core.GenericEntity; -import javax.ws.rs.core.HttpHeaders; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; +import javax.ws.rs.*; +import javax.ws.rs.container.ResourceContext; +import javax.ws.rs.core.*; import java.net.URI; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import java.util.Map; /** * @author Bill Burke @@ -50,23 +33,24 @@ public class RealmsAdminResource { noCache.setNoCache(true); } + @Context + protected ResourceContext resourceContext; + + @Context + protected KeycloakSession session; + @GET @NoCache @Produces("application/json") public List getRealms() { - return new Transaction>() { - @Override - protected List callImpl() { - logger.info(("getRealms()")); - RealmManager realmManager = new RealmManager(session); - List realms = session.getRealms(admin); - List reps = new ArrayList(); - for (RealmModel realm : realms) { - reps.add(realmManager.toRepresentation(realm)); - } - return reps; - } - }.call(); + logger.info(("getRealms()")); + RealmManager realmManager = new RealmManager(session); + List realms = session.getRealms(admin); + List reps = new ArrayList(); + for (RealmModel realm : realms) { + reps.add(realmManager.toRepresentation(realm)); + } + return reps; } public static UriBuilder realmUrl(UriInfo uriInfo) { @@ -81,34 +65,26 @@ public class RealmsAdminResource { @Consumes("application/json") public Response importRealm(@Context final UriInfo uriInfo, final RealmRepresentation rep) { logger.info("importRealm: " + rep.getRealm()); - return new Transaction() { - @Override - protected Response callImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.importRealm(rep, admin); - URI location = realmUrl(uriInfo).build(realm.getId()); - logger.info("imported realm success, sending back: " + location.toString()); - return Response.created(location).build(); - } - }.call(); + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.importRealm(rep, admin); + URI location = realmUrl(uriInfo).build(realm.getId()); + logger.info("imported realm success, sending back: " + location.toString()); + return Response.created(location).build(); } @Path("{id}") public RealmAdminResource getRealmAdmin(@Context final HttpHeaders headers, @PathParam("id") final String id) { - return new Transaction(false) { - @Override - protected RealmAdminResource callImpl() { - RealmManager realmManager = new RealmManager(session); - RealmModel realm = realmManager.getRealm(id); - if (realm == null) throw new NotFoundException(); - if (!realm.isRealmAdmin(admin)) { - throw new ForbiddenException(); - } + RealmManager realmManager = new RealmManager(session); + RealmModel realm = realmManager.getRealm(id); + if (realm == null) throw new NotFoundException(); + if (!realm.isRealmAdmin(admin)) { + throw new ForbiddenException(); + } - return new RealmAdminResource(admin, realm); - } - }.call(); + RealmAdminResource adminResource = new RealmAdminResource(admin, realm); + resourceContext.initResource(adminResource); + return adminResource; } diff --git a/services/src/main/java/org/keycloak/services/resources/flows/Flows.java b/services/src/main/java/org/keycloak/services/resources/flows/Flows.java old mode 100644 new mode 100755 index 723d023567..e7ad5894b7 --- a/services/src/main/java/org/keycloak/services/resources/flows/Flows.java +++ b/services/src/main/java/org/keycloak/services/resources/flows/Flows.java @@ -21,13 +21,13 @@ */ package org.keycloak.services.resources.flows; -import javax.ws.rs.core.UriInfo; - import org.jboss.resteasy.spi.HttpRequest; import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.TokenManager; import org.keycloak.services.models.RealmModel; +import javax.ws.rs.core.UriInfo; + /** * @author Stian Thorgersen */ diff --git a/services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java b/services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java old mode 100644 new mode 100755 index d1e3407940..bbf453e110 --- a/services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java +++ b/services/src/main/java/org/keycloak/services/resources/flows/FormFlows.java @@ -21,14 +21,14 @@ */ package org.keycloak.services.resources.flows; -import javax.ws.rs.core.MultivaluedMap; -import javax.ws.rs.core.Response; - import org.jboss.resteasy.spi.HttpRequest; import org.keycloak.services.models.RealmModel; import org.keycloak.services.models.UserModel; import org.picketlink.idm.model.sample.Realm; +import javax.ws.rs.core.MultivaluedMap; +import javax.ws.rs.core.Response; + /** * @author Stian Thorgersen */ diff --git a/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java b/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java old mode 100644 new mode 100755 index 6a87ead696..da18de5405 --- a/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java +++ b/services/src/main/java/org/keycloak/services/resources/flows/OAuthFlows.java @@ -21,10 +21,6 @@ */ package org.keycloak.services.resources.flows; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.UriBuilder; -import javax.ws.rs.core.UriInfo; - import org.jboss.resteasy.logging.Logger; import org.jboss.resteasy.spi.HttpRequest; import org.keycloak.services.managers.AccessCodeEntry; @@ -36,6 +32,10 @@ import org.keycloak.services.models.RoleModel; import org.keycloak.services.models.UserModel; import org.keycloak.services.resources.TokenService; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.UriBuilder; +import javax.ws.rs.core.UriInfo; + /** * @author Bill Burke * @author Stian Thorgersen diff --git a/services/src/main/java/org/keycloak/services/resources/flows/PageFlows.java b/services/src/main/java/org/keycloak/services/resources/flows/PageFlows.java old mode 100644 new mode 100755 index 9b38098f59..dd6edb812d --- a/services/src/main/java/org/keycloak/services/resources/flows/PageFlows.java +++ b/services/src/main/java/org/keycloak/services/resources/flows/PageFlows.java @@ -21,12 +21,12 @@ */ package org.keycloak.services.resources.flows; -import javax.ws.rs.core.Response; - import org.jboss.resteasy.logging.Logger; import org.jboss.resteasy.spi.HttpRequest; import org.keycloak.services.JspRequestParameters; +import javax.ws.rs.core.Response; + /** * @author Stian Thorgersen */ diff --git a/services/src/main/java/org/keycloak/services/resources/flows/Urls.java b/services/src/main/java/org/keycloak/services/resources/flows/Urls.java old mode 100644 new mode 100755 index 3079602e0c..62b9e561ff --- a/services/src/main/java/org/keycloak/services/resources/flows/Urls.java +++ b/services/src/main/java/org/keycloak/services/resources/flows/Urls.java @@ -21,15 +21,10 @@ */ package org.keycloak.services.resources.flows; -import java.net.URI; +import org.keycloak.services.resources.*; import javax.ws.rs.core.UriBuilder; - -import org.keycloak.services.resources.AccountService; -import org.keycloak.services.resources.RealmsResource; -import org.keycloak.services.resources.SaasService; -import org.keycloak.services.resources.SocialResource; -import org.keycloak.services.resources.TokenService; +import java.net.URI; /** * @author Stian Thorgersen diff --git a/services/src/main/java/org/keycloak/services/validation/Validation.java b/services/src/main/java/org/keycloak/services/validation/Validation.java old mode 100644 new mode 100755 index f8d85bc42d..58b0650ab6 --- a/services/src/main/java/org/keycloak/services/validation/Validation.java +++ b/services/src/main/java/org/keycloak/services/validation/Validation.java @@ -1,12 +1,11 @@ package org.keycloak.services.validation; -import java.util.List; - -import javax.ws.rs.core.MultivaluedMap; - import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.services.messages.Messages; +import javax.ws.rs.core.MultivaluedMap; +import java.util.List; + public class Validation { public static String validateRegistrationForm(MultivaluedMap formData, List requiredCredentialTypes) { diff --git a/services/src/test/java/org/keycloak/test/AbstractKeycloakServerTest.java b/services/src/test/java/org/keycloak/test/AbstractKeycloakServerTest.java new file mode 100755 index 0000000000..a2b00e14a4 --- /dev/null +++ b/services/src/test/java/org/keycloak/test/AbstractKeycloakServerTest.java @@ -0,0 +1,70 @@ +package org.keycloak.test; + +import io.undertow.servlet.Servlets; +import io.undertow.servlet.api.DeploymentInfo; +import io.undertow.servlet.api.FilterInfo; +import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; +import org.jboss.resteasy.jwt.JsonSerialization; +import org.jboss.resteasy.plugins.server.undertow.UndertowJaxrsServer; +import org.jboss.resteasy.spi.ResteasyDeployment; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.keycloak.SkeletonKeyContextResolver; +import org.keycloak.representations.idm.RealmRepresentation; +import org.keycloak.services.filters.KeycloakSessionServletFilter; +import org.keycloak.services.resources.KeycloakApplication; + +import javax.servlet.DispatcherType; +import javax.ws.rs.client.Client; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +/** + * @author Bill Burke + * @version $Revision: 1 $ + */ +public class AbstractKeycloakServerTest { + public static UndertowJaxrsServer server; + public static ResteasyDeployment deployment; + public static Client client; + public static KeycloakApplication application; + + @BeforeClass + public static void undertowSetup() throws Exception { + deployment = new ResteasyDeployment(); + deployment.setApplicationClass(KeycloakApplication.class.getName()); + server = new UndertowJaxrsServer().start(); + DeploymentInfo di = server.undertowDeployment(deployment); + di.setClassLoader(AbstractKeycloakServerTest.class.getClassLoader()); + di.setContextPath("/"); + di.setDeploymentName("Keycloak"); + + FilterInfo filter = Servlets.filter("SessionFilter", KeycloakSessionServletFilter.class); + di.addFilter(filter); + di.addFilterUrlMapping("SessionFilter", "/*", DispatcherType.REQUEST); + server.deploy(di); + application = (KeycloakApplication) deployment.getApplication(); + client = new ResteasyClientBuilder().connectionPoolSize(10).build(); + client.register(SkeletonKeyContextResolver.class); + + } + + @AfterClass + public static void undertowShutdown() throws Exception { + server.stop(); + } + + public static RealmRepresentation loadJson(String path) throws IOException { + InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path); + ByteArrayOutputStream os = new ByteArrayOutputStream(); + int c; + while ((c = is.read()) != -1) { + os.write(c); + } + byte[] bytes = os.toByteArray(); + System.out.println(new String(bytes)); + + return JsonSerialization.fromBytes(RealmRepresentation.class, bytes); + } +} diff --git a/services/src/test/java/org/keycloak/test/ImportTest.java b/services/src/test/java/org/keycloak/test/ImportTest.java index e237c67b8d..33dbebef35 100755 --- a/services/src/test/java/org/keycloak/test/ImportTest.java +++ b/services/src/test/java/org/keycloak/test/ImportTest.java @@ -66,7 +66,7 @@ public class ImportTest { UserModel admin = defaultRealm.addUser("admin"); defaultRealm.grantRole(admin, role); - RealmRepresentation rep = KeycloakTestBase.loadJson("testrealm.json"); + RealmRepresentation rep = AbstractKeycloakServerTest.loadJson("testrealm.json"); RealmModel realm = manager.createRealm("demo", rep.getRealm()); manager.importRealm(rep, realm); realm.addRealmAdmin(admin); @@ -141,7 +141,7 @@ public class ImportTest { UserModel admin = defaultRealm.addUser("admin"); defaultRealm.grantRole(admin, role); - RealmRepresentation rep = KeycloakTestBase.loadJson("testrealm-demo.json"); + RealmRepresentation rep = AbstractKeycloakServerTest.loadJson("testrealm-demo.json"); RealmModel realm = manager.createRealm("demo", rep.getRealm()); manager.importRealm(rep, realm); realm.addRealmAdmin(admin); diff --git a/services/src/test/java/org/keycloak/test/KeycloakTestBase.java b/services/src/test/java/org/keycloak/test/KeycloakTestBase.java deleted file mode 100755 index 5bd0b6da7a..0000000000 --- a/services/src/test/java/org/keycloak/test/KeycloakTestBase.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.keycloak.test; - -import org.jboss.resteasy.jwt.JsonSerialization; -import org.jboss.resteasy.test.BaseResourceTest; -import org.keycloak.representations.idm.RealmRepresentation; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; - -/** - * @author Bill Burke - * @version $Revision: 1 $ - */ -public class KeycloakTestBase extends BaseResourceTest -{ - public static RealmRepresentation loadJson(String path) throws IOException - { - InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream(path); - ByteArrayOutputStream os = new ByteArrayOutputStream(); - int c; - while ( (c = is.read()) != -1) - { - os.write(c); - } - byte[] bytes = os.toByteArray(); - System.out.println(new String(bytes)); - - return JsonSerialization.fromBytes(RealmRepresentation.class, bytes); - } -} diff --git a/services/src/test/java/org/keycloak/test/RealmCreationTest.java b/services/src/test/java/org/keycloak/test/RealmCreationTest.java index 0d446ff2f6..c93c7429ab 100755 --- a/services/src/test/java/org/keycloak/test/RealmCreationTest.java +++ b/services/src/test/java/org/keycloak/test/RealmCreationTest.java @@ -1,12 +1,8 @@ package org.keycloak.test; -import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; -import org.jboss.resteasy.spi.ResteasyDeployment; -import org.jboss.resteasy.test.EmbeddedContainer; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; -import org.keycloak.SkeletonKeyContextResolver; import org.keycloak.representations.AccessTokenResponse; import org.keycloak.representations.idm.CredentialRepresentation; import org.keycloak.representations.idm.RealmRepresentation; @@ -15,10 +11,8 @@ import org.keycloak.services.managers.AuthenticationManager; import org.keycloak.services.managers.RealmManager; import org.keycloak.services.models.KeycloakSession; import org.keycloak.services.models.RealmModel; -import org.keycloak.services.resources.KeycloakApplication; import javax.ws.rs.NotAuthorizedException; -import javax.ws.rs.client.Client; import javax.ws.rs.client.Entity; import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.Form; @@ -31,30 +25,16 @@ import static org.jboss.resteasy.test.TestPortProvider.generateURL; * @author Bill Burke * @version $Revision: 1 $ */ -public class RealmCreationTest { - - private static ResteasyDeployment deployment; - private static Client client; +public class RealmCreationTest extends AbstractKeycloakServerTest { @BeforeClass public static void before() throws Exception { - deployment = new ResteasyDeployment(); - deployment.setApplicationClass(KeycloakApplication.class.getName()); - EmbeddedContainer.start(deployment); - KeycloakApplication application = (KeycloakApplication) deployment.getApplication(); KeycloakSession session = application.getFactory().createSession(); session.getTransaction().begin(); RealmManager manager = new RealmManager(session); new InstallationManager().install(manager); session.getTransaction().commit(); session.close(); - client = new ResteasyClientBuilder().build(); - client.register(SkeletonKeyContextResolver.class); - } - - public static void after() throws Exception { - client.close(); - EmbeddedContainer.stop(); } @Test @@ -86,7 +66,7 @@ public class RealmCreationTest { System.out.println(tokenResponse.getToken()); // - RealmRepresentation realm = KeycloakTestBase.loadJson("testrealm.json"); + RealmRepresentation realm = loadJson("testrealm.json"); response = target.path("saas/admin/realms").request().header(HttpHeaders.AUTHORIZATION, "Bearer " + tokenResponse.getToken()).post(Entity.json(realm)); Assert.assertEquals(201, response.getStatus()); response.close();
    {{user.userId}}{{user.username}} {{user.firstName}} {{user.lastName}} {{user.email}}