You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@usergrid.apache.org by snoopdave <gi...@git.apache.org> on 2015/04/14 16:02:35 UTC

[GitHub] incubator-usergrid pull request: Validate External Token (UG Centr...

GitHub user snoopdave opened a pull request:

    https://github.com/apache/incubator-usergrid/pull/221

    Validate External Token (UG Central SSO)

    FOR REVIEW ONLY -- NOT READY FOR MERGE
    
    New endpoint that allows Usergrid to use access tokens issued by a central Usergrid SSO service.
    
    https://issues.apache.org/jira/browse/USERGRID-567
    


You can merge this pull request into a Git repository by running:

    $ git pull https://github.com/snoopdave/incubator-usergrid master

Alternatively you can review and apply these changes as the patch at:

    https://github.com/apache/incubator-usergrid/pull/221.patch

To close this pull request, make a commit to your master/trunk branch
with (at least) the following in the commit message:

    This closes #221
    
----
commit 098355f8521a7528fe0fa44e9ce959f7c4c603d8
Author: Dave Johnson <dm...@apigee.com>
Date:   2015-04-13T15:24:53Z

    First cut of Usergrid Central SSO feature, with tests.

commit c15fcc8cd04637c2cb45e390035520751295b77d
Author: Dave Johnson <dm...@apigee.com>
Date:   2015-04-13T20:47:39Z

    Fixes to Usergrid Central SSO feature from manual testing.

commit 27757b3292c97af81ca8e38a93a0c949811ee362
Author: Dave Johnson <dm...@apigee.com>
Date:   2015-04-14T14:00:44Z

    small refactor.

----


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-usergrid pull request: Validate External Token (UG Centr...

Posted by snoopdave <gi...@git.apache.org>.
Github user snoopdave commented on a diff in the pull request:

    https://github.com/apache/incubator-usergrid/pull/221#discussion_r28328971
  
    --- Diff: stack/services/src/main/java/org/apache/usergrid/security/shiro/Realm.java ---
    @@ -235,8 +235,16 @@ protected AuthorizationInfo doGetAuthorizationInfo( PrincipalCollection principa
     
             for ( PrincipalIdentifier principal : principals.byType( PrincipalIdentifier.class ) ) {
     
    +            // TODO: refactor so that this whole instanceof mess can be replaced with this:
    --- End diff --
    
    Only some notes about a possible refactor here.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-usergrid pull request: Validate External Token (UG Centr...

Posted by snoopdave <gi...@git.apache.org>.
Github user snoopdave commented on a diff in the pull request:

    https://github.com/apache/incubator-usergrid/pull/221#discussion_r28356858
  
    --- Diff: stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java ---
    @@ -441,6 +451,181 @@ public Viewable handleAuthorizeForm( @Context UriInfo ui, @FormParam( "response_
         }
     
     
    +    /**
    +     * <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" )
    +    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");
    +        }
    +        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" )
    +    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 ( 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");
    +        }
    +
    +        if ( ttl == -1 ) {
    +            throw new IllegalArgumentException("ttl must be specified");
    +        }
    +
    +        // 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();
    +        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;
    +        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();
    +
    +            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
    +        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();
    +    }
    +
    +
    +    /**
    +     * 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 ) {
    --- End diff --
    
    can we expose more specific error information, and throw different exceptions, here based on what comes back from the request?


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-usergrid pull request: Validate External Token (UG Centr...

Posted by snoopdave <gi...@git.apache.org>.
Github user snoopdave commented on a diff in the pull request:

    https://github.com/apache/incubator-usergrid/pull/221#discussion_r28346513
  
    --- Diff: stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java ---
    @@ -441,6 +451,181 @@ public Viewable handleAuthorizeForm( @Context UriInfo ui, @FormParam( "response_
         }
     
     
    +    /**
    +     * <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" )
    +    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");
    +        }
    +        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" )
    +    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 ( 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");
    +        }
    +
    +        if ( ttl == -1 ) {
    +            throw new IllegalArgumentException("ttl must be specified");
    +        }
    +
    +        // 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();
    +        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;
    +        final OrganizationInfo organizationInfo = management.getOrganizationByName(username);
    +
    +        if ( organizationInfo == null ) {
    +
    +            // create local user and personal organization, activate user.
    +
    +            OrganizationOwnerInfo ownerOrgInfo = management.createOwnerAndOrganization(
    --- End diff --
    
    Instead of creating an organization with the same name as the username, we should get the list of organizations from the accessInfoNode and create each of those listed.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-usergrid pull request: Validate External Token (UG Centr...

Posted by snoopdave <gi...@git.apache.org>.
Github user snoopdave commented on a diff in the pull request:

    https://github.com/apache/incubator-usergrid/pull/221#discussion_r28329002
  
    --- Diff: stack/rest/src/test/java/org/apache/usergrid/rest/test/PropertiesResourceIT.java ---
    @@ -51,25 +48,31 @@ public void testBasicOperation() {
     
             // 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" )
    --- End diff --
    
    Only formatting changes in this file.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-usergrid pull request: Validate External Token (UG Centr...

Posted by snoopdave <gi...@git.apache.org>.
Github user snoopdave commented on the pull request:

    https://github.com/apache/incubator-usergrid/pull/221#issuecomment-93042705
  
    We will also need a configuration variable that will turn-off new Admin User registrations and logins on "UG Dev" systems when the Usergrid Central SSO feature is enabled.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-usergrid pull request: Validate External Token (UG Centr...

Posted by snoopdave <gi...@git.apache.org>.
Github user snoopdave closed the pull request at:

    https://github.com/apache/incubator-usergrid/pull/221


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-usergrid pull request: Validate External Token (UG Centr...

Posted by snoopdave <gi...@git.apache.org>.
Github user snoopdave commented on a diff in the pull request:

    https://github.com/apache/incubator-usergrid/pull/221#discussion_r28328923
  
    --- Diff: stack/rest/src/test/java/org/apache/usergrid/rest/test/PropertiesResourceIT.java ---
    @@ -36,9 +36,6 @@
     public class PropertiesResourceIT extends AbstractRestIT {
         static final Logger logger = LoggerFactory.getLogger( PropertiesResourceIT.class );
     
    -    @Autowired
    -    protected ServiceManagerFactory smf;
    -
     
    --- End diff --
    
    Only formatting changes in this file.


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---

[GitHub] incubator-usergrid pull request: Validate External Token (UG Centr...

Posted by snoopdave <gi...@git.apache.org>.
Github user snoopdave commented on a diff in the pull request:

    https://github.com/apache/incubator-usergrid/pull/221#discussion_r28356699
  
    --- Diff: stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java ---
    @@ -441,6 +451,181 @@ public Viewable handleAuthorizeForm( @Context UriInfo ui, @FormParam( "response_
         }
     
     
    +    /**
    +     * <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" )
    +    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");
    +        }
    +        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" )
    +    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 ( 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");
    +        }
    +
    +        if ( ttl == -1 ) {
    +            throw new IllegalArgumentException("ttl must be specified");
    +        }
    +
    +        // look up user via UG Central's /management/me endpoint.
    +
    +        JsonNode accessInfoNode = getMeFromUgCentral( extAccessToken );
    --- End diff --
    
    Should add some metrics collection here via MetricsFactory 


---
If your project is set up for it, you can reply to this email and have your
reply appear on GitHub as well. If your project does not have this feature
enabled and wishes so, or if the feature is enabled but not working, please
contact infrastructure at infrastructure@apache.org or file a JIRA ticket
with INFRA.
---