[ 
https://issues.apache.org/jira/browse/USERGRID-567?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14498192#comment-14498192
 ] 

ASF GitHub Bot commented on USERGRID-567:
-----------------------------------------

Github user snoopdave commented on a diff in the pull request:

    https://github.com/apache/incubator-usergrid/pull/224#discussion_r28521613
  
    --- Diff: 
stack/rest/src/main/java/org/apache/usergrid/rest/management/ManagementResource.java
 ---
    @@ -441,6 +464,229 @@ public Viewable handleAuthorizeForm( @Context UriInfo 
ui, @FormParam( "response_
         }
     
     
    +    /**
    +     * <p>
    +     * Allows call to validateExternalToken() (see below) with a POST of a 
JSON object.
    +     * </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 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.
    +     * 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");
    +        }
    +        AccessInfo accessInfo = null;
    +
    +        try {
    +            // 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();
    +
    +            // if user does not exist locally then we need to fix that
    +
    +            UserInfo userInfo = management.getAdminUserByUsername( 
username );
    +            UUID userId = userInfo == null ? null : userInfo.getUuid();
    +
    +            if ( userId == null ) {
    +
    +                // 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();
    +                String dummyPassword = 
RandomStringUtils.randomAlphanumeric( 40 );
    +
    +                JsonNode orgsNode = userNode.get( "organizations" );
    +                final Iterator<String> fieldNames = 
orgsNode.getFieldNames();
    +
    +                // create user and any organizations that user is supposed 
to have
    +
    +                while ( fieldNames.hasNext() ) {
    +
    +                    String orgName = fieldNames.next();
    +
    +                    if ( userId == null ) {
    +
    +                        // 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() );
    +
    +                        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 );
    +                    }
    +                }
    +
    +            }
    +
    +            // 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 );
    +
    +        } catch (Exception e) {
    +            logger.debug("Error validating external token", e);
    +            throw e;
    +        }
    +
    +        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 ) {
    +            // user not found 404
    +            String msg = "Cannot find Admin User associated with " + 
extAccessToken;
    +            throw new EntityNotFoundException( msg, e );
    +        }
    +        return accessInfoNode;
    +    }
    +
    +
    +    /**
    --- End diff --
    
    I moved the "superuser-only login when external token validation enabled" 
logic in the below new method:


> Validate External Token for Usergrid Central SSO
> ------------------------------------------------
>
>                 Key: USERGRID-567
>                 URL: https://issues.apache.org/jira/browse/USERGRID-567
>             Project: Usergrid
>          Issue Type: Story
>            Reporter: David Johnson
>            Assignee: David Johnson
>
> The requirement is to have multiple Usergrid systems, each with its own 
> Cassandra cluster, be able to authenticate Admin Users with one central 
> Usergrid system -- giving Admin Users Single-Sign-On (SSO) across all of 
> those systems.
> We can do this by adding just one new end-point to Usergrid.
> This Google Doc explains a complete design for "Usergrid Central SSO":
> https://docs.google.com/document/d/12kXgaYcB6L9JoTyRGn0ZHEMg3vL1LJDqvtnltIBDa1Y/edit?usp=sharing
> The design is based on earlier work by Ed Anuff and Nate McCall.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to