[
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)