Enable access to OAuth 2.0 tokens by user ID and app ID

Edge for Private Cloud v. 4.16.05

This document describes how to enable retrieval and revocation of OAuth 2.0 access tokens by end user ID, app ID, or both.

App IDs are automatically added to an OAuth access token. Therefore, after you use the procedure below to enable token access for an organization, you can access tokens by app ID.

To retrieve and revoke OAuth 2.0 access tokens by end user ID, an end user ID must be present in the access token. The procedure below describes how add an end user ID to an existing token or to new tokens.

By default, when Edge generates an OAuth 2.0 access token, the token has the format:

{
  "issued_at" : "1421847736581",
  "application_name" : "a68d01f8-b15c-4be3-b800-ceae8c456f5a",
  "scope" : "READ",
  "status" : "approved",
  "api_product_list" : "[PremiumWeatherAPI]",
  "expires_in" : "3599",
  "developer.email" : "tesla@weathersample.com",
  "organization_id" : "0",
  "token_type" : "BearerToken",
  "client_id" : "k3nJyFJIA3p62DWOkLO6OJNi87GYXFmP",
  "access_token" : "7S22UqXGJDTuUADGzJzjXzXSaGJL",
  "organization_name" : "myorg",
  "refresh_token_expires_in" : "0",
  "refresh_count" : "0"
}

Note the following:

  • The application_name field contains the UUID of the app associated with the token. If you enable retrieval and revocation of OAuth 2.0 access tokens by app ID, this is the app ID you use.
  • The access_token field contains the OAuth 2.0 access token value.

To enable retrieval and revocation of OAuth 2.0 access tokens by end user ID, configure the OAuth 2.0 policy to include the user ID in the token, as described in the procedure below.

The end user ID is the string that Edge uses as the developer ID, not the developer's email address. You can determine the developer's ID from the developer's email address by using the Get Developer API call.

After you configure Edge to include the end user ID in the token, it is included as the app_enduser field, as shown below:

{
  "issued_at" : "1421847736581",
  "application_name" : "a68d01f8-b15c-4be3-b800-ceae8c456f5a",
  "scope" : "READ",
  "app_enduser" : "6ZG094fgnjNf02EK",
  "status" : "approved",
  "api_product_list" : "[PremiumWeatherAPI]",
  "expires_in" : "3599",
  "developer.email" : "tesla@weathersample.com",
  "organization_id" : "0",
  "token_type" : "BearerToken",
  "client_id" : "k3nJyFJIA3p62DWOkLO6OJNi87GYXFmP",
  "access_token" : "7S22UqXGJDTuUADGzJzjXzXSaGJL",
  "organization_name" : "myorg",
  "refresh_token_expires_in" : "0",
  "refresh_count" : "0"
}

APIs to retrieve and revoke OAuth 2.0 access tokens by user ID and app ID

Use the following APIs to access OAuth tokens by user ID, app ID, or both:

Procedure for enabling token access

Use the following procedure to enable retrieval and revocation of OAuth 2.0 access tokens by end user ID and app ID.

Step 1: Enable token access support for an organization

You must enable token access for each organization separately. Call the PUT API below for each organization on which you want to enable the retrieval and revocation of OAuth 2.0 access tokens by end user ID or app ID.

The user making the following call must be in the role orgadmin or opsadmin for the organization. Replace the values in {curly braces} with your org-specific values:

> curl -H "Content-type:text/xml" -X POST \
  https://<ms-ip>:8080/v1/organizations/{org_name} \
  -d '<Organization name="{org_name}">
      <Properties>
        <Property name="features.isOAuthRevokeEnabled">true</Property>
        <Property name="features.isOAuth2TokenSearchEnabled">true</Property>
      </Properties>
    </Organization>' \ 
  -u {userEmail}:{mypassword}

Step 2: Set permissions for opsadmin role in the organization

Only the orgadmin and opsadmin roles in an organization should be given permissions to retrieve (HTTP GET) and revoke (HTTP PUT) OAuth 2.0 tokens based on user ID or app ID. To control access, set get and put permissions on the /oauth2 resource for an organization. That resource has a URL in the form:

https://<ms-ip>:8080/v1/organizations/{org_name}/oauth2

The orgadmin role should already have the necessary permissions. For the opsadmin role for the /oauth2 resource, the permissions should look like this:

<ResourcePermission path="/oauth2">
    <Permissions>
        <Permission>get</Permission>
        <Permission>put</Permission>
    </Permissions>
</ResourcePermission>

You can use the Get Permission for a Single Resource API call to see which roles have permissions for the /oauth2 resource.

Based on the response, you can use the Add Permissions for Resource to a Role and Delete Permission for Resource API calls to make any necessary adjustments to the /oauth2 resource permissions.

Use the following cURL command to give the opsadmin role get and put permissions for the /oauth2 resource. Replace the values in {curly braces} with your org-specific values:

> curl -X POST -H 'Content-type:application/xml' \
  http://<ms-ip>:8080/v1/organizations/{org}/userroles/opsadmin/permissions \
  -d '<ResourcePermission path="/oauth2">
      <Permissions>
        <Permission>get</Permission>
        <Permission>put</Permission>
      </Permissions>
    </ResourcePermission>' \
  -u {USEREMAIL}:{PWD} 

Use the following cURL command to revoke get and put permissions for the /oauth2 resource from roles other than orgadmin and opsadmin. Replace the values in {curly braces} with your org-specific values:

> curl -X DELETE -H 'Content-type:application/xml' \
  http://<msip>:8080/v1/organizations/{org-name}/userroles/{roles}/permissions \
  -d '<ResourcePermission path="/oauth2">
      <Permissions></Permissions>
    </ResourcePermission>' \
   -u {USEREMAIL}:{PWD} 

Step 3: Set the oauth_max_search_limit property

Ensure that the conf_keymanagement_oauth_max_search_limit property in /<inst_dir>/apigee/customer/application/management-server.properties file is set to 100:

conf_keymanagement_oauth_max_search_limit = 100

If this file does not exist, create it.

This property sets the page size used when fetching tokens. Apigee recommends a value of 100, but you can set it as you see fit.

On a new installation, the property should be already set to 100. If you have to change the value of this property, restart the Management Server and Message Processor by using the commands:

> /<inst_rt>/apigee/apigee-service/bin/apigee-service edge-management-server restart
> /<inst_rt>/apigee/apigee-service/bin/apigee-service edge-message-processor restart

Step 4: Configure the OAuth 2.0 policy that generates tokens to include end user ID

Configure the OAuth 2.0 policy used to generate access tokens to include the end user ID in the token. By including end user IDs in the access token, you can retrieve and revoke tokens by ID.

To configure the policy to include an end user ID in an access token, the request that creates the access token must include the end user ID and you must specify the input variable that contains the end user ID.

The OAuth 2.0 policy below, named GenerateAccessTokenClient, generates an OAuth 2.0 access token. Note the addition of the <AppEndUser> tag in bold that specifies the variable containing the end user ID:

<OAuthV2 async="false" continueOnError="false" enabled="true" name="GenerateAccessTokenClient">
    <DisplayName>OAuth 2.0.0 1</DisplayName>
    <ExternalAuthorization>false</ExternalAuthorization>
    <Operation>GenerateAccessToken</Operation>
    <SupportedGrantTypes>
         <GrantType>client_credentials</GrantType>
    </SupportedGrantTypes>
    <GenerateResponse enabled="true"/>
    <GrantType>request.queryparam.grant_type</GrantType> 
    <AppEndUser>request.header.appuserID</AppEndUser> 
    <ExpiresIn>960000</ExpiresIn>
</OAuthV2>

You can then use the following cURL command to generate the OAuth 2.0 access token, passing the user ID as the appuserID header:

> curl -H "appuserID:6ZG094fgnjNf02EK" \
https://myorg-test.apigee.net/oauth/client_credential/accesstoken?grant_type=client_credentials \
  -X POST \
  -d 'client_id=k3nJyFJIA3p62TKIkLO6OJNXFmP&client_secret=gk5K5lIp943AY4'

In this example, the appuserID is passed as a request header. You can pass information as part of a request in many ways. For example, as an alternative, you can:

  • Use a form parameter variable: request.formparam.appuserID
  • Use a flow variable providing the end user ID