Was this helpful?

The previous topic Secure APIs with API keys demonstrates how to configure simple API key validation. In this topic, you enhance API key-based security by configuring OAuth client credentials to provide authorization for APIs.

OAuth is an authorization protocol. The OAuth specification describes ways that apps can retrieve access tokens. 'Access tokens' have been compared to 'valet keys'. A valet key is a car key that only unlocks doors and starts the car. A valet key cannot be used to open the trunk or the glove compartment. An access token can, for example, provide an app with the ability to access an end user's account to read a checking account balance, but not to issue an electronic funds transfer.

Another benefit of OAuth access tokens is that they can be long-lived, or easily refreshed. This enables apps to access data on behalf of end users repeatedly, without requiring the end user to login each time. They can also be revoked by the end user or the provider whenever necessary, providing an extra level of accountability.

OAuth defines different ways of creating access tokens that apps can use to accesss protected APIs. The various mechanisms for distributing access tokens are referred to as 'grant types'. In this topic, you configure the most basic grant type defined by the OAuth specification: 'client credentials'.

Client credential grant type

The client credentials grant type is so named because OAuth access tokens are generated in exchange for 'client credentials'. Client credentials consist of a consumer key and secret pair. These credentials are sometimes called API key and secret. The two terms are interchangeable and refer to the same thing.

Therefore, it is relatively simple to 'step up' from API key validation to the client credentials grant type. You can use the key and secret generated for your app in Provision API products, developers and apps to retrieve access tokens from the endpoint you configure in this topic.

The full specification for the client credentials grant can be found in the OAuth 2.0 Specification.

OAuth is an authorization protocol. As such, it defines ways that API providers can enforce control over the capabilities that apps are permitted access. The OAuth specification describes ways that apps can get access tokens. An 'access token' has been described as a 'valet key'. A 'valet key' is a car key that only enables a driver to unlock doors and to start the car. A valet key cannot be used to open the trunk or the glove compartment.

For example, an access token can provide an app with the ability to access an end user's checking account to read a checking account balance. OAuth can be used to limit the app's access such that it cannot also issue an electronic funds transfer.

OAuth access tokens can be long-lived or easily refreshed. This enables apps to access data on behalf of end users repeatedly, without requiring the end user to login each time. Access tokens can also be revoked by the end user or the provider whenever necessary, providing an additional level of control.

OAuth defines several different ways in which apps can request access tokens. The mechanisms for distributing access tokens are called 'grant types'. In this topic, you configure the most basic grant type defined by the OAuth specification: 'client credentials'.

Client credential grant type

The client credentials grant type defines a flow in which access tokens are distributed in exchange for 'client credentials'. Client credentials consist of a consumer key and secret pair. (These credentials are sometimes called API key and secret. The two terms are interchangeable and refer to the same credentials.) In other words the client credentials grant type makes it easy for apps to obtain access tokens using common consumer key and secret pairs.

Therefore, it is relatively simple to 'step up' from API key validation to the client credentials grant type. You can use the consumer key and secret generated for your app in Provision API products, developers and apps to retrieve access tokens from the endpoint you configure in this topic.

The full specification for the client credentials grant can be found in the OAuth 2.0 Specification.

Setting up OAuth client credentials is a two-step procedure:

  1. Configure a token endpoint
  2. Apply policies to protected resources

Configure a Token Endpoint

A token endpoint distributes access tokens to apps that present valid client credential. "Valid credentials" consist of a consumer key and secret pair. The token endpoint verifies that the consumer key and secret are approved and have not been revoked.

To set up a token endpoint, configure a policy of type OAuthV2 that specifies the GenerateAccessToken operation.

This policy configures the behavior of the token endpoint, which will distribute OAuth 2.0 access tokens to apps that present valid credentials. The policy is configured in a file called GenerateAccessToken.xmlwith the following content:

<OAuthV2 name="GenerateAccessToken">
  <Operation>GenerateAccessToken</Operation>
  <ExpiresIn>3600000</ExpiresIn>
  <SupportedGrantTypes>
    <GrantType>client_credentials</GrantType>
  </SupportedGrantTypes>
    <GrantType>request.queryparam.grant_type</GrantType>
  <GenerateResponse/>
</OAuthV2>

Policy settings

Name Description Default Required?
OAuthV2The policy type
name The name of the policy, which is referenced in the API proxy Endpoint configuration. N/A Yes
Operation The operation to be executed by the OAuthV2 policy. The OAUthV2 policy type be configured to enforce several OAuthV2 operations By specifying GenerateAccessToken, you configure the policy to perform the generation of access tokens for apps. N/A Yes
ExpiresIn Time in milliseconds for which access tokens generated by this token endpoint will be valid. N/A Yes
SupportedGrantTypes Defines the grant types that this token endpoint supports. A token endpoint can be configured to more than one grant type. In this case, you can simply configure this setting for client_credentials. N/A Yes
GrantType Specifies the location in the request message where the app should indicate the desired grant type. The location can be set to HTTP header, query parameter, or form parameter. N/A Yes
GenerateResponse When present in the configuration, this element indicates that the policy defines an endpoint, and that no further processing of the request message should take place. The policy itself generates a response and returns it to the requesting client app. N/A Yes

Apply policies to protected resources

ValidateOAuth policy of type OAuthV2

Once access tokens are issued to apps, the apps can in turn use the access tokens to make calls to 'protected resources'. You can protect an API resource by applying an OAuthV2 policy that defines the VerifyAccessToken operation.

<OAuthV2 name="ValidateOAuth"> 
  <Operation>VerifyAccessToken</Operation> 
</OAuthV2>

Policy settings

Name Description Default Required?
OAuthV2The policy type
name The name of the policy, which is referenced in the API proxy Endpoint configuration. N/A Yes
Operation The operation to be executed by the OAuthV2 policy. By specifying VerifyAccessToken, you configure the policy to check requests for access tokens, and to verify that the access token is valid, has not expired, and is approved to consume the designated API resources. (To make this check, the policy checks the requested resource against API product(s) for the consumer key has been approved.) N/A Yes

Attaching policies to the ProxyEndpoint

You have now configured two policies. One policy defines a token endpoint. The other policy defines a protected resource. Now you need to attach the policies as processing Steps to appropriate Flows in the API proxy configuration.

An OAuth configuration requires at least two conditional Flows to be configured, one for the token endpoint and another for the protected resource(s). Each Flow defines a URI path. One path defines the URI used by apps to obtain access tokens. The other URI(s) define the resources that you need to protect.

These URIs and policy attachments can be defined in the API proxy, or in different API proxies. For example, you may wish to consolidate OAuth-related policies in a single, dedicated API proxy that only serves as a token distribution endpoint. For simplicity, here you include both the token endpoint URI and the protected resource URI in the same API proxy configuration.

A token endpoint is simply a URI fragment to which an OAuthV2 policy attached. Such a condition can be defined as follows:

<Condition>proxy.pathsuffix MatchesPath "/accesstoken"</Condition>

By configuring this Condition, you create a URI that apps can use to retrieve access tokens.

To create a Flow that executes the OAuthV2 policy, and thus acts as a token endpoint, create a Flow like this:

<Flow name="TokenEndpoint">
   <Condition>proxy.pathsuffix MatchesPath "/accesstoken"</Condition>
   <Request>
     <Step><Name>GenerateAccessToken</Name></Step>
   </Request>
 </Flow>

The full path to the token endpoint is the virtual host, the ProxyEndpoint base path, and a 'suffix', this case, /accesstoken.

{virtual_host}/{base_path}/accesstoken

Therefore, to request an access token, an app makes a request to, for example:

http://{org_name}-test.apigee.net/weather/accesstoken

You now have a URL that you can share with app developers building OAuth-enabled apps.

To enforce access tokens for authorization to protected resources, create a named Flow with no condition. Since no condition is specified, the Flow will execute for every request that does not suffix /accesstoken. In other words, it acts as a 'default' Flow. Apps first call /accesstoken, and once they possess an access token, they call the URL for the protected resource.

<Flow name="Authorize">
  <Request>
    <Step><Name>ValidateOAuth</Name></Step>
  </Request>
</Flow>

In the simpleProxy, configure the ProxyEndpoint named default /proxies/default.xml as follows:

<ProxyEndpoint name="default">
  <Flows>
    <Flow name="TokenEndpoint">
    <!-- Apps call this URI to present credentials and obtain an access token -->
      <Condition>proxy.pathsuffix MatchesPath "/accesstoken"</Condition>
      <Request>
        <Step><Name>GenerateAccessToken</Name></Step>
      </Request>
    </Flow>
    <Flow name="Authorize">
    <!-- Validates access tokens before authorizing access -->
      <Request>
        <Step><Name>ValidateOAuth</Name></Step>
      </Request>
    </Flow>
  </Flows>
  <HTTPProxyConnection>
    <BasePath>/weather</BasePath>
    <VirtualHost>default</VirtualHost>
  </HTTPProxyConnection>
  <RouteRule name="default">
    <TargetEndpoint>default</TargetEndpoint>
  </RouteRule>
</ProxyEndpoint>

Importing and deploying

The deploy tool is used for importing and deploying changes, by substituting a valid username and password for myname:mypass, and an Apigee organization for org_name.

python tools/deploy.py -n weatherapi -u myname:mypass -o {org_name} -e test -p / -d simpleProxy
Writing simpleProxy/apiproxy/weatherapi.xml to apiproxy/weatherapi.xml
Writing simpleProxy/apiproxy/policies/GenerateAccessToken.xml to apiproxy/policies/GenerateAccessToken.xml
Writing simpleProxy/apiproxy/policies/ValidateOAuth.xml to apiproxy/policies/ValidateOAuth.xml
Writing simpleProxy/apiproxy/proxies/default.xml to apiproxy/proxies/default.xml
Writing simpleProxy/apiproxy/targets/default.xml to apiproxy/targets/default.xml
Imported new proxy version 7
Undeploying revision 6 in same environment and path:
Environment: test
  Revision: 7 BasePath = /
  State: deployed

Obtaining a access token and invoking a protected resource

An app obtains an access token by making a request to the token endpoint with valid credentials. Since you configured the client credentials grant type, an app can obtain an access token using only valid consumer key and secret pair.

First, use the Platform API to retrieve the consumer key and secret for the app created in Provision API products, developers and apps:

$ curl -u myname:mypass https://api.enterprise.apigee.com/v1/o/{myorg}/developers/{developer_email}/apps/{app_name}

For example, an app profile for weatherapp

{
  "accessType" : "read",
  "appFamily" : "default",
  "attributes" : [ {
    "name" : "Platform",
    "value" : "iOS"
  } ],
  "callbackUrl" : "login.weatherapp.com",
  "createdAt" : 1349462499114,
  "createdBy" : "ntesla@theramin.com",
  "credentials" : [ {
    "apiProducts" : [ {
      "apiproduct" : "weather_free",
      "status" : "approved"
    } ],
    "attributes" : [ ],
    "consumerKey" : "bBGAQrXgivA9lKu7NMPyoYpVKNhGar6K",
    "consumerSecret" : "hAr4Gn0gA9vAyvI4",
    "scopes" : [ ],
    "status" : "approved"
  } ],
  "developerId" : "myorg@@@6E2W6HKAFsJhqAb9",
  "lastModifiedAt" : 1349462499114,
  "lastModifiedBy" : "admin@apigee.com",
  "name" : "weatherapp",
  "status" : "approved"
}

Note the consumer key and consumer secret values. The consumer key and secret are presented to the token endpoint as 'Basic Authentication' credentials as follows. The request must also specify the grant type, in this case client credentials. The grant type is presented as a query parameter to the request:

$ curl -u bBGAQrXgivA9lKu7NMPyoYpVKNhGar6K:hAr4Gn0gA9vAyvI4 http://{org_name}-test.apigee.net/weather/accesstoken?grant_type=client_credentials

The API Platform verifies the consumer key and secret and then generates a response containing the access token for this app:

{
"issued_at":1349466897628,
"scope":"",
"application_name":"weatherapp",
"status":"approved",
"organization_id":0,
"state":"null",
"expires_in":1799,
"api_profile_name":"null",
"refresh_token":"null",
"access_token":"OqX8UUlT98XAKsBbTYHpEt5tkiCV",
"refresh_count":0
}

Note the access_token value in the response above. This is the access token that the app will use to gain runtime access to protected resources.

The access token is included in the request as an "Authorization" HTTP header as follows:

curl -H "Authorization: Bearer OqX8UUlT98XAKsBbTYHpEt5tkiCV" http://{org_name}-test.apigee.net/weather/forecastrss?w=12797282

The API Platform validates that the access token presented is valid for the API product, and then grants access, returning the Weather report.

Post questions to the Apigee Developer Forum.

Back to API Platform Developer Guide.