Cleanup. Add tests.

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

Branch: refs/heads/apigee-sso-provider
Commit: 6d88bcfdccc458b382b16483b5d3048df699262c
Parents: 5fcad44
Author: Ayesha Dastagiri <ayesha.am...@gmail.com>
Authored: Tue Jul 26 11:49:42 2016 -0700
Committer: Ayesha Dastagiri <ayesha.am...@gmail.com>
Committed: Tue Jul 26 11:49:42 2016 -0700

----------------------------------------------------------------------
 stack/rest/pom.xml                              |   8 +
 .../rest/management/ManagementResource.java     |  13 +-
 .../rest/management/ExternalSSOEnabledIT.java   | 175 +++++++++++++++++++
 .../rest/management/ManagementResourceIT.java   |  24 ++-
 .../security/sso/ApigeeSSO2Provider.java        |  28 +--
 .../tokens/cassandra/TokenServiceImpl.java      |   3 +
 6 files changed, 233 insertions(+), 18 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/usergrid/blob/6d88bcfd/stack/rest/pom.xml
----------------------------------------------------------------------
diff --git a/stack/rest/pom.xml b/stack/rest/pom.xml
index 89d14b4..580814c 100644
--- a/stack/rest/pom.xml
+++ b/stack/rest/pom.xml
@@ -306,6 +306,14 @@
             <version>${jackson-2-version}</version>
         </dependency>
 
+        <!-- for mocking the Apigee SSO Service -->
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <version>${mockito.version}</version>
+            <scope>test</scope>
+        </dependency>
+
         <!-- databinding; ObjectMapper, JsonNode and related classes are here 
-->
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>

http://git-wip-us.apache.org/repos/asf/usergrid/blob/6d88bcfd/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 7217c49..c5d7c77 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
@@ -385,9 +385,14 @@ public class ManagementResource extends 
AbstractContextResource {
 
             //moved the check for sso enabled form MangementServiceImpl since 
was unable to get the current user there to check if its super user.
             if( tokens.isExternalSSOProviderEnabled()
-                && !userServiceAdmin(user.getUsername()) ){
-                throw new RuntimeException("SSO Integration is enabled, Admin 
users must login via provider: "+
-                    
properties.getProperty(TokenServiceImpl.USERGRID_EXTERNAL_PROVIDER));
+                && !userServiceAdmin(username) ){
+                OAuthResponse response =
+                    OAuthResponse.errorResponse( SC_BAD_REQUEST ).setError( 
OAuthError.TokenResponse.INVALID_GRANT )
+                        .setErrorDescription( "SSO Integration is enabled, 
Admin users must login via provider: "+
+                            
properties.getProperty(TokenServiceImpl.USERGRID_EXTERNAL_PROVIDER) 
).buildJSONMessage();
+                return Response.status( response.getResponseStatus() ).type( 
jsonMediaType( callback ) )
+                    .entity( wrapWithCallback( response.getBody(), callback ) 
).build();
+
             }
 
             String token = management.getAccessTokenForAdminUser( 
user.getUuid(), ttl );
@@ -616,7 +621,7 @@ public class ManagementResource extends 
AbstractContextResource {
 
         if ( tokens.isExternalSSOProviderEnabled() ) {
             // when external tokens enabled then only superuser can obtain an 
access token
-            if ( userServiceAdmin(username)) {
+            if ( !userServiceAdmin(username)) {
                 // this guy is not the superuser
                 throw new IllegalArgumentException( "Admin Users must login 
via " +
                         properties.getProperty( USERGRID_EXTERNAL_PROVIDER_URL 
) );

http://git-wip-us.apache.org/repos/asf/usergrid/blob/6d88bcfd/stack/rest/src/test/java/org/apache/usergrid/rest/management/ExternalSSOEnabledIT.java
----------------------------------------------------------------------
diff --git 
a/stack/rest/src/test/java/org/apache/usergrid/rest/management/ExternalSSOEnabledIT.java
 
b/stack/rest/src/test/java/org/apache/usergrid/rest/management/ExternalSSOEnabledIT.java
new file mode 100644
index 0000000..75fa0b5
--- /dev/null
+++ 
b/stack/rest/src/test/java/org/apache/usergrid/rest/management/ExternalSSOEnabledIT.java
@@ -0,0 +1,175 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.usergrid.rest.management;
+
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+import io.jsonwebtoken.impl.crypto.RsaProvider;
+import org.apache.commons.collections4.map.HashedMap;
+import org.apache.usergrid.cassandra.SpringResource;
+import org.apache.usergrid.persistence.index.utils.UUIDUtils;
+import org.apache.usergrid.rest.test.resource.AbstractRestIT;
+import org.apache.usergrid.rest.test.resource.RestClient;
+import org.apache.usergrid.rest.test.resource.model.ApiResponse;
+import org.apache.usergrid.rest.test.resource.model.Entity;
+import org.apache.usergrid.security.sso.ApigeeSSO2Provider;
+import org.codehaus.jackson.JsonNode;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.security.*;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.*;
+
+/**
+ * Created by ayeshadastagiri on 7/20/16.
+ */
+@Ignore("Need to figure out a way to set the public key for Mock server.")
+public class ExternalSSOEnabledIT extends AbstractRestIT {
+
+    Key key;
+    PublicKey publicKey;
+    PrivateKey privateKey;
+    String compactJws;
+    String username = "SSOadminuser" + UUIDUtils.newTimeUUID();
+    ApigeeSSO2Provider apigeeSSO2ProviderTest;
+    //SSO2 implementation
+    public static final String USERGRID_EXTERNAL_SSO_ENABLED = 
"usergrid.external.sso.enabled";
+    public static final String USERGRID_EXTERNAL_PROVIDER =    
"usergrid.external.sso.provider";
+
+    public ExternalSSOEnabledIT() throws Exception {
+
+    }
+
+    @Before
+    public void setup() throws NoSuchAlgorithmException {
+        generateKey();
+    }
+
+    private void generateKey() {
+        KeyPair kp = RsaProvider.generateKeyPair(1024);
+        publicKey = kp.getPublic();
+        privateKey = kp.getPrivate();
+    }
+
+    private String genrateToken(){
+        Map<String, Object> claims = new HashedMap<String, Object>();
+        claims.put("jti","c7df0339-3847-450b-a925-628ef237953a");
+        claims.put("sub","b6d62259-217b-4e96-8f49-e00c366e4fed");
+        claims.put("scope","size = 5");
+        claims.put("client_id", "edgecli");
+        claims.put("azp","edgecli");
+        claims.put("grant_type" ,"password");
+        claims.put("user_id","b6d62259-217b-4e96-8f49-e00c366e4fed");
+        claims.put( "origin","usergrid");
+        claims.put("user_name","AyeshaSSOUser");
+        claims.put("email", "adastagiri+ssotest...@apigee.com");
+        claims.put( "rev_sig","dfe5d0d3");
+        claims.put("iat","1466550862");
+        claims.put("exp", System.currentTimeMillis() + 1000);
+        claims.put("iss", "https://login.apigee.com/oauth/token";);
+        claims.put( "zid","uaa");
+        claims.put( "aud"," size = 6");
+        claims.put("grant_type","password");
+
+        String jwt = 
Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.RS256, 
privateKey).compact();
+        return jwt;
+
+    }
+
+    @Test
+    public void SuperUserTestsFor() throws NoSuchAlgorithmException {
+
+        // create a admin user.
+        RestClient restClient = clientSetup.getRestClient();
+
+        //Create adminUser values
+        Entity adminUserPayload = new Entity();
+        adminUserPayload.put("username", "TestUser");
+        adminUserPayload.put("name", username);
+        adminUserPayload.put("email", "adastagiri+ssotest...@apigee.com");
+        adminUserPayload.put("password", username);
+
+        //create adminUser
+        ApiResponse adminUserEntityResponse = 
management().orgs().org(clientSetup.getOrganizationName()).users().post(ApiResponse.class,
 adminUserPayload);
+
+        Entity adminUserResponse = new Entity(adminUserEntityResponse);
+        //verify that the response contains the correct data
+        assertNotNull(adminUserResponse);
+        assertEquals("TestUser", adminUserResponse.get("username"));
+
+        Map<String, String> props = new HashMap<String, String>();
+
+        props.put( USERGRID_EXTERNAL_SSO_ENABLED, "true" );
+        props.put( USERGRID_EXTERNAL_PROVIDER, "apigee" );
+        pathResource( "testproperties" ).post( props );
+
+        // /management/me --> superuser and query params --> Generate a super 
usesr token.
+        Map<String, Object> loginInfo = new HashMap<String, Object>() {{
+            put( "username", "superuser" );
+            put( "password", "superpassword" );
+            put( "grant_type", "password" );
+        }};
+        ApiResponse postResponse2 = pathResource( "management/token" ).post( 
false,ApiResponse.class,loginInfo );
+        assertTrue(postResponse2.getAccessToken() != null );
+
+
+        // /orgs  create an org with superuser credentials.
+        // /management/me --> superuser and query params --> Generate a super 
usesr token.
+        Map<String, Object> orgDetails = new HashMap<String, Object>() {{
+            put( "email", "adastagiri+ssotest...@apigee.com" );
+            put( "name", "testuser" );
+            put( "organization", username );
+        }};
+
+        
context().getToken().put("access_token",postResponse2.getAccessToken());
+        postResponse2 = pathResource( "management/orgs" ).post( 
true,ApiResponse.class,orgDetails);
+        assertTrue(postResponse2.getData() != null);
+
+        postResponse2 = 
pathResource("management/orgs").get(ApiResponse.class,true);
+        assertTrue(postResponse2 != null);
+
+
+        compactJws = genrateToken();
+
+        
SpringResource.getInstance().getAppContext().getBean(ApigeeSSO2Provider.class).setPublicKey(
 publicKey  );
+        context().getToken().put("access_token",compactJws);
+        // /management/me --> admin user and jwt token. Return the user 
information and "token" should have jwt token.
+        JsonNode responseToken = management().me().get(JsonNode.class,true);
+        assertTrue(responseToken.get("access_token") != null);
+
+
+        // /management/me --> admin and query params --> Generate a super 
usesr token.
+        Map<String, Object> loginInfo1 = new HashMap<String, Object>() {{
+            put( "username", "TestUser" );
+            put( "password", username );
+            put( "grant_type", "password" );
+        }};
+
+        // /managment/token -> adminusername and password --> should fail.
+        ApiResponse postResponse1 = 
pathResource("management/token").post(false, ApiResponse.class,loginInfo1);
+//        fail( "SSO Integration is enabled, Admin users must login via 
provider: "+ USERGRID_EXTERNAL_PROVIDER_URL);
+
+
+
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/usergrid/blob/6d88bcfd/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 1fe4f01..21c62ba 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
@@ -38,6 +38,7 @@ import java.io.IOException;
 import java.util.*;
 
 import static 
org.apache.usergrid.security.tokens.cassandra.TokenServiceImpl.USERGRID_EXTERNAL_PROVIDER_URL;
+import static 
org.apache.usergrid.security.tokens.cassandra.TokenServiceImpl.USERGRID_EXTERNAL_SSO_ENABLED;
 import static org.apache.usergrid.utils.MapUtils.hashMap;
 import static org.junit.Assert.*;
 
@@ -671,6 +672,7 @@ public class ManagementResourceIT extends AbstractRestIT {
 
         String suToken = clientSetup.getSuperuserToken().getAccessToken();
         Map<String, String> props = new HashMap<String, String>();
+        props.put(USERGRID_EXTERNAL_SSO_ENABLED, "true");
         props.put( USERGRID_EXTERNAL_PROVIDER_URL, 
getBaseURI().toURL().toExternalForm() );
         pathResource( "testproperties" ).post( props );
 
@@ -685,7 +687,7 @@ public class ManagementResourceIT extends AbstractRestIT {
                     put( "grant_type", "password" );
                 }};
                 ApiResponse postResponse = pathResource( "management/token" 
).post( false, ApiResponse.class, loginInfo );
-                fail( "Login as Admin User must fail when validate external 
tokens is enabled" );
+                fail( "SSO Integration is enabled, Admin users must login via 
provider: "+ USERGRID_EXTERNAL_PROVIDER_URL);
 
             } catch (ClientErrorException actual) {
                 assertEquals( 400, actual.getResponse().getStatus() );
@@ -709,11 +711,31 @@ public class ManagementResourceIT extends AbstractRestIT {
             String accessToken = postResponse2.getAccessToken();
             assertNotNull( accessToken );
 
+            //Superuser : GET -> get tokenInfo with access_token
+            ApiResponse getResponse3 = 
pathResource("management/me").get(ApiResponse.class,new QueryParameters()
+                .addParam("grant_type", "password").addParam("password", 
"superpassword")
+                .addParam("username", "superuser"),false);
+
+            assertNotNull(getResponse3.getAccessToken());
+
+            //Superuser : POST -> Add org using super user credentials.
+            Map<String, Object> orgAdminUserInfo = new HashMap<String, 
Object>() {{
+                put( "username", username+"test" );
+                put("password","RandomPassword");
+                put("email",username+"@gmail.com");
+                put( "organization", username+"RandomOrgName" );
+            }};
+            ApiResponse postResponse4 = pathResource("management/orgs")
+                .post(false,orgAdminUserInfo,new 
QueryParameters().addParam("access_token",getResponse3.getAccessToken()));
+            assertNotNull(postResponse4.getData());
+
+
         } finally {
 
             // turn off validate external tokens by un-setting the 
usergrid.central.url
 
             props.put( USERGRID_EXTERNAL_PROVIDER_URL, "" );
+            props.put(USERGRID_EXTERNAL_SSO_ENABLED, "");
             pathResource( "testproperties" ).post( props );
         }
     }

http://git-wip-us.apache.org/repos/asf/usergrid/blob/6d88bcfd/stack/services/src/main/java/org/apache/usergrid/security/sso/ApigeeSSO2Provider.java
----------------------------------------------------------------------
diff --git 
a/stack/services/src/main/java/org/apache/usergrid/security/sso/ApigeeSSO2Provider.java
 
b/stack/services/src/main/java/org/apache/usergrid/security/sso/ApigeeSSO2Provider.java
index 61a1601..d48495d 100644
--- 
a/stack/services/src/main/java/org/apache/usergrid/security/sso/ApigeeSSO2Provider.java
+++ 
b/stack/services/src/main/java/org/apache/usergrid/security/sso/ApigeeSSO2Provider.java
@@ -57,7 +57,7 @@ public class ApigeeSSO2Provider implements 
ExternalSSOProvider {
     protected Properties properties;
     protected ManagementService management;
     protected Client client;
-    protected String publicKey;
+    protected PublicKey publicKey;
 
     public static final String USERGRID_EXTERNAL_PUBLICKEY_URL = 
"usergrid.external.sso.url";
 
@@ -67,12 +67,17 @@ public class ApigeeSSO2Provider implements 
ExternalSSOProvider {
         client = ClientBuilder.newClient(clientConfig);
     }
 
-    public String getPublicKey(String keyUrl) {
+    public PublicKey getPublicKey(String keyUrl) {
 
         if(keyUrl != null && !keyUrl.isEmpty()) {
             try {
                 Map<String, Object> publicKey = 
client.target(keyUrl).request().get(Map.class);
-                return 
publicKey.get(RESPONSE_PUBLICKEY_VALUE).toString().split("----\n")[1].split("\n---")[0];
+                String ssoPublicKey = 
publicKey.get(RESPONSE_PUBLICKEY_VALUE).toString().split("----\n")[1].split("\n---")[0];
+                byte[] publicBytes = decodeBase64(ssoPublicKey);
+                X509EncodedKeySpec keySpec = new 
X509EncodedKeySpec(publicBytes);
+                KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+                PublicKey pubKey = keyFactory.generatePublic(keySpec);
+                return pubKey;
             }
             catch(Exception e){
                 throw new IllegalArgumentException("error getting public key");
@@ -140,7 +145,7 @@ public class ApigeeSSO2Provider implements 
ExternalSSOProvider {
         return properties.getProperty(USERGRID_EXTERNAL_PUBLICKEY_URL);
     }
 
-    public Jws<Claims> getClaimsForKeyUrl(String token, String ssoPublicKey) 
throws NoSuchAlgorithmException, InvalidKeySpecException, BadTokenException {
+    public Jws<Claims> getClaimsForKeyUrl(String token, PublicKey 
ssoPublicKey) throws NoSuchAlgorithmException, InvalidKeySpecException, 
BadTokenException {
         Jws<Claims> claims = null;
 
         if(ssoPublicKey == null){
@@ -148,14 +153,8 @@ public class ApigeeSSO2Provider implements 
ExternalSSOProvider {
                 "token in order to verify signature.");
         }
 
-
-        byte[] publicBytes = decodeBase64(ssoPublicKey);
-        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
-        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
-        PublicKey pubKey = keyFactory.generatePublic(keySpec);
-
         try {
-            claims = Jwts.parser().setSigningKey(pubKey).parseClaimsJws(token);
+            claims = 
Jwts.parser().setSigningKey(ssoPublicKey).parseClaimsJws(token);
         } catch (SignatureException se) {
             if(logger.isDebugEnabled()) {
                 logger.debug("Signature was invalid for Apigee JWT: {} and 
key: {}", token, ssoPublicKey);
@@ -196,10 +195,13 @@ public class ApigeeSSO2Provider implements 
ExternalSSOProvider {
             throw new ExpiredTokenException(String.format("Token expired %d 
millisecons ago.", expirationDelta ));
         }
 
-
     }
 
 
+    public void setPublicKey( PublicKey publicKeyArg){
+        this.publicKey = publicKeyArg;
+    }
+
     @Autowired
     public void setManagement(ManagementService management) {
         this.management = management;
@@ -208,6 +210,6 @@ public class ApigeeSSO2Provider implements 
ExternalSSOProvider {
     @Autowired
     public void setProperties(Properties properties) {
         this.properties = properties;
-        this.publicKey = getPublicKey(getExternalSSOUrl());
+        this.publicKey =  getPublicKey(getExternalSSOUrl());
     }
 }

http://git-wip-us.apache.org/repos/asf/usergrid/blob/6d88bcfd/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 62d454a..46ea7fe 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
@@ -328,6 +328,9 @@ public class TokenServiceImpl implements TokenService {
         try{
             uuid = getUUIDForToken( token );
         }
+        catch (ExpiredTokenException expiredTokenException){
+            throw new 
ExpiredTokenException(expiredTokenException.getMessage());
+        }
         catch(Exception e){
 
             // If the token doesn't parse as a Usergrid token, see if an 
external provider other than Usergrid is

Reply via email to