You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by gr...@apache.org on 2015/04/16 20:09:25 UTC

[1/9] incubator-usergrid git commit: First cut of Usergrid Central SSO feature, with tests.

Repository: incubator-usergrid
Updated Branches:
  refs/heads/master 6d962b7fe -> 25d0077ed


First cut of Usergrid Central SSO feature, with tests.


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/098355f8
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/098355f8
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/098355f8

Branch: refs/heads/master
Commit: 098355f8521a7528fe0fa44e9ce959f7c4c603d8
Parents: 9ef73e7
Author: Dave Johnson <dm...@apigee.com>
Authored: Mon Apr 13 11:24:53 2015 -0400
Committer: Dave Johnson <dm...@apigee.com>
Committed: Mon Apr 13 11:24:53 2015 -0400

----------------------------------------------------------------------
 .../rest/management/ManagementResource.java     | 170 ++++++++++++++++++-
 .../OAuth2AccessTokenSecurityFilter.java        |   5 +
 .../rest/management/ManagementResourceIT.java   |  71 +++++++-
 .../rest/test/PropertiesResourceIT.java         |  23 +--
 .../usergrid/management/ManagementService.java  |   5 +-
 .../cassandra/ManagementServiceImpl.java        |   7 +
 .../apache/usergrid/security/shiro/Realm.java   |  10 +-
 .../usergrid/security/tokens/TokenService.java  |   3 +
 .../tokens/cassandra/TokenServiceImpl.java      |  44 ++++-
 .../security/tokens/TokenServiceIT.java         |  42 +++++
 10 files changed, 354 insertions(+), 26 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/098355f8/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
index c590140..c1c0be5 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
@@ -19,21 +19,25 @@ package org.apache.usergrid.rest.management;
 
 import java.net.URLEncoder;
 import java.util.Map;
+import java.util.UUID;
 
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DefaultValue;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.GET;
-import javax.ws.rs.HeaderParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.QueryParam;
+import javax.ws.rs.*;
 import javax.ws.rs.core.Context;
 import javax.ws.rs.core.MediaType;
 import javax.ws.rs.core.Response;
 import javax.ws.rs.core.UriInfo;
 
+import com.sun.jersey.api.client.Client;
+import com.sun.jersey.api.client.config.ClientConfig;
+import com.sun.jersey.api.client.config.DefaultClientConfig;
+import com.sun.jersey.api.json.JSONConfiguration;
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.usergrid.management.OrganizationInfo;
+import org.apache.usergrid.management.OrganizationOwnerInfo;
+import org.apache.usergrid.persistence.exceptions.EntityNotFoundException;
+import org.apache.usergrid.rest.security.annotations.RequireSystemAccess;
+import org.apache.usergrid.utils.UUIDUtils;
+import org.codehaus.jackson.JsonNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.context.annotation.Scope;
@@ -95,6 +99,8 @@ public class ManagementResource extends AbstractContextResource {
 
     private static final Logger logger = LoggerFactory.getLogger( ManagementResource.class );
 
+    public static final String USERGRID_CENTRAL_URL = "usergrid.central.url";
+
 
     public ManagementResource() {
         logger.info( "ManagementResource initialized" );
@@ -441,6 +447,152 @@ public class ManagementResource extends AbstractContextResource {
     }
 
 
+    /**
+     * <p>
+     * Validates access token from other or "external" Usergrid system.
+     * Calls other system's /management/me endpoint to get the User associated with the access token.
+     * If user does not exist locally, then user and organization with the same name of user is created.
+     * If no user is returned from the other cluster, then this endpoint will return 401.
+     * <p>
+     *
+     * <p>
+     * See <a href="https://issues.apache.org/jira/browse/USERGRID-567">USERGRID-567</a>
+     * for details about Usergrid Central SSO.
+     * </p>
+     *
+     * @param ui             Information about calling URI.
+     * @param json           JSON object with fields: ext_access_token, ttl
+     * @param callback       For JSONP support.
+     * @return               Returns JSON object with access_token field.
+     * @throws Exception     Returns 401 if access token cannot be validated
+     */
+    @POST
+    @Path( "/externaltoken" )
+    //@RequireSystemAccess TODO: should this be required
+    public Response validateExternalToken(
+            @Context UriInfo ui,
+            Map<String, Object> json,
+            @QueryParam( "callback" ) @DefaultValue( "" ) String callback )  throws Exception {
+
+        Object extAccessTokenObj = json.get("ext_access_token");
+        if ( extAccessTokenObj == null ) {
+            throw new IllegalArgumentException("ext_access_token must be specified");
+        }
+        String extAccessToken = json.get("ext_access_token").toString();
+
+        Object ttlObj = json.get("ttl");
+        if ( ttlObj == null ) {
+            throw new IllegalArgumentException("ttl must be specified");
+        }
+        long ttl;
+        try {
+            ttl = Long.parseLong(ttlObj.toString());
+        } catch ( NumberFormatException e ) {
+            throw new IllegalArgumentException("ttl must be specified as a long");
+        }
+
+        return validateExternalToken( ui, extAccessToken, ttl, callback );
+    }
+
+
+    /**
+     * <p>
+     * Validates access token from other or "external" Usergrid system.
+     * Calls other system's /management/me endpoint to get the User associated with the access token.
+     * If user does not exist locally, then user and organization with the same name of user is created.
+     * If no user is returned from the other cluster, then this endpoint will return 401.
+     * </p>
+     *
+     * <p> Part of Usergrid Central SSO feature.
+     * See <a href="https://issues.apache.org/jira/browse/USERGRID-567">USERGRID-567</a>
+     * for details about Usergrid Central SSO.
+     * </p>
+     *
+     * @param ui             Information about calling URI.
+     * @param extAccessToken Access token from external Usergrid system.
+     * @param ttl            Time to live for token.
+     * @param callback       For JSONP support.
+     * @return               Returns JSON object with access_token field.
+     * @throws Exception     Returns 401 if access token cannot be validated
+     */
+    @GET
+    @Path( "/externaltoken" )
+    //@RequireSystemAccess TODO: should this be required
+    public Response validateExternalToken(
+                                @Context UriInfo ui,
+                                @QueryParam( "ext_access_token" ) String extAccessToken,
+                                @QueryParam( "ttl" ) @DefaultValue("-1") long ttl,
+                                @QueryParam( "callback" ) @DefaultValue( "" ) String callback )
+            throws Exception {
+
+
+        if ( extAccessToken == null ) {
+            throw new IllegalArgumentException("ext_access_token must be specified");
+        }
+
+        if ( ttl == -1 ) {
+            throw new IllegalArgumentException("ttl must be specified");
+        }
+
+        // create URL of central Usergrid's /management/me endpoint
+
+        String externalUrl = properties.getProperty( USERGRID_CENTRAL_URL ).trim();
+        // be lenient about trailing slash
+        externalUrl = !externalUrl.endsWith( "/" ) ? externalUrl + "/" : externalUrl;
+        String me = externalUrl + "management/me?access_token=" + extAccessToken;
+
+        // use our favorite HTTP client to GET /management/me
+
+        ClientConfig clientConfig = new DefaultClientConfig();
+        clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+        Client client = Client.create(clientConfig);
+        final JsonNode accessInfoNode;
+        try {
+            accessInfoNode = client.resource( me )
+                    .type(MediaType.APPLICATION_JSON_TYPE)
+                    .get(JsonNode.class);
+
+        } catch ( Exception e ) {
+            // user not found 404
+            String msg = "Cannot find Admin User associated with " + extAccessToken;
+            throw new EntityNotFoundException( msg, e );
+        }
+
+        // good. user was found in central Usergrid
+
+        JsonNode userNode = accessInfoNode.get( "user" );
+        UUID userId     = UUIDUtils.tryExtractUUID( userNode.get( "uuid" ).getTextValue() );
+        String username = userNode.get( "username" ).getTextValue();
+        String name     = userNode.get( "name" ).getTextValue();
+        String email    = userNode.get( "email" ).getTextValue();
+
+        // set dummy password to random string that nobody can guess, in SSO setup
+        // admin users should never be able to login directly to this Usergrid system
+        String dummyPassword = RandomStringUtils.randomAlphanumeric( 40 );
+
+        // if user does not exist locally then we need to fix that
+
+        final OrganizationInfo organizationInfo = management.getOrganizationByName(username);
+        if ( organizationInfo == null ) {
+
+            // create local user and personal organization, activate user.
+
+            OrganizationOwnerInfo ownerOrgInfo = management.createOwnerAndOrganization(
+                    username, username, name, email, dummyPassword, true, true);
+        }
+
+        // store the external access_token as if it were one of our own
+        management.importTokenForAdminUser( userId, extAccessToken, ttl );
+
+        // success! return JSON object with access_token field
+        AccessInfo accessInfo = new AccessInfo()
+                .withExpiresIn( tokens.getMaxTokenAgeInSeconds(extAccessToken ) )
+                .withAccessToken( extAccessToken );
+
+        return Response.status( SC_OK ).type( jsonMediaType( callback ) ).entity( accessInfo ).build();
+    }
+
+
     String errorMsg = "";
     String responseType;
     String clientId;

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/098355f8/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/OAuth2AccessTokenSecurityFilter.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/OAuth2AccessTokenSecurityFilter.java b/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/OAuth2AccessTokenSecurityFilter.java
index f4c4fc5..e3a7d54 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/OAuth2AccessTokenSecurityFilter.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/OAuth2AccessTokenSecurityFilter.java
@@ -104,7 +104,12 @@ public class OAuth2AccessTokenSecurityFilter extends SecurityFilter {
                 catch ( InvalidTokenException ite ) {
                     throw mappableSecurityException( INVALID_AUTH_ERROR );
                 }
+                catch ( IndexOutOfBoundsException ioobe ) {
+                    // token is just some rubbish string
+                    throw mappableSecurityException( BAD_ACCESS_TOKEN_ERROR );
+                }
                 catch ( Exception e ) {
+                    // unexpected so we log it
                     LOG.error( "unable to verify oauth token", e );
                     throw mappableSecurityException( UNVERIFIED_OAUTH_ERROR );
                 }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/098355f8/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java b/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java
index 13cb2ae..b18614d 100644
--- a/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java
+++ b/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java
@@ -26,6 +26,7 @@ import java.util.UUID;
 
 import javax.ws.rs.core.MediaType;
 
+import org.apache.commons.lang.RandomStringUtils;
 import org.codehaus.jackson.JsonNode;
 import org.junit.Test;
 
@@ -40,12 +41,13 @@ import org.apache.usergrid.rest.management.organizations.OrganizationsResource;
 import com.sun.jersey.api.client.ClientResponse.Status;
 import com.sun.jersey.api.client.UniformInterfaceException;
 import com.sun.jersey.api.representation.Form;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import static org.apache.usergrid.utils.MapUtils.hashMap;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+
+import static org.apache.usergrid.rest.management.ManagementResource.USERGRID_CENTRAL_URL;
+import static org.junit.Assert.*;
 
 
 /**
@@ -54,6 +56,8 @@ import static org.junit.Assert.assertTrue;
 @Concurrent()
 public class ManagementResourceIT extends AbstractRestIT {
 
+    private static final Logger logger = LoggerFactory.getLogger(ManagementResourceIT.class);
+
     public ManagementResourceIT() throws Exception {
 
     }
@@ -640,4 +644,63 @@ public class ManagementResourceIT extends AbstractRestIT {
         assertEquals( Status.OK, status );
     }
 
+
+    @Test
+    public void validateExternalToken() throws Exception {
+
+        // set the Usergrid Central SSO URL becuase Tomcat port is dynamically assigned
+
+        String suToken = superAdminToken();
+
+        Map<String, String> props = new HashMap<String, String>();
+        props.put( USERGRID_CENTRAL_URL, getBaseURI().toURL().toExternalForm());
+        resource().path( "/testproperties" )
+                .queryParam( "access_token", suToken)
+                .accept( MediaType.APPLICATION_JSON )
+                .type( MediaType.APPLICATION_JSON_TYPE )
+                .post( props );
+
+        // create a new admin user, get access token
+
+        String rand = RandomStringUtils.randomAlphanumeric(10);
+        final String username = "user_" + rand;
+        OrganizationOwnerInfo orgInfo = setup.getMgmtSvc().createOwnerAndOrganization(
+                username, username, "Test User", username + "@example.com", "password" );
+
+        Map<String, Object> loginInfo = new HashMap<String, Object>() {{
+            put("username", username );
+            put("password", "password");
+            put("grant_type", "password");
+        }};
+        JsonNode accessInfoNode = resource().path("/management/token")
+            .type( MediaType.APPLICATION_JSON_TYPE )
+            .post( JsonNode.class, loginInfo );
+        String accessToken = accessInfoNode.get( "access_token" ).getTextValue();
+
+        // attempt to validate the token, must be valid
+
+        JsonNode validatedNode = resource().path( "/management/externaltoken" )
+            .queryParam( "access_token", suToken ) // as superuser
+            .queryParam( "ext_access_token", accessToken )
+            .queryParam( "ttl", "1000" )
+            .get( JsonNode.class );
+        String validatedAccessToken = validatedNode.get( "access_token" ).getTextValue();
+        assertEquals( accessToken, validatedAccessToken );
+
+        // attempt to validate an invalid token, must fail
+
+        try {
+            JsonNode invalidNode = resource().path( "/management/externaltoken" )
+                .queryParam( "access_token", suToken ) // as superuser
+                .queryParam( "ext_access_token", "rubbish_token")
+                .queryParam( "ttl", "1000" )
+                .get( JsonNode.class );
+            fail("Validation should have failed");
+        } catch ( Exception expected ) {}
+
+
+        // TODO: how do we test the create new user and organization case?
+
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/098355f8/stack/rest/src/test/java/org/apache/usergrid/rest/test/PropertiesResourceIT.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/test/java/org/apache/usergrid/rest/test/PropertiesResourceIT.java b/stack/rest/src/test/java/org/apache/usergrid/rest/test/PropertiesResourceIT.java
index ebd6f9e..db3f046 100644
--- a/stack/rest/src/test/java/org/apache/usergrid/rest/test/PropertiesResourceIT.java
+++ b/stack/rest/src/test/java/org/apache/usergrid/rest/test/PropertiesResourceIT.java
@@ -36,9 +36,6 @@ import static org.apache.usergrid.management.AccountCreationProps.PROPERTIES_ADM
 public class PropertiesResourceIT extends AbstractRestIT {
     static final Logger logger = LoggerFactory.getLogger( PropertiesResourceIT.class );
 
-    @Autowired
-    protected ServiceManagerFactory smf;
-
 
     @Test
     public void testBasicOperation() {
@@ -51,25 +48,31 @@ public class PropertiesResourceIT extends AbstractRestIT {
 
         // verify that is is not set in Jetty
         {
-            Map<String, String> map = resource().path( "/testproperties" ).queryParam( "access_token", access_token )
-                    .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE ).get( Map.class );
-            Assert.assertFalse( Boolean.parseBoolean( map.get( PROPERTIES_ADMIN_USERS_REQUIRE_CONFIRMATION ) ) );
+            Map map = resource().path( "/testproperties" )
+                    .queryParam( "access_token", access_token )
+                    .accept( MediaType.APPLICATION_JSON )
+                    .type( MediaType.APPLICATION_JSON_TYPE ).get(Map.class);
+            Assert.assertFalse( Boolean.parseBoolean(
+                    map.get( PROPERTIES_ADMIN_USERS_REQUIRE_CONFIRMATION ).toString() ) );
         }
 
         // set property in Jetty
         {
             Map<String, String> props = new HashMap<String, String>();
             props.put( PROPERTIES_ADMIN_USERS_REQUIRE_CONFIRMATION, "true" );
-            resource().path( "/testproperties" ).queryParam( "access_token", access_token )
-                    .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE ).post( props );
+            resource().path( "/testproperties" )
+                    .queryParam( "access_token", access_token )
+                    .accept( MediaType.APPLICATION_JSON )
+                    .type( MediaType.APPLICATION_JSON_TYPE ).post( props );
         }
 
         // verify that it is set in Jetty
         {
-            Map<String, String> map = resource().path( "/testproperties" ).queryParam( "access_token", access_token )
+            Map map = resource().path( "/testproperties" ).queryParam( "access_token", access_token )
                     .accept( MediaType.APPLICATION_JSON ).type( MediaType.APPLICATION_JSON_TYPE ).get( Map.class );
 
-            Assert.assertTrue( Boolean.parseBoolean( map.get( PROPERTIES_ADMIN_USERS_REQUIRE_CONFIRMATION ) ) );
+            Assert.assertTrue( Boolean.parseBoolean(
+                    map.get( PROPERTIES_ADMIN_USERS_REQUIRE_CONFIRMATION ).toString() ) );
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/098355f8/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java b/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java
index 865f296..56343d4 100644
--- a/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java
+++ b/stack/services/src/main/java/org/apache/usergrid/management/ManagementService.java
@@ -109,7 +109,7 @@ public interface ManagementService {
 
     public String getAccessTokenForAdminUser( UUID userId, long duration ) throws Exception;
 
-    /** Revoke all active access tokens for this admin user */
+   /** Revoke all active access tokens for this admin user */
     public void revokeAccessTokensForAdminUser( UUID userId ) throws Exception;
 
     public void revokeAccessTokenForAdminUser( UUID userId, String token ) throws Exception;
@@ -120,6 +120,9 @@ public interface ManagementService {
 
     public String getActivationTokenForOrganization( UUID organizationId, long ttl ) throws Exception;
 
+    /** Import an Admin User token generated by some other system */
+    public void importTokenForAdminUser( UUID userId, String token, long ttl ) throws Exception;
+
     public ServiceResults getAdminUserActivities( UserInfo user ) throws Exception;
 
     public ServiceResults getAdminUserActivity( UserInfo user ) throws Exception;

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/098355f8/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java
index a2e1271..5b77534 100644
--- a/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java
+++ b/stack/services/src/main/java/org/apache/usergrid/management/cassandra/ManagementServiceImpl.java
@@ -1391,6 +1391,13 @@ public class ManagementServiceImpl implements ManagementService {
     }
 
 
+    @Override
+    public void importTokenForAdminUser(UUID userId, String token, long ttl) throws Exception {
+        tokens.importToken( token, TokenCategory.ACCESS, null,
+                new AuthPrincipalInfo( ADMIN_USER, userId, MANAGEMENT_APPLICATION_ID ), null, ttl );
+    }
+
+
     /*
    * (non-Javadoc)
    * 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/098355f8/stack/services/src/main/java/org/apache/usergrid/security/shiro/Realm.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/security/shiro/Realm.java b/stack/services/src/main/java/org/apache/usergrid/security/shiro/Realm.java
index 84f4fe5..0f1f9e8 100644
--- a/stack/services/src/main/java/org/apache/usergrid/security/shiro/Realm.java
+++ b/stack/services/src/main/java/org/apache/usergrid/security/shiro/Realm.java
@@ -235,8 +235,16 @@ public class Realm extends AuthorizingRealm {
 
         for ( PrincipalIdentifier principal : principals.byType( PrincipalIdentifier.class ) ) {
 
+            // TODO: refactor so that this whole instanceof mess can be replaced with this:
+            // principle.addRolesAndPermissionsToInfo( info );
+            // principle.addApplicationsToSet( applicationsSet );
+            // principle.addOrganizationsToSet( applicationsSet );
+            // organization = principle.getOrganization();
+            // application = principle.getApplication();
+
             if ( principal instanceof OrganizationPrincipal ) {
-                // OrganizationPrincipals are usually only through OAuth
+
+                // OrganizationPricipals are usually only through OAuth
                 // They have access to a single organization
 
                 organization = ( ( OrganizationPrincipal ) principal ).getOrganization();

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/098355f8/stack/services/src/main/java/org/apache/usergrid/security/tokens/TokenService.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/security/tokens/TokenService.java b/stack/services/src/main/java/org/apache/usergrid/security/tokens/TokenService.java
index 8b5863f..36decce 100644
--- a/stack/services/src/main/java/org/apache/usergrid/security/tokens/TokenService.java
+++ b/stack/services/src/main/java/org/apache/usergrid/security/tokens/TokenService.java
@@ -31,6 +31,9 @@ public interface TokenService {
     public String createToken( TokenCategory tokenCategory, String type, AuthPrincipalInfo principal,
                                Map<String, Object> state, long duration ) throws Exception;
 
+    public void importToken( String token, TokenCategory tokenCategory, String type, AuthPrincipalInfo principal,
+                               Map<String, Object> state, long duration ) throws Exception;
+
     /** Get the token info for the string version of this token */
     public TokenInfo getTokenInfo( String token ) throws Exception;
 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/098355f8/stack/services/src/main/java/org/apache/usergrid/security/tokens/cassandra/TokenServiceImpl.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/security/tokens/cassandra/TokenServiceImpl.java b/stack/services/src/main/java/org/apache/usergrid/security/tokens/cassandra/TokenServiceImpl.java
index 50156b5..7ea2af3 100644
--- a/stack/services/src/main/java/org/apache/usergrid/security/tokens/cassandra/TokenServiceImpl.java
+++ b/stack/services/src/main/java/org/apache/usergrid/security/tokens/cassandra/TokenServiceImpl.java
@@ -230,14 +230,56 @@ public class TokenServiceImpl implements TokenService {
             Assert.notNull( principal.getUuid() );
         }
 
+        // create UUID that we will use to store token info in our database
         UUID uuid = UUIDUtils.newTimeUUID( creationTimestamp );
+
         long timestamp = getTimestampInMillis( uuid );
         if ( type == null ) {
             type = TOKEN_TYPE_ACCESS;
         }
         TokenInfo tokenInfo = new TokenInfo( uuid, type, timestamp, timestamp, 0, duration, principal, state );
         putTokenInfo( tokenInfo );
-        return getTokenForUUID( tokenInfo, tokenCategory, uuid );
+
+        // generate token from the UUID that we created
+        return getTokenForUUID(tokenInfo, tokenCategory, uuid);
+    }
+
+
+    @Override
+    public void importToken(String token, TokenCategory tokenCategory, String type, AuthPrincipalInfo principal,
+                            Map<String, Object> state, long duration) throws Exception {
+
+        // same logic as create token
+
+        long maxTokenTtl = getMaxTtl( tokenCategory, principal );
+
+        if ( duration > maxTokenTtl ) {
+            throw new IllegalArgumentException(
+                    String.format( "Your token age cannot be more than the maximum age of %d milliseconds",
+                            maxTokenTtl ) );
+        }
+
+        if ( duration == 0 ) {
+            duration = maxTokenTtl;
+        }
+
+        if ( principal != null ) {
+            Assert.notNull( principal.getType() );
+            Assert.notNull( principal.getApplicationId() );
+            Assert.notNull( principal.getUuid() );
+        }
+
+        // except that we generate the UUID based on the token
+
+        UUID uuid = getUUIDForToken(token);
+
+        long timestamp = getTimestampInMillis( uuid );
+        if ( type == null ) {
+            type = TOKEN_TYPE_ACCESS;
+        }
+
+        TokenInfo tokenInfo = new TokenInfo( uuid, type, timestamp, timestamp, 0, duration, principal, state );
+        putTokenInfo( tokenInfo );
     }
 
 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/098355f8/stack/services/src/test/java/org/apache/usergrid/security/tokens/TokenServiceIT.java
----------------------------------------------------------------------
diff --git a/stack/services/src/test/java/org/apache/usergrid/security/tokens/TokenServiceIT.java b/stack/services/src/test/java/org/apache/usergrid/security/tokens/TokenServiceIT.java
index 0141c9b..58ab3e6 100644
--- a/stack/services/src/test/java/org/apache/usergrid/security/tokens/TokenServiceIT.java
+++ b/stack/services/src/test/java/org/apache/usergrid/security/tokens/TokenServiceIT.java
@@ -454,4 +454,46 @@ public class TokenServiceIT {
 
         assertTrue( invalidTokenException );
     }
+
+    @Test
+    public void testImportToken() throws Exception {
+
+        // create admin user token and make sure it is working
+
+        AuthPrincipalInfo adminPrincipal = new AuthPrincipalInfo(
+                AuthPrincipalType.ADMIN_USER, adminUser.getUuid(), UUIDUtils.newTimeUUID() );
+
+        String tokenStr = setup.getTokenSvc().createToken(
+                TokenCategory.ACCESS, null, adminPrincipal, null, 0 );
+
+        log.info("token: " + tokenStr);
+
+        // revoke token and check to make sure it is no longer valid
+
+        setup.getTokenSvc().revokeToken( tokenStr );
+
+        boolean invalidTokenException = false;
+        try {
+            setup.getTokenSvc().getTokenInfo( tokenStr );
+        }
+        catch ( InvalidTokenException ite ) {
+            invalidTokenException = true;
+        }
+        assertTrue(invalidTokenException);
+
+        // import same token and make sure it works again
+
+        setup.getTokenSvc().importToken( tokenStr, TokenCategory.ACCESS, null, adminPrincipal, null, 0 );
+
+        TokenInfo tokenInfo = setup.getTokenSvc().getTokenInfo( tokenStr );
+
+        long last_access = tokenInfo.getAccessed();
+
+        assertEquals( "access", tokenInfo.getType() );
+        assertEquals( adminUser.getUuid(), tokenInfo.getPrincipal().getUuid() );
+
+        tokenInfo = setup.getTokenSvc().getTokenInfo( tokenStr );
+
+        assertTrue(last_access < tokenInfo.getAccessed());
+    }
 }


[9/9] incubator-usergrid git commit: An additional test for validate external tokens logic, plus some related fixes to superuser-only login logic.

Posted by gr...@apache.org.
An additional test for validate external tokens logic, plus some related fixes to superuser-only login logic.


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/25d0077e
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/25d0077e
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/25d0077e

Branch: refs/heads/master
Commit: 25d0077edd0b69607459ef3b0c87d276498adac9
Parents: 6ae492e
Author: Dave Johnson <dm...@apigee.com>
Authored: Thu Apr 16 11:22:07 2015 -0400
Committer: Dave Johnson <dm...@apigee.com>
Committed: Thu Apr 16 11:22:07 2015 -0400

----------------------------------------------------------------------
 .../rest/management/ManagementResource.java     | 161 ++++++++++---------
 .../rest/management/ManagementResourceIT.java   | 108 +++++++++++--
 2 files changed, 176 insertions(+), 93 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/25d0077e/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
index 73963fe..2bbcfd9 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
@@ -37,6 +37,7 @@ import org.apache.usergrid.exception.NotImplementedException;
 import org.apache.usergrid.management.ApplicationCreator;
 import org.apache.usergrid.management.OrganizationInfo;
 import org.apache.usergrid.management.OrganizationOwnerInfo;
+import org.apache.usergrid.persistence.entities.User;
 import org.apache.usergrid.persistence.exceptions.EntityNotFoundException;
 import org.codehaus.jackson.JsonNode;
 import org.slf4j.Logger;
@@ -87,6 +88,8 @@ import static org.apache.usergrid.utils.StringUtils.stringOrSubstringBeforeFirst
 } )
 public class ManagementResource extends AbstractContextResource {
 
+    private static final Logger logger = LoggerFactory.getLogger( ManagementResource.class );
+
     /*-
      * New endpoints:
      * 
@@ -99,32 +102,17 @@ public class ManagementResource extends AbstractContextResource {
      * 
      */
 
-    private static final Logger logger = LoggerFactory.getLogger( ManagementResource.class );
-
     @Autowired
     private ApplicationCreator applicationCreator;
 
     public static final String USERGRID_CENTRAL_URL = "usergrid.central.url";
 
-    private boolean superuserAllowed;
-
-    private boolean externalTokensEnabled;
+    public static final String USERGRID_SYSADMIN_LOGIN_NAME = "usergrid.sysadmin.login.name";
 
-    private String superuserName;
+    public static final String USERGRID_SYSADMIN_LOGIN_ALLOWED = "usergrid.sysadmin.login.allowed";
 
 
     public ManagementResource() {
-
-        String superuserAllowedStr =  properties.getProperty( "usergrid.sysadmin.login.allowed" );
-
-        superuserName = properties.getProperty( "usergrid.sysadmin.login.name" );
-
-        superuserAllowed = !StringUtils.isEmpty( superuserAllowedStr )
-                && superuserAllowedStr.trim().equalsIgnoreCase( "true" );
-
-        externalTokensEnabled =
-                !StringUtils.isEmpty( properties.getProperty( USERGRID_CENTRAL_URL ));
-
         logger.info( "ManagementResource initialized" );
     }
 
@@ -196,20 +184,11 @@ public class ManagementResource extends AbstractContextResource {
     }
 
 
-    private Response getAccessTokenInternal( UriInfo ui, String authorization, String grant_type, String username,
+   private Response getAccessTokenInternal( UriInfo ui, String authorization, String grant_type, String username,
                                              String password, String client_id, String client_secret, long ttl,
                                              String callback, boolean loadAdminData ) throws Exception {
 
 
-        // when external tokens (Usergrid Central SSO) are enabled only superuser can login as Admin User.
-        if ( externalTokensEnabled &&
-                superuserAllowed && !username.equalsIgnoreCase( superuserName )) {
-
-            // cause an HTTP 400 response with a useful message
-            throw  new IllegalArgumentException("Admin Users must login via " +
-                properties.getProperty( USERGRID_CENTRAL_URL ));
-        }
-
         UserInfo user = null;
 
         try {
@@ -222,6 +201,11 @@ public class ManagementResource extends AbstractContextResource {
             String errorDescription = "invalid username or password";
 
             if ( user == null ) {
+
+                // make sure authentication is allowed considering
+                // external token validation configuration (UG Central SSO)
+                ensureAuthenticationAllowed( username, grant_type );
+
                 if ( authorization != null ) {
                     String type = stringOrSubstringBeforeFirst( authorization, ' ' ).toUpperCase();
 
@@ -482,15 +466,7 @@ public class ManagementResource extends AbstractContextResource {
 
     /**
      * <p>
-     * Validates access token from other or "external" Usergrid system.
-     * Calls other system's /management/me endpoint to get the User associated with the access token.
-     * If user does not exist locally, then user and organization with the same name of user is created.
-     * If no user is returned from the other cluster, then this endpoint will return 401.
-     * <p>
-     *
-     * <p>
-     * See <a href="https://issues.apache.org/jira/browse/USERGRID-567">USERGRID-567</a>
-     * for details about Usergrid Central SSO.
+     * Allows call to validateExternalToken() (see below) with a POST of a JSON object.
      * </p>
      *
      * @param ui             Information about calling URI.
@@ -573,71 +549,74 @@ public class ManagementResource extends AbstractContextResource {
         if ( ttl == -1 ) {
             throw new IllegalArgumentException("ttl must be specified");
         }
+        AccessInfo accessInfo = null;
 
-        // look up user via UG Central's /management/me endpoint.
-
-        JsonNode accessInfoNode = getMeFromUgCentral( extAccessToken );
-
-        JsonNode userNode = accessInfoNode.get( "user" );
-        String username = userNode.get( "username" ).getTextValue();
+        try {
+            // look up user via UG Central's /management/me endpoint.
 
-        // if user does not exist locally then we need to fix that
+            JsonNode accessInfoNode = getMeFromUgCentral( extAccessToken );
 
-        UUID userId = management.getAdminUserByUsername( username ).getUuid();
+            JsonNode userNode = accessInfoNode.get( "user" );
+            String username = userNode.get( "username" ).getTextValue();
 
-        if ( userId == null ) {
+            // if user does not exist locally then we need to fix that
 
-            // create local user and and organizations they have on the central Usergrid instance
+            UserInfo userInfo = management.getAdminUserByUsername( username );
+            UUID userId = userInfo == null ? null : userInfo.getUuid();
 
-            String name     = userNode.get( "name" ).getTextValue();
-            String email    = userNode.get( "email" ).getTextValue();
+            if ( userId == null ) {
 
-            // set dummy password to random string that nobody can guess, in central SSO setup
-            // admin users should never be able to login directly to this Usergrid system
-            String dummyPassword = RandomStringUtils.randomAlphanumeric( 40 );
+                // create local user and and organizations they have on the central Usergrid instance
 
-            JsonNode orgsNode = userNode.get( "organizations" );
-            final Iterator<String> fieldNames = orgsNode.getFieldNames();
+                String name  = userNode.get( "name" ).getTextValue();
+                String email = userNode.get( "email" ).getTextValue();
+                String dummyPassword = RandomStringUtils.randomAlphanumeric( 40 );
 
-            UserInfo userInfo = null;
+                JsonNode orgsNode = userNode.get( "organizations" );
+                final Iterator<String> fieldNames = orgsNode.getFieldNames();
 
-            // create user and any organizations that user is supposed to have
+                // create user and any organizations that user is supposed to have
 
-            while ( fieldNames.hasNext() ) {
+                while ( fieldNames.hasNext() ) {
 
-                String orgName = fieldNames.next();
+                    String orgName = fieldNames.next();
 
-                if ( userId == null ) {
+                    if ( userId == null ) {
 
-                    // haven't created user yet so do that now
-                    OrganizationOwnerInfo ownerOrgInfo = management.createOwnerAndOrganization(
-                            orgName, username, name, email, dummyPassword, true, true );
+                        // haven't created user yet so do that now
+                        OrganizationOwnerInfo ownerOrgInfo = management.createOwnerAndOrganization(
+                                orgName, username, name, email, dummyPassword, true, true );
 
-                    management.activateOrganization( ownerOrgInfo.getOrganization() ); // redundant?
-                    applicationCreator.createSampleFor( ownerOrgInfo.getOrganization() );
+                        management.activateOrganization( ownerOrgInfo.getOrganization() ); // redundant?
+                        applicationCreator.createSampleFor( ownerOrgInfo.getOrganization() );
 
-                    userId = ownerOrgInfo.getOwner().getUuid();
-                    userInfo = ownerOrgInfo.getOwner();
+                        userId = ownerOrgInfo.getOwner().getUuid();
+                        userInfo = ownerOrgInfo.getOwner();
 
-                } else {
+                    } else {
 
-                    // already created user, so just create an org
-                    final OrganizationInfo organization = management.createOrganization( orgName, userInfo, true );
+                        // already created user, so just create an org
+                        final OrganizationInfo organization = management.createOrganization( orgName, userInfo, true );
 
-                    management.activateOrganization( organization ); // redundant?
-                    applicationCreator.createSampleFor( organization );
+                        management.activateOrganization( organization ); // redundant?
+                        applicationCreator.createSampleFor( organization );
+                    }
                 }
+
             }
 
-        }
+            // store the external access_token as if it were one of our own
+            management.importTokenForAdminUser( userId, extAccessToken, ttl );
 
-        // store the external access_token as if it were one of our own
-        management.importTokenForAdminUser( userId, extAccessToken, ttl );
+            // success! return JSON object with access_token field
+            accessInfo = new AccessInfo()
+                    .withExpiresIn( tokens.getMaxTokenAgeInSeconds( extAccessToken ) )
+                    .withAccessToken( extAccessToken );
 
-        // success! return JSON object with access_token field
-        AccessInfo accessInfo = new AccessInfo()
-                .withExpiresIn( tokens.getMaxTokenAgeInSeconds(extAccessToken ) )
-                .withAccessToken( extAccessToken );
+        } catch (Exception e) {
+            logger.debug("Error validating external token", e);
+            throw e;
+        }
 
         return Response.status( SC_OK ).type( jsonMediaType( callback ) ).entity( accessInfo ).build();
     }
@@ -680,6 +659,34 @@ public class ManagementResource extends AbstractContextResource {
     }
 
 
+    /**
+     * Check that authentication is allowed. If external token validation is enabled (Central Usergrid SSO)
+     * then only superusers should be allowed to login directly to this Usergrid instance.
+     */
+    private void ensureAuthenticationAllowed( String username, String grant_type ) {
+
+        final boolean externalTokensEnabled =
+                !StringUtils.isEmpty( properties.getProperty( USERGRID_CENTRAL_URL ) );
+
+        if ( externalTokensEnabled ) {
+
+            // when external tokens enabled then only superuser can obtain an access token
+
+            final String superuserName = properties.getProperty( USERGRID_SYSADMIN_LOGIN_NAME );
+            final String superuserAllowedStr = properties.getProperty( USERGRID_SYSADMIN_LOGIN_ALLOWED );
+            final boolean superuserAllowed = !StringUtils.isEmpty( superuserAllowedStr )
+                    && superuserAllowedStr.trim().equalsIgnoreCase( "true" );
+
+            if ( superuserAllowed && !superuserName.equalsIgnoreCase( username )) {
+
+                // this guy is not the superuser
+                throw new IllegalArgumentException( "Admin Users must login via " +
+                        properties.getProperty( USERGRID_CENTRAL_URL ) );
+            }
+        }
+    }
+
+
     String errorMsg = "";
     String responseType;
     String clientId;

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/25d0077e/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java b/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java
index b18614d..d6b507e 100644
--- a/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java
+++ b/stack/rest/src/test/java/org/apache/usergrid/rest/management/ManagementResourceIT.java
@@ -381,7 +381,7 @@ public class ManagementResourceIT extends AbstractRestIT {
         assertEquals( "test@usergrid.com", userdata.get( "data" ).get( "email" ).asText() );
 
         // wait for the token to expire
-        Thread.sleep( ttl - ( System.currentTimeMillis() - startTime ) + 1000 );
+        Thread.sleep( ttl - (System.currentTimeMillis() - startTime) + 1000 );
 
         Status responseStatus = null;
         try {
@@ -646,19 +646,7 @@ public class ManagementResourceIT extends AbstractRestIT {
 
 
     @Test
-    public void validateExternalToken() throws Exception {
-
-        // set the Usergrid Central SSO URL becuase Tomcat port is dynamically assigned
-
-        String suToken = superAdminToken();
-
-        Map<String, String> props = new HashMap<String, String>();
-        props.put( USERGRID_CENTRAL_URL, getBaseURI().toURL().toExternalForm());
-        resource().path( "/testproperties" )
-                .queryParam( "access_token", suToken)
-                .accept( MediaType.APPLICATION_JSON )
-                .type( MediaType.APPLICATION_JSON_TYPE )
-                .post( props );
+    public void testValidateExternalToken() throws Exception {
 
         // create a new admin user, get access token
 
@@ -677,6 +665,17 @@ public class ManagementResourceIT extends AbstractRestIT {
             .post( JsonNode.class, loginInfo );
         String accessToken = accessInfoNode.get( "access_token" ).getTextValue();
 
+        // set the Usergrid Central SSO URL because Tomcat port is dynamically assigned
+
+        String suToken = superAdminToken();
+        Map<String, String> props = new HashMap<String, String>();
+        props.put( USERGRID_CENTRAL_URL, getBaseURI().toURL().toExternalForm());
+        resource().path( "/testproperties" )
+                .queryParam( "access_token", suToken)
+                .accept( MediaType.APPLICATION_JSON )
+                .type( MediaType.APPLICATION_JSON_TYPE )
+                .post( props );
+
         // attempt to validate the token, must be valid
 
         JsonNode validatedNode = resource().path( "/management/externaltoken" )
@@ -690,17 +689,94 @@ public class ManagementResourceIT extends AbstractRestIT {
         // attempt to validate an invalid token, must fail
 
         try {
-            JsonNode invalidNode = resource().path( "/management/externaltoken" )
+            resource().path( "/management/externaltoken" )
                 .queryParam( "access_token", suToken ) // as superuser
                 .queryParam( "ext_access_token", "rubbish_token")
                 .queryParam( "ttl", "1000" )
                 .get( JsonNode.class );
             fail("Validation should have failed");
-        } catch ( Exception expected ) {}
+        } catch ( Exception actual ) {
+            logger.debug( "error", actual );
+        }
+
 
 
         // TODO: how do we test the create new user and organization case?
 
+
+
+        // unset the Usergrid Central SSO URL so it does not interfere with other tests
+
+        props.put( USERGRID_CENTRAL_URL, "" );
+        resource().path( "/testproperties" )
+                .queryParam( "access_token", suToken)
+                .accept( MediaType.APPLICATION_JSON )
+                .type( MediaType.APPLICATION_JSON_TYPE )
+                .post( props );
+
+    }
+
+
+    @Test
+    public void testSuperuserOnlyWhenValidateExternalTokensEnabled() throws Exception {
+
+        // create an org and an admin user
+
+        String rand = RandomStringUtils.randomAlphanumeric(10);
+        final String username = "user_" + rand;
+        OrganizationOwnerInfo orgInfo = setup.getMgmtSvc().createOwnerAndOrganization(
+                username, username, "Test User", username + "@example.com", "password" );
+
+        // turn on validate external tokens by setting the usergrid.central.url
+
+        String suToken = superAdminToken();
+        Map<String, String> props = new HashMap<String, String>();
+        props.put( USERGRID_CENTRAL_URL, getBaseURI().toURL().toExternalForm());
+        resource().path( "/testproperties" )
+                .queryParam( "access_token", suToken)
+                .accept( MediaType.APPLICATION_JSON )
+                .type( MediaType.APPLICATION_JSON_TYPE )
+                .post( props );
+
+        // calls to login as an Admin User must now fail
+
+        try {
+
+            Map<String, Object> loginInfo = new HashMap<String, Object>() {{
+                                                                              put("username", username );
+                                                                              put("password", "password");
+                                                                              put("grant_type", "password");
+                                                                              }};
+            JsonNode accessInfoNode = resource().path("/management/token")
+                    .type( MediaType.APPLICATION_JSON_TYPE )
+                    .post( JsonNode.class, loginInfo );
+            fail("Login as Admin User must fail when validate external tokens is enabled");
+
+        } catch ( Exception actual ) {
+            logger.debug( "error", actual );
+        }
+
+        // login as superuser must succeed
+
+        Map<String, Object> loginInfo = new HashMap<String, Object>() {{
+            put("username", "superuser");
+            put("password", "superpassword");
+            put("grant_type", "password");
+        }};
+        JsonNode accessInfoNode = resource().path("/management/token")
+                .type( MediaType.APPLICATION_JSON_TYPE )
+                .post( JsonNode.class, loginInfo );
+        String accessToken = accessInfoNode.get( "access_token" ).getTextValue();
+        assertNotNull( accessToken );
+
+        // turn off validate external tokens by un-setting the usergrid.central.url
+
+        props.put( USERGRID_CENTRAL_URL, "" );
+        resource().path( "/testproperties" )
+                .queryParam( "access_token", suToken)
+                .accept( MediaType.APPLICATION_JSON )
+                .type( MediaType.APPLICATION_JSON_TYPE )
+                .post( props );
     }
 
 }


[7/9] incubator-usergrid git commit: Merge branch 'master' of https://github.com/snoopdave/incubator-usergrid

Posted by gr...@apache.org.
Merge branch 'master' of https://github.com/snoopdave/incubator-usergrid


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/7aabf68f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/7aabf68f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/7aabf68f

Branch: refs/heads/master
Commit: 7aabf68f24d2d88bf3bd0fbc5afcb6d8257e83f0
Parents: 6d962b7 9a8d5e0
Author: Dave Johnson <dm...@apigee.com>
Authored: Thu Apr 16 09:40:33 2015 -0400
Committer: Dave Johnson <dm...@apigee.com>
Committed: Thu Apr 16 09:40:33 2015 -0400

----------------------------------------------------------------------
 .../main/resources/usergrid-default.properties  |   5 +
 .../rest/management/ManagementResource.java     | 260 ++++++++++++++++++-
 .../OAuth2AccessTokenSecurityFilter.java        |   5 +
 .../rest/management/ManagementResourceIT.java   |  71 ++++-
 .../rest/test/PropertiesResourceIT.java         |  23 +-
 .../usergrid/management/ManagementService.java  |   5 +-
 .../cassandra/ManagementServiceImpl.java        |   7 +
 .../apache/usergrid/security/shiro/Realm.java   |  10 +-
 .../usergrid/security/tokens/TokenService.java  |   3 +
 .../tokens/cassandra/TokenServiceImpl.java      |  44 +++-
 .../security/tokens/TokenServiceIT.java         |  42 +++
 11 files changed, 449 insertions(+), 26 deletions(-)
----------------------------------------------------------------------



[5/9] incubator-usergrid git commit: Merge branch 'master' into USERGRID-567-central-sso

Posted by gr...@apache.org.
Merge branch 'master' into USERGRID-567-central-sso


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/f2525470
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/f2525470
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/f2525470

Branch: refs/heads/master
Commit: f25254709a16b8e8c0814a00b4484159a8c1f0a7
Parents: 9a8d5e0 6d962b7
Author: Dave Johnson <dm...@apigee.com>
Authored: Wed Apr 15 14:16:33 2015 -0400
Committer: Dave Johnson <dm...@apigee.com>
Committed: Wed Apr 15 14:16:33 2015 -0400

----------------------------------------------------------------------
 .../org/apache/usergrid/tools/ExportAdmins.java | 236 ++++++++++
 .../org/apache/usergrid/tools/ImportAdmins.java | 451 +++++++++++++++++++
 2 files changed, 687 insertions(+)
----------------------------------------------------------------------



[3/9] incubator-usergrid git commit: small refactor.

Posted by gr...@apache.org.
small refactor.


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/27757b32
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/27757b32
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/27757b32

Branch: refs/heads/master
Commit: 27757b3292c97af81ca8e38a93a0c949811ee362
Parents: c15fcc8
Author: Dave Johnson <dm...@apigee.com>
Authored: Tue Apr 14 10:00:44 2015 -0400
Committer: Dave Johnson <dm...@apigee.com>
Committed: Tue Apr 14 10:00:44 2015 -0400

----------------------------------------------------------------------
 .../rest/management/ManagementResource.java     | 75 +++++++++++++-------
 1 file changed, 48 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/27757b32/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
index 0dfd7a7..27dda53 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
@@ -32,6 +32,7 @@ import com.sun.jersey.api.client.config.ClientConfig;
 import com.sun.jersey.api.client.config.DefaultClientConfig;
 import com.sun.jersey.api.json.JSONConfiguration;
 import org.apache.commons.lang.RandomStringUtils;
+import org.apache.usergrid.exception.NotImplementedException;
 import org.apache.usergrid.management.ApplicationCreator;
 import org.apache.usergrid.management.OrganizationInfo;
 import org.apache.usergrid.management.OrganizationOwnerInfo;
@@ -471,12 +472,15 @@ public class ManagementResource extends AbstractContextResource {
      */
     @POST
     @Path( "/externaltoken" )
-    //@RequireSystemAccess TODO: should this be required
     public Response validateExternalToken(
             @Context UriInfo ui,
             Map<String, Object> json,
             @QueryParam( "callback" ) @DefaultValue( "" ) String callback )  throws Exception {
 
+        if ( StringUtils.isEmpty( properties.getProperty( USERGRID_CENTRAL_URL ))) {
+            throw new NotImplementedException( "External Token Validation Service is not configured" );
+        }
+
         Object extAccessTokenObj = json.get("ext_access_token");
         if ( extAccessTokenObj == null ) {
             throw new IllegalArgumentException("ext_access_token must be specified");
@@ -520,7 +524,6 @@ public class ManagementResource extends AbstractContextResource {
      */
     @GET
     @Path( "/externaltoken" )
-    //@RequireSystemAccess TODO: should this be required
     public Response validateExternalToken(
                                 @Context UriInfo ui,
                                 @QueryParam( "ext_access_token" ) String extAccessToken,
@@ -529,6 +532,10 @@ public class ManagementResource extends AbstractContextResource {
             throws Exception {
 
 
+        if ( StringUtils.isEmpty( properties.getProperty( USERGRID_CENTRAL_URL ))) {
+            throw new NotImplementedException( "External Token Validation Service is not configured" );
+        }
+
         if ( extAccessToken == null ) {
             throw new IllegalArgumentException("ext_access_token must be specified");
         }
@@ -537,31 +544,9 @@ public class ManagementResource extends AbstractContextResource {
             throw new IllegalArgumentException("ttl must be specified");
         }
 
-        // create URL of central Usergrid's /management/me endpoint
-
-        String externalUrl = properties.getProperty( USERGRID_CENTRAL_URL ).trim();
-        // be lenient about trailing slash
-        externalUrl = !externalUrl.endsWith( "/" ) ? externalUrl + "/" : externalUrl;
-        String me = externalUrl + "management/me?access_token=" + extAccessToken;
-
-        // use our favorite HTTP client to GET /management/me
-
-        ClientConfig clientConfig = new DefaultClientConfig();
-        clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
-        Client client = Client.create(clientConfig);
-        final JsonNode accessInfoNode;
-        try {
-            accessInfoNode = client.resource( me )
-                    .type(MediaType.APPLICATION_JSON_TYPE)
-                    .get(JsonNode.class);
-
-        } catch ( Exception e ) {
-            // user not found 404
-            String msg = "Cannot find Admin User associated with " + extAccessToken;
-            throw new EntityNotFoundException( msg, e );
-        }
+        // look up user via UG Central's /management/me endpoint.
 
-        // good. user was found in central Usergrid
+        JsonNode accessInfoNode = getMeFromUgCentral( extAccessToken );
 
         JsonNode userNode = accessInfoNode.get( "user" );
         String username = userNode.get( "username" ).getTextValue();
@@ -575,8 +560,8 @@ public class ManagementResource extends AbstractContextResource {
         // if user does not exist locally then we need to fix that
 
         final UUID userId;
-
         final OrganizationInfo organizationInfo = management.getOrganizationByName(username);
+
         if ( organizationInfo == null ) {
 
             // create local user and personal organization, activate user.
@@ -605,6 +590,42 @@ public class ManagementResource extends AbstractContextResource {
     }
 
 
+    /**
+     * Look up Admin User via UG Central's /management/me endpoint.
+     *
+     * @param extAccessToken Access token issued by UG Central of Admin User
+     * @return JsonNode representation of AccessInfo object for Admin User
+     * @throws EntityNotFoundException if access_token is not valid.
+     */
+    private JsonNode getMeFromUgCentral( String extAccessToken )  throws EntityNotFoundException {
+
+        // create URL of central Usergrid's /management/me endpoint
+
+        String externalUrl = properties.getProperty( USERGRID_CENTRAL_URL ).trim();
+        // be lenient about trailing slash
+        externalUrl = !externalUrl.endsWith( "/" ) ? externalUrl + "/" : externalUrl;
+        String me = externalUrl + "management/me?access_token=" + extAccessToken;
+
+        // use our favorite HTTP client to GET /management/me
+
+        ClientConfig clientConfig = new DefaultClientConfig();
+        clientConfig.getFeatures().put( JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
+        Client client = Client.create(clientConfig);
+        final JsonNode accessInfoNode;
+        try {
+            accessInfoNode = client.resource( me )
+                    .type( MediaType.APPLICATION_JSON_TYPE)
+                    .get(JsonNode.class);
+
+        } catch ( Exception e ) {
+            // user not found 404
+            String msg = "Cannot find Admin User associated with " + extAccessToken;
+            throw new EntityNotFoundException( msg, e );
+        }
+        return accessInfoNode;
+    }
+
+
     String errorMsg = "";
     String responseType;
     String clientId;


[6/9] incubator-usergrid git commit: Fixes from code review.

Posted by gr...@apache.org.
Fixes from code review.


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/96ef88f6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/96ef88f6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/96ef88f6

Branch: refs/heads/master
Commit: 96ef88f691ae8b73dc7918c9adc96e4410790d40
Parents: f252547
Author: Dave Johnson <dm...@apigee.com>
Authored: Thu Apr 16 09:38:30 2015 -0400
Committer: Dave Johnson <dm...@apigee.com>
Committed: Thu Apr 16 09:38:30 2015 -0400

----------------------------------------------------------------------
 .../rest/management/ManagementResource.java        | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/96ef88f6/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
index 1bae8eb..73963fe 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
@@ -201,9 +201,9 @@ public class ManagementResource extends AbstractContextResource {
                                              String callback, boolean loadAdminData ) throws Exception {
 
 
-        // if external tokens are enabled for Usegrid central authentication,
-        // then only the superuser can login via this Usergrid instance.
-        if ( externalTokensEnabled && !username.equalsIgnoreCase( superuserName )) {
+        // when external tokens (Usergrid Central SSO) are enabled only superuser can login as Admin User.
+        if ( externalTokensEnabled &&
+                superuserAllowed && !username.equalsIgnoreCase( superuserName )) {
 
             // cause an HTTP 400 response with a useful message
             throw  new IllegalArgumentException("Admin Users must login via " +
@@ -583,17 +583,16 @@ public class ManagementResource extends AbstractContextResource {
 
         // if user does not exist locally then we need to fix that
 
-        UUID userId = null;
-        final OrganizationInfo organizationInfo = management.getOrganizationByName(username);
+        UUID userId = management.getAdminUserByUsername( username ).getUuid();
 
-        if ( organizationInfo == null ) {
+        if ( userId == null ) {
 
-            // create local user and personal organization, activate user.
+            // create local user and and organizations they have on the central Usergrid instance
 
             String name     = userNode.get( "name" ).getTextValue();
             String email    = userNode.get( "email" ).getTextValue();
 
-            // set dummy password to random string that nobody can guess, in SSO setup
+            // set dummy password to random string that nobody can guess, in central SSO setup
             // admin users should never be able to login directly to this Usergrid system
             String dummyPassword = RandomStringUtils.randomAlphanumeric( 40 );
 
@@ -630,8 +629,6 @@ public class ManagementResource extends AbstractContextResource {
                 }
             }
 
-        } else {
-            userId = management.getAdminUserByUsername( username ).getUuid();
         }
 
         // store the external access_token as if it were one of our own


[4/9] incubator-usergrid git commit: When provisioning a local user for a valid external token, create all organizations listed in the user's Access Info object. Also: prevent Admin Users from logging in when external token validation is enabled.

Posted by gr...@apache.org.
When provisioning a local user for a valid external token, create all organizations listed in the user's Access Info object. Also: prevent Admin Users from logging in when external token validation is enabled.


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/9a8d5e07
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/9a8d5e07
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/9a8d5e07

Branch: refs/heads/master
Commit: 9a8d5e07822c5bd856f2aea2ec87232ad8888307
Parents: 27757b3
Author: Dave Johnson <dm...@apigee.com>
Authored: Wed Apr 15 11:24:52 2015 -0400
Committer: Dave Johnson <dm...@apigee.com>
Committed: Wed Apr 15 11:24:52 2015 -0400

----------------------------------------------------------------------
 .../main/resources/usergrid-default.properties  |  5 ++
 .../rest/management/ManagementResource.java     | 89 ++++++++++++++++----
 2 files changed, 78 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9a8d5e07/stack/config/src/main/resources/usergrid-default.properties
----------------------------------------------------------------------
diff --git a/stack/config/src/main/resources/usergrid-default.properties b/stack/config/src/main/resources/usergrid-default.properties
index cc4dda6..fe7a945 100644
--- a/stack/config/src/main/resources/usergrid-default.properties
+++ b/stack/config/src/main/resources/usergrid-default.properties
@@ -111,6 +111,11 @@ usergrid.sysadmin.login.allowed=false
 usergrid.sysadmin.approve.users=false
 usergrid.sysadmin.approve.organizations=false
 
+# Base URL of central Usergrid SSO server
+# Setting this will enable external token validation.
+# See also: https://issues.apache.org/jira/browse/USERGRID-567
+usergrid.central.url=
+
 # Where to store temporary files
 usergrid.temp.files=/tmp/usergrid
 

http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/9a8d5e07/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
index 27dda53..1bae8eb 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
@@ -18,6 +18,7 @@ package org.apache.usergrid.rest.management;
 
 
 import java.net.URLEncoder;
+import java.util.Iterator;
 import java.util.Map;
 import java.util.UUID;
 
@@ -105,8 +106,25 @@ public class ManagementResource extends AbstractContextResource {
 
     public static final String USERGRID_CENTRAL_URL = "usergrid.central.url";
 
+    private boolean superuserAllowed;
+
+    private boolean externalTokensEnabled;
+
+    private String superuserName;
+
 
     public ManagementResource() {
+
+        String superuserAllowedStr =  properties.getProperty( "usergrid.sysadmin.login.allowed" );
+
+        superuserName = properties.getProperty( "usergrid.sysadmin.login.name" );
+
+        superuserAllowed = !StringUtils.isEmpty( superuserAllowedStr )
+                && superuserAllowedStr.trim().equalsIgnoreCase( "true" );
+
+        externalTokensEnabled =
+                !StringUtils.isEmpty( properties.getProperty( USERGRID_CENTRAL_URL ));
+
         logger.info( "ManagementResource initialized" );
     }
 
@@ -181,6 +199,17 @@ public class ManagementResource extends AbstractContextResource {
     private Response getAccessTokenInternal( UriInfo ui, String authorization, String grant_type, String username,
                                              String password, String client_id, String client_secret, long ttl,
                                              String callback, boolean loadAdminData ) throws Exception {
+
+
+        // if external tokens are enabled for Usegrid central authentication,
+        // then only the superuser can login via this Usergrid instance.
+        if ( externalTokensEnabled && !username.equalsIgnoreCase( superuserName )) {
+
+            // cause an HTTP 400 response with a useful message
+            throw  new IllegalArgumentException("Admin Users must login via " +
+                properties.getProperty( USERGRID_CENTRAL_URL ));
+        }
+
         UserInfo user = null;
 
         try {
@@ -481,7 +510,7 @@ public class ManagementResource extends AbstractContextResource {
             throw new NotImplementedException( "External Token Validation Service is not configured" );
         }
 
-        Object extAccessTokenObj = json.get("ext_access_token");
+        Object extAccessTokenObj = json.get( "ext_access_token" );
         if ( extAccessTokenObj == null ) {
             throw new IllegalArgumentException("ext_access_token must be specified");
         }
@@ -505,9 +534,10 @@ public class ManagementResource extends AbstractContextResource {
     /**
      * <p>
      * Validates access token from other or "external" Usergrid system.
-     * Calls other system's /management/me endpoint to get the User associated with the access token.
-     * If user does not exist locally, then user and organization with the same name of user is created.
-     * If no user is returned from the other cluster, then this endpoint will return 401.
+     * Calls other system's /management/me endpoint to get the User
+     * associated with the access token. If user does not exist locally,
+     * then user and organizations will be created. If no user is returned
+     * from the other cluster, then this endpoint will return 401.
      * </p>
      *
      * <p> Part of Usergrid Central SSO feature.
@@ -550,29 +580,55 @@ public class ManagementResource extends AbstractContextResource {
 
         JsonNode userNode = accessInfoNode.get( "user" );
         String username = userNode.get( "username" ).getTextValue();
-        String name     = userNode.get( "name" ).getTextValue();
-        String email    = userNode.get( "email" ).getTextValue();
-
-        // set dummy password to random string that nobody can guess, in SSO setup
-        // admin users should never be able to login directly to this Usergrid system
-        String dummyPassword = RandomStringUtils.randomAlphanumeric( 40 );
 
         // if user does not exist locally then we need to fix that
 
-        final UUID userId;
+        UUID userId = null;
         final OrganizationInfo organizationInfo = management.getOrganizationByName(username);
 
         if ( organizationInfo == null ) {
 
             // create local user and personal organization, activate user.
 
-            OrganizationOwnerInfo ownerOrgInfo = management.createOwnerAndOrganization(
-                    username, username, name, email, dummyPassword, true, true );
-            userId = ownerOrgInfo.getOwner().getUuid();
+            String name     = userNode.get( "name" ).getTextValue();
+            String email    = userNode.get( "email" ).getTextValue();
+
+            // set dummy password to random string that nobody can guess, in SSO setup
+            // admin users should never be able to login directly to this Usergrid system
+            String dummyPassword = RandomStringUtils.randomAlphanumeric( 40 );
+
+            JsonNode orgsNode = userNode.get( "organizations" );
+            final Iterator<String> fieldNames = orgsNode.getFieldNames();
+
+            UserInfo userInfo = null;
+
+            // create user and any organizations that user is supposed to have
+
+            while ( fieldNames.hasNext() ) {
+
+                String orgName = fieldNames.next();
+
+                if ( userId == null ) {
 
-            management.activateOrganization( ownerOrgInfo.getOrganization() );
+                    // haven't created user yet so do that now
+                    OrganizationOwnerInfo ownerOrgInfo = management.createOwnerAndOrganization(
+                            orgName, username, name, email, dummyPassword, true, true );
 
-            applicationCreator.createSampleFor( ownerOrgInfo.getOrganization() );
+                    management.activateOrganization( ownerOrgInfo.getOrganization() ); // redundant?
+                    applicationCreator.createSampleFor( ownerOrgInfo.getOrganization() );
+
+                    userId = ownerOrgInfo.getOwner().getUuid();
+                    userInfo = ownerOrgInfo.getOwner();
+
+                } else {
+
+                    // already created user, so just create an org
+                    final OrganizationInfo organization = management.createOrganization( orgName, userInfo, true );
+
+                    management.activateOrganization( organization ); // redundant?
+                    applicationCreator.createSampleFor( organization );
+                }
+            }
 
         } else {
             userId = management.getAdminUserByUsername( username ).getUuid();
@@ -602,6 +658,7 @@ public class ManagementResource extends AbstractContextResource {
         // create URL of central Usergrid's /management/me endpoint
 
         String externalUrl = properties.getProperty( USERGRID_CENTRAL_URL ).trim();
+
         // be lenient about trailing slash
         externalUrl = !externalUrl.endsWith( "/" ) ? externalUrl + "/" : externalUrl;
         String me = externalUrl + "management/me?access_token=" + extAccessToken;


[2/9] incubator-usergrid git commit: Fixes to Usergrid Central SSO feature from manual testing.

Posted by gr...@apache.org.
Fixes to Usergrid Central SSO feature from manual testing.


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/c15fcc8c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/c15fcc8c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/c15fcc8c

Branch: refs/heads/master
Commit: c15fcc8cd04637c2cb45e390035520751295b77d
Parents: 098355f
Author: Dave Johnson <dm...@apigee.com>
Authored: Mon Apr 13 16:47:39 2015 -0400
Committer: Dave Johnson <dm...@apigee.com>
Committed: Mon Apr 13 16:47:39 2015 -0400

----------------------------------------------------------------------
 .../rest/management/ManagementResource.java     | 20 ++++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-usergrid/blob/c15fcc8c/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
index c1c0be5..0dfd7a7 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
@@ -32,14 +32,14 @@ import com.sun.jersey.api.client.config.ClientConfig;
 import com.sun.jersey.api.client.config.DefaultClientConfig;
 import com.sun.jersey.api.json.JSONConfiguration;
 import org.apache.commons.lang.RandomStringUtils;
+import org.apache.usergrid.management.ApplicationCreator;
 import org.apache.usergrid.management.OrganizationInfo;
 import org.apache.usergrid.management.OrganizationOwnerInfo;
 import org.apache.usergrid.persistence.exceptions.EntityNotFoundException;
-import org.apache.usergrid.rest.security.annotations.RequireSystemAccess;
-import org.apache.usergrid.utils.UUIDUtils;
 import org.codehaus.jackson.JsonNode;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Scope;
 import org.springframework.stereotype.Component;
 
@@ -99,6 +99,9 @@ public class ManagementResource extends AbstractContextResource {
 
     private static final Logger logger = LoggerFactory.getLogger( ManagementResource.class );
 
+    @Autowired
+    private ApplicationCreator applicationCreator;
+
     public static final String USERGRID_CENTRAL_URL = "usergrid.central.url";
 
 
@@ -561,7 +564,6 @@ public class ManagementResource extends AbstractContextResource {
         // good. user was found in central Usergrid
 
         JsonNode userNode = accessInfoNode.get( "user" );
-        UUID userId     = UUIDUtils.tryExtractUUID( userNode.get( "uuid" ).getTextValue() );
         String username = userNode.get( "username" ).getTextValue();
         String name     = userNode.get( "name" ).getTextValue();
         String email    = userNode.get( "email" ).getTextValue();
@@ -572,13 +574,23 @@ public class ManagementResource extends AbstractContextResource {
 
         // if user does not exist locally then we need to fix that
 
+        final UUID userId;
+
         final OrganizationInfo organizationInfo = management.getOrganizationByName(username);
         if ( organizationInfo == null ) {
 
             // create local user and personal organization, activate user.
 
             OrganizationOwnerInfo ownerOrgInfo = management.createOwnerAndOrganization(
-                    username, username, name, email, dummyPassword, true, true);
+                    username, username, name, email, dummyPassword, true, true );
+            userId = ownerOrgInfo.getOwner().getUuid();
+
+            management.activateOrganization( ownerOrgInfo.getOrganization() );
+
+            applicationCreator.createSampleFor( ownerOrgInfo.getOrganization() );
+
+        } else {
+            userId = management.getAdminUserByUsername( username ).getUuid();
         }
 
         // store the external access_token as if it were one of our own


[8/9] incubator-usergrid git commit: Merge branch 'USERGRID-567-central-sso'

Posted by gr...@apache.org.
Merge branch 'USERGRID-567-central-sso'


Project: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/commit/6ae492e3
Tree: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/tree/6ae492e3
Diff: http://git-wip-us.apache.org/repos/asf/incubator-usergrid/diff/6ae492e3

Branch: refs/heads/master
Commit: 6ae492e37d9142e73469da250cf5d976eed17bbe
Parents: 7aabf68 96ef88f
Author: Dave Johnson <dm...@apigee.com>
Authored: Thu Apr 16 09:41:29 2015 -0400
Committer: Dave Johnson <dm...@apigee.com>
Committed: Thu Apr 16 09:41:29 2015 -0400

----------------------------------------------------------------------
 .../rest/management/ManagementResource.java        | 17 +++++++----------
 1 file changed, 7 insertions(+), 10 deletions(-)
----------------------------------------------------------------------