You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@usergrid.apache.org by mr...@apache.org on 2016/07/14 20:26:24 UTC

[15/16] usergrid git commit: 1. added /management/tokendetails?token=&provider=&keyurl 2. POST /management/token -> with grant_type : password and super user —> should create a UG token and return. 3. GET /management/me?access_token= —> with super user t

1. added /management/tokendetails?token=&provider=&keyurl
2. POST /management/token -> with grant_type : password and super user \u2014> should create a UG token and return.
3. GET /management/me?access_token= \u2014> with super user token -> should return superuser info.
4. Inprogress --> superuser be able to add an org without providing all the administer details.


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

Branch: refs/heads/apigee-sso-provider
Commit: fad65a8dff462c0521ceb46585b1bc5f969a926a
Parents: 6e093bc
Author: Ayesha Dastagiri <ay...@gmail.com>
Authored: Thu Jul 14 00:48:56 2016 -0700
Committer: Ayesha Dastagiri <ay...@gmail.com>
Committed: Thu Jul 14 00:48:56 2016 -0700

----------------------------------------------------------------------
 .../main/resources/usergrid-default.properties  |  6 +-
 .../rest/management/ManagementResource.java     | 62 ++++++++++++++++++--
 .../organizations/OrganizationsResource.java    | 11 +++-
 .../security/shiro/filters/SecurityFilter.java  |  2 +-
 .../cassandra/ManagementServiceImpl.java        |  6 --
 ...alSSOProviderAdminUserNotFoundException.java | 17 ++++++
 .../security/sso/ApigeeSSO2Provider.java        | 41 ++++++++++---
 .../security/sso/ExternalSSOProvider.java       |  4 ++
 .../security/sso/SSOProviderFactory.java        | 31 +++++++---
 .../security/sso/UsergridExternalProvider.java  | 14 ++++-
 10 files changed, 159 insertions(+), 35 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/usergrid/blob/fad65a8d/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 fe739b9..371b251 100644
--- a/stack/config/src/main/resources/usergrid-default.properties
+++ b/stack/config/src/main/resources/usergrid-default.properties
@@ -19,7 +19,7 @@
 #                       USERGRID DEPLOYMENT PROPERTIES
 ###############################################################################
 #
-# Contained below are properties used to configure the Usergrid application.
+# Contained below are propertiefs used to configure the Usergrid application.
 # Some of the core settings depend on the specific Usergrid deployment architecture.
 # For more info, check the docs at:
 #     <http://usergrid.readthedocs.org/en/two-dot-o-instructions/index.html>
@@ -496,7 +496,6 @@ usergrid.central.read.timeout=10000
 usergrid.external.sso.enabled=false
 usergrid.external.sso.provider=
 usergrid.external.sso.url=
-usergrid.external.sso.publicKeyUrl=
 
 ###############################  Usergrid Assets  #############################
 #
@@ -541,6 +540,9 @@ usergrid.sysadmin.login.email=super@usergrid.com
 usergrid.sysadmin.login.password=test
 usergrid.sysadmin.login.allowed=true
 
+#enable if superuser can create an org without any user associated with it.
+usergrid.superuser.addorg.enable=true
+
 # if usergrid.sysadmin.login.allowed=true, only allows sysadmin login if request is localhost
 # if usergrid.sysadmin.login.allowed=false, this property has no effect
 usergrid.sysadmin.localhost.only=false

http://git-wip-us.apache.org/repos/asf/usergrid/blob/fad65a8d/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 c94987a..77569d6 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
@@ -39,6 +39,8 @@ import org.apache.usergrid.security.shiro.principals.PrincipalIdentifier;
 import org.apache.usergrid.security.shiro.utils.SubjectUtils;
 import org.apache.usergrid.security.sso.ExternalSSOProvider;
 import org.apache.usergrid.security.sso.SSOProviderFactory;
+import org.apache.usergrid.security.tokens.cassandra.TokenServiceImpl;
+import org.apache.usergrid.utils.JsonUtils;
 import org.glassfish.jersey.server.mvc.Viewable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -57,8 +59,8 @@ import java.util.Map;
 import static javax.servlet.http.HttpServletResponse.*;
 import static javax.ws.rs.core.MediaType.*;
 import static org.apache.commons.lang.StringUtils.isNotBlank;
-import static org.apache.usergrid.security.tokens.cassandra.TokenServiceImpl.USERGRID_EXTERNAL_SSO_ENABLED;
 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.JsonUtils.mapToJsonString;
 import static org.apache.usergrid.utils.StringUtils.stringOrSubstringAfterFirst;
 import static org.apache.usergrid.utils.StringUtils.stringOrSubstringBeforeFirst;
@@ -191,15 +193,12 @@ public class ManagementResource extends AbstractContextResource {
         }
 
 
-        if(ssoEnabled){
-
+        if(ssoEnabled && !user.getUsername().equals(properties.getProperty(USERGRID_SYSADMIN_LOGIN_NAME))){
             ExternalSSOProvider provider = ssoProviderFactory.getProvider();
-
             tokenTtl =
                 Long.valueOf(provider.getDecodedTokenDetails(access_token).get("expiry")) - System.currentTimeMillis()/1000;
 
         }else{
-
             tokenTtl = tokens.getTokenInfo(access_token).getDuration();
         }
 
@@ -215,6 +214,51 @@ public class ManagementResource extends AbstractContextResource {
 
     }
 
+    /**
+     * Get token details. Specially used for external tokens.
+     * @param ui
+     * @param authorization
+     * @param token
+     * @param provider
+     * @param keyUrl
+     * @param callback
+     * @return the json with all the token details. Error message if the external SSO provider is not supported or any other error.
+     * @throws Exception
+     */
+    @GET
+    @Path( "tokendetails" )
+    public Response getTokenDetails( @Context UriInfo ui, @HeaderParam( "Authorization" ) String authorization,
+                                    @QueryParam( "token" ) String token,
+                                    @QueryParam( "provider" )  @DefaultValue( "" ) String provider,
+                                    @QueryParam( "keyurl" )  @DefaultValue( "" ) String keyUrl,
+                                    @QueryParam( "callback" ) @DefaultValue( "" ) String callback
+                                    ) throws Exception {
+
+        ExternalSSOProvider externalprovider = null;
+        Map<String, Object> jwt = null;
+
+        if (! provider.isEmpty()) {
+            //check if its in one of the external provider list.
+            if (!ssoProviderFactory.getProvidersList().contains(StringUtils.upperCase(provider))) {
+                throw new IllegalArgumentException("Unsupported provider.");
+            } else {
+                //get the specific provider.
+                externalprovider = ssoProviderFactory.getSpecificProvider(provider);
+            }
+        }
+        else{   //if the provider is not specified get the default provider enabled in the properties.
+            externalprovider = ssoProviderFactory.getProvider();
+        }
+
+        if(keyUrl.isEmpty()) {
+            keyUrl =  externalprovider.getExternalSSOUrl();
+        }
+
+        jwt = externalprovider.getAllTokenDetails(token, keyUrl);
+
+        return Response.status( SC_OK ).type( jsonMediaType( callback ) )
+            .entity( wrapWithCallback(JsonUtils.mapToJsonString(jwt) , callback ) ).build();
+    }
 
     @GET
     @Path( "token" )
@@ -336,6 +380,12 @@ public class ManagementResource extends AbstractContextResource {
                                .entity( wrapWithCallback( response.getBody(), callback ) ).build();
             }
 
+            //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() && !user.getUsername().equals(properties.getProperty(USERGRID_SYSADMIN_LOGIN_NAME)) ){
+                throw new RuntimeException("SSO Integration is enabled, Admin users must login via provider: "+
+                    properties.getProperty(TokenServiceImpl.USERGRID_EXTERNAL_PROVIDER));
+            }
+
             String token = management.getAccessTokenForAdminUser( user.getUuid(), ttl );
             Long passwordChanged = management.getLastAdminPasswordChange( user.getUuid() );
 
@@ -520,6 +570,8 @@ public class ManagementResource extends AbstractContextResource {
                 else {
                     redirect_uri += "&";
                 }
+
+                //todo: check if sso enabled.
                 redirect_uri += "code=" + management.getAccessTokenForAdminUser( user.getUuid(), 0 );
                 if ( isNotBlank( state ) ) {
                     redirect_uri += "&state=" + URLEncoder.encode( state, "UTF-8" );

http://git-wip-us.apache.org/repos/asf/usergrid/blob/fad65a8d/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationsResource.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationsResource.java b/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationsResource.java
index 476e315..eb70486 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationsResource.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/management/organizations/OrganizationsResource.java
@@ -28,6 +28,7 @@ import org.apache.usergrid.rest.AbstractContextResource;
 import org.apache.usergrid.rest.ApiResponse;
 import org.apache.usergrid.rest.RootResource;
 import org.apache.usergrid.rest.security.annotations.RequireSystemAccess;
+import org.apache.usergrid.security.shiro.utils.SubjectUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -55,6 +56,8 @@ public class OrganizationsResource extends AbstractContextResource {
 
     public static final String ORGANIZATION_PROPERTIES = "properties";
     public static final String ORGANIZATION_CONFIGURATION = "configuration";
+    public static final String USERGRID_SYSADMIN_LOGIN_NAME = "usergrid.sysadmin.login.name";
+    public static final String USERGRID_SUPERUSER_ADDORG_ENABLED ="usergrid.superuser.addorg.enable";
 
     @Autowired
     private ApplicationCreator applicationCreator;
@@ -185,9 +188,13 @@ public class OrganizationsResource extends AbstractContextResource {
                                              String email, String password, Map<String, Object> userProperties,
                                              Map<String, Object> orgProperties, String callback ) throws Exception {
 
+        String tokenUserName = SubjectUtils.getUser().getUsername();
+
         if ( tokens.isExternalSSOProviderEnabled() ) {
-            throw new IllegalArgumentException( "Organization / Admin Users must be created via " +
-                    properties.getProperty( USERGRID_EXTERNAL_PROVIDER_URL ) );
+            if(!tokenUserName.equals(properties.getProperty(USERGRID_SYSADMIN_LOGIN_NAME))) {
+                throw new IllegalArgumentException("Organization / Admin Users must be created via " +
+                    properties.getProperty(USERGRID_EXTERNAL_PROVIDER_URL));
+            }
         }
 
         Preconditions

http://git-wip-us.apache.org/repos/asf/usergrid/blob/fad65a8d/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/SecurityFilter.java
----------------------------------------------------------------------
diff --git a/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/SecurityFilter.java b/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/SecurityFilter.java
index 1c06aed..817464f 100644
--- a/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/SecurityFilter.java
+++ b/stack/rest/src/main/java/org/apache/usergrid/rest/security/shiro/filters/SecurityFilter.java
@@ -137,7 +137,7 @@ public abstract class SecurityFilter implements ContainerRequestFilter {
 
         // if this is a CORS Pre-Flight request, we can skip the security check
         // OPTIONS requests do not have access into Usergrid data, Jersey default handles these requests
-        if( request.getMethod().equalsIgnoreCase("options")){
+        if( request.getMethod().equalsIgnoreCase("options") ){
             return true;
         }
 

http://git-wip-us.apache.org/repos/asf/usergrid/blob/fad65a8d/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 e812b75..90eb4c9 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
@@ -68,7 +68,6 @@ import org.apache.usergrid.security.shiro.utils.SubjectUtils;
 import org.apache.usergrid.security.tokens.TokenCategory;
 import org.apache.usergrid.security.tokens.TokenInfo;
 import org.apache.usergrid.security.tokens.TokenService;
-import org.apache.usergrid.security.tokens.cassandra.TokenServiceImpl;
 import org.apache.usergrid.security.tokens.exceptions.TokenException;
 import org.apache.usergrid.services.*;
 import org.apache.usergrid.utils.*;
@@ -1530,11 +1529,6 @@ public class ManagementServiceImpl implements ManagementService {
     @Override
     public String getAccessTokenForAdminUser( UUID userId, long duration ) throws Exception {
 
-        if( properties.getProperty(TokenServiceImpl.USERGRID_EXTERNAL_SSO_ENABLED).equalsIgnoreCase("true")){
-            throw new RuntimeException("SSO Integration is enabled, Admin users must login via provider: "+
-                properties.getProperty(TokenServiceImpl.USERGRID_EXTERNAL_PROVIDER));
-        }
-
         return getTokenForPrincipal( ACCESS, null, smf.getManagementAppId(), ADMIN_USER, userId, duration );
     }
 

http://git-wip-us.apache.org/repos/asf/usergrid/blob/fad65a8d/stack/services/src/main/java/org/apache/usergrid/management/exceptions/ExternalSSOProviderAdminUserNotFoundException.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/management/exceptions/ExternalSSOProviderAdminUserNotFoundException.java b/stack/services/src/main/java/org/apache/usergrid/management/exceptions/ExternalSSOProviderAdminUserNotFoundException.java
index 67f1b1e..dabe9b9 100644
--- a/stack/services/src/main/java/org/apache/usergrid/management/exceptions/ExternalSSOProviderAdminUserNotFoundException.java
+++ b/stack/services/src/main/java/org/apache/usergrid/management/exceptions/ExternalSSOProviderAdminUserNotFoundException.java
@@ -1,3 +1,20 @@
+/*
+ * 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.management.exceptions;
 
 /**

http://git-wip-us.apache.org/repos/asf/usergrid/blob/fad65a8d/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 953da55..61a1601 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
@@ -26,6 +26,7 @@ import org.apache.usergrid.security.AuthPrincipalType;
 import org.apache.usergrid.security.tokens.TokenInfo;
 import org.apache.usergrid.security.tokens.exceptions.BadTokenException;
 import org.apache.usergrid.security.tokens.exceptions.ExpiredTokenException;
+import org.apache.usergrid.utils.JsonUtils;
 import org.apache.usergrid.utils.UUIDUtils;
 import org.glassfish.jersey.client.ClientConfig;
 import org.glassfish.jersey.jackson.JacksonFeature;
@@ -36,7 +37,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 import javax.ws.rs.client.Client;
 import javax.ws.rs.client.ClientBuilder;
 import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
 import java.security.PublicKey;
+import java.security.spec.InvalidKeySpecException;
 import java.security.spec.X509EncodedKeySpec;
 import java.util.HashMap;
 import java.util.Map;
@@ -64,12 +67,16 @@ public class ApigeeSSO2Provider implements ExternalSSOProvider {
         client = ClientBuilder.newClient(clientConfig);
     }
 
-    private String getPublicKey() {
+    public String getPublicKey(String keyUrl) {
 
-        final String keyUrl = properties.getProperty(USERGRID_EXTERNAL_PUBLICKEY_URL);
         if(keyUrl != null && !keyUrl.isEmpty()) {
-            Map<String, Object> publicKey = client.target(properties.getProperty(USERGRID_EXTERNAL_PUBLICKEY_URL)).request().get(Map.class);
-            return publicKey.get(RESPONSE_PUBLICKEY_VALUE).toString().split("----\n")[1].split("\n---")[0];
+            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];
+            }
+            catch(Exception e){
+                throw new IllegalArgumentException("error getting public key");
+            }
         }
 
         return null;
@@ -121,18 +128,28 @@ public class ApigeeSSO2Provider implements ExternalSSOProvider {
 
     }
 
+    @Override
+    public Map<String, Object> getAllTokenDetails(String token, String keyUrl) throws Exception {
+        Jws<Claims> claims = getClaimsForKeyUrl(token,getPublicKey(keyUrl));
+        return JsonUtils.toJsonMap(claims.getBody());
 
-    private Jws<Claims> getClaims(String token) throws Exception{
+    }
 
+    @Override
+    public String getExternalSSOUrl() {
+        return properties.getProperty(USERGRID_EXTERNAL_PUBLICKEY_URL);
+    }
+
+    public Jws<Claims> getClaimsForKeyUrl(String token, String ssoPublicKey) throws NoSuchAlgorithmException, InvalidKeySpecException, BadTokenException {
         Jws<Claims> claims = null;
 
-        if(publicKey == null){
+        if(ssoPublicKey == null){
             throw new IllegalArgumentException("Public key must be provided with Apigee " +
                 "token in order to verify signature.");
         }
 
 
-        byte[] publicBytes = decodeBase64(publicKey);
+        byte[] publicBytes = decodeBase64(ssoPublicKey);
         X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicBytes);
         KeyFactory keyFactory = KeyFactory.getInstance("RSA");
         PublicKey pubKey = keyFactory.generatePublic(keySpec);
@@ -141,7 +158,7 @@ public class ApigeeSSO2Provider implements ExternalSSOProvider {
             claims = Jwts.parser().setSigningKey(pubKey).parseClaimsJws(token);
         } catch (SignatureException se) {
             if(logger.isDebugEnabled()) {
-                logger.debug("Signature was invalid for Apigee JWT: {} and key: {}", token, publicKey);
+                logger.debug("Signature was invalid for Apigee JWT: {} and key: {}", token, ssoPublicKey);
             }
             throw new BadTokenException("Invalid Apigee SSO token signature");
         } catch (MalformedJwtException me){
@@ -160,6 +177,12 @@ public class ApigeeSSO2Provider implements ExternalSSOProvider {
         return claims;
     }
 
+    public Jws<Claims> getClaims(String token) throws Exception{
+
+        return getClaimsForKeyUrl(token,publicKey);
+
+    }
+
     private void validateClaims (final Jws<Claims> claims) throws ExpiredTokenException {
 
         final Claims body = claims.getBody();
@@ -185,6 +208,6 @@ public class ApigeeSSO2Provider implements ExternalSSOProvider {
     @Autowired
     public void setProperties(Properties properties) {
         this.properties = properties;
-        this.publicKey = getPublicKey();
+        this.publicKey = getPublicKey(getExternalSSOUrl());
     }
 }

http://git-wip-us.apache.org/repos/asf/usergrid/blob/fad65a8d/stack/services/src/main/java/org/apache/usergrid/security/sso/ExternalSSOProvider.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/security/sso/ExternalSSOProvider.java b/stack/services/src/main/java/org/apache/usergrid/security/sso/ExternalSSOProvider.java
index 180a675..ebd7ec5 100644
--- a/stack/services/src/main/java/org/apache/usergrid/security/sso/ExternalSSOProvider.java
+++ b/stack/services/src/main/java/org/apache/usergrid/security/sso/ExternalSSOProvider.java
@@ -35,4 +35,8 @@ public interface ExternalSSOProvider {
     /** Decode the token, if supported, and return any information encoded with the token */
     Map<String, String> getDecodedTokenDetails(String token) throws Exception;
 
+    Map<String, Object> getAllTokenDetails(String token, String keyUrl) throws Exception;
+
+    String getExternalSSOUrl() throws Exception;
+
 }

http://git-wip-us.apache.org/repos/asf/usergrid/blob/fad65a8d/stack/services/src/main/java/org/apache/usergrid/security/sso/SSOProviderFactory.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/security/sso/SSOProviderFactory.java b/stack/services/src/main/java/org/apache/usergrid/security/sso/SSOProviderFactory.java
index a3016c8..2b9755e 100644
--- a/stack/services/src/main/java/org/apache/usergrid/security/sso/SSOProviderFactory.java
+++ b/stack/services/src/main/java/org/apache/usergrid/security/sso/SSOProviderFactory.java
@@ -21,7 +21,10 @@ import org.apache.usergrid.persistence.EntityManagerFactory;
 import org.apache.usergrid.security.tokens.cassandra.TokenServiceImpl;
 import org.springframework.beans.factory.annotation.Autowired;
 
+import java.util.List;
 import java.util.Properties;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * Created by russo on 6/24/16.
@@ -38,17 +41,21 @@ public class SSOProviderFactory {
 
     public ExternalSSOProvider getProvider(){
 
-        final Provider configuredProvider;
+        return getSpecificProvider(properties.getProperty(TokenServiceImpl.USERGRID_EXTERNAL_PROVIDER));
+
+    }
+
+    public ExternalSSOProvider getSpecificProvider(String providerName){
+
+        final Provider specifiedProvider ;
         try{
-            configuredProvider =
-                Provider.valueOf(properties.getProperty(TokenServiceImpl.USERGRID_EXTERNAL_PROVIDER).toUpperCase());
-        }catch (IllegalArgumentException e){
-            throw new RuntimeException("Property usergrid.external.sso.provider must " +
-                "be configured when external SSO is enabled");
+            specifiedProvider = Provider.valueOf(providerName.toUpperCase());
+        }
+        catch(IllegalArgumentException e){
+            throw new IllegalArgumentException("Unsupported provider");
         }
 
-        switch (configuredProvider){
-
+        switch (specifiedProvider){
             case APIGEE:
                 return ((CpEntityManagerFactory)emf).getApplicationContext().getBean( ApigeeSSO2Provider.class );
             case USERGRID:
@@ -56,9 +63,9 @@ public class SSOProviderFactory {
             default:
                 throw new RuntimeException("Unknown SSO provider");
         }
-
     }
 
+
     @Autowired
     public void setEntityManagerFactory( EntityManagerFactory emf ) {
         this.emf = emf;
@@ -69,4 +76,10 @@ public class SSOProviderFactory {
     public void setProperties(Properties properties) {
         this.properties = properties;
     }
+
+    public List<String> getProvidersList() {
+        return Stream.of(Provider.values())
+            .map(Enum::name)
+            .collect(Collectors.toList());
+    }
 }

http://git-wip-us.apache.org/repos/asf/usergrid/blob/fad65a8d/stack/services/src/main/java/org/apache/usergrid/security/sso/UsergridExternalProvider.java
----------------------------------------------------------------------
diff --git a/stack/services/src/main/java/org/apache/usergrid/security/sso/UsergridExternalProvider.java b/stack/services/src/main/java/org/apache/usergrid/security/sso/UsergridExternalProvider.java
index a2e5fb2..0cfe2d0 100644
--- a/stack/services/src/main/java/org/apache/usergrid/security/sso/UsergridExternalProvider.java
+++ b/stack/services/src/main/java/org/apache/usergrid/security/sso/UsergridExternalProvider.java
@@ -48,7 +48,7 @@ public class UsergridExternalProvider implements ExternalSSOProvider {
     private static final String SSO_PROCESSING_TIME = "sso.processing_time";
     private static final String SSO_TOKENS_REJECTED = "sso.tokens_rejected";
     private static final String SSO_TOKENS_VALIDATED = "sso.tokens_validated";
-    public static final String USERGRID_CENTRAL_URL = "usergrid.external.sso.publicKeyUrl";
+    public static final String USERGRID_CENTRAL_URL = "usergrid.external.sso.url";
     public static final String CENTRAL_CONNECTION_POOL_SIZE = "usergrid.central.connection.pool.size";
     public static final String CENTRAL_CONNECTION_TIMEOUT = "usergrid.central.connection.timeout";
     public static final String CENTRAL_READ_TIMEOUT = "usergrid.central.read.timeout";
@@ -91,6 +91,18 @@ public class UsergridExternalProvider implements ExternalSSOProvider {
     }
 
     @Override
+    public Map<String, Object> getAllTokenDetails(String token, String keyUrl) throws Exception {
+        throw new UnsupportedOperationException("Returning all token details info not supported from external Usergrid SSO tokens");
+
+    }
+
+    @Override
+    public String getExternalSSOUrl() {
+        return properties.getProperty(USERGRID_CENTRAL_URL);
+    }
+
+
+    @Override
     public UserInfo validateAndReturnUserInfo(String token, long ttl) throws Exception {
         if (token == null) {
             throw new IllegalArgumentException("ext_access_token must be specified");