Was this helpful?


This topic describes how to set up OAuth endpoints in an organization on Apigee Edge. An "OAuth endpoint" is a URL that is exposed by Apigee Edge in your organization. OAuth defines token endpoints, authorization endpoints, and refresh endpoints. Apps call these endpoints to get access tokens, to refresh access tokens, and, in some cases, to get authorization codes. Apigee Edge makes it easy to set up OAuth endpoints simply by configuring Policies.

You can put all of your OAuth endpoint Policies in an API proxy that is dedicated to supporting OAuth. To configure this OAuth proxy, you define a set of URIs and then attach OAuth Policies that support two-legged and/or three-legged OAuth exchanges. The OAuth proxy that you create does not make any backend calls. Instead, the OAuth proxy acts as a standalone service. Once you have set up the URIs and attached the Policies, app developers can call the URLs exposed by your API proxy to get access tokens, refresh access tokens, and so on.

Create a single API proxy to support all OAuth endpoints. However, do not mix endpoint functionality with runtime validation. In other words, don't issue access tokens from the same API proxy that validates tokens on behalf of protected resources.

Several sample API proxies that implement OAuth endpoints are available in the API Services samples on GitHub. To simplify OAuth endpoint setup, deploy the oauth-login-app sample proxy, and then modify the configuration to meet your requirements.

Default endpoints

Every organization on Apigee Edge is provided with one default OAuth token endpoint. The default token endpoint only supports the client credential grant type.

You can view the default OAuth 2.0 by selecting APIs > API Proxies from the main menu.

In the list of API proxies, you will see an API proxy called oauth.

Select the oauth API proxy to open the Overview.

Default OAuth 2.0 API proxy Overview

Select the Develop view.

Default OAuth 2.0 API proxy Develop view

Note that two OAuth Policies are configured:

  • RefreshAccessToken: This Policy exchanges access tokens for refresh tokens. (This Policy is disabled, because the client credentials grant type does not support refresh tokens.)
  • GenerateAccessTokenClient: This Policy implements the token endpoint functionality that validates consumer key/secret pairs and generates access tokens.

Also note two conditional Flows:

  • RefreshAccessToken: The RefreshAccessToken Policy is attached to this Flow.
  • AccessTokenClientCredential: The GenerateAccessTokenClient Policy is attached to this Flow.
To view the token endpoint configuration, under Navigator > Policies, select GenerateAccessTokenClient.

Policy and Flow configurations in the API Proxy Navigator

In the Code panel of the Develop view, the configuration of the AccessTokenClientCredential will display:

Code view of the AccessTokenClientCredential Policy

Default XML configuration

The default OAuthV2 policy is shown below:

<OAuthV2 name="GenerateAccessTokenClient">
  <!-- This policy generates an OAuth 2.0 access token using the client_credentials grant type -->
  <Operation>GenerateAccessToken</Operation>
  <!-- This is in millseconds, so expire in an hour -->
  <ExpiresIn>3600000</ExpiresIn>
  <SupportedGrantTypes>
    <GrantType>client_credentials</GrantType>
  </SupportedGrantTypes>
  <GrantType>request.queryparam.grant_type</GrantType>
  <GenerateResponse/>
</OAuthV2>

This is the policy that defines the token endpoint. To add additional grant types, you edit this Policy. (A single OAuth Policy can enable support for multiple grant types.)

To set up a token endpoint you use an OAuthV2 policy that specifies the GenerateAccessToken operation. The token endpoint is responsible for validating credentials (including authorization codes, if necessary) and then issuing an access token to an app that has been authorized.

The settings for the OAuthV2 Policy type are documented in Authorize requests using OAuth 2.0.

GenerateAccessToken Policy

As you can see in the Policy configuration below, a token endpoint is defined using a policy of type OAuthV2 that specifies the GenerateAccessToken operation. The GenerateAccessToken operation handles the complexity associated with authorizing apps and issuing access tokens. For example, the policy below configures a token endpoint that returns access tokens for the auth code, implicit, and client credentials grant types.

Create this policy as a file called GenerateAccessToken.xml under /apiproxy/policies with the following content:

<OAuthV2 name="GenerateAccessToken">
  <GenerateResponse/>
  <!-- <Operation>GenerateAccessToken</Operation> -->
  <!-- This is in millseconds, so expire in an hour -->
  <ExpiresIn>3600000</ExpiresIn>
  <SupportedGrantTypes>
    <GrantType>authorization_code</GrantType>
    <GrantType>implicit</GrantType>
    <GrantType>client_credentials</GrantType>
  </SupportedGrantTypes>
</OAuthV2>

For each grant type, the policy makes assumptions about the location or required information in request messages. These assumptions are based on the the OAuth 2.0 specification. If your apps need to deviate from the OAuth 2.0 specification, then you can specify the expected locations for each parameter. For example, when using auth code, you can specify the location of the authorization code, the client ID, the redirect URI, and the scope. These can be specified as HTTP headers, query parameters, or form parameters.

The example below demonstrates how you can specify the location of required authorization code parameters as HTTP headers:

<GrantType>request.header.grant_type</GrantType>
<Code>request.header.code</Code>
<ClientId>request.header.client_id</ClientId>
<RedirectUri>request.header.redirect_uri</RedirectUri>
<Scope>request.header.scope</Scope>

Or, if necessary to support your client app base, you can mix and match headers and query parameters:

<GrantType>request.header.grant_type</GrantType>
<Code>request.header.code</Code>
<ClientId>request.queryparam.client_id</ClientId>
<RedirectUri>request.queryparam.redirect_uri</RedirectUri>
<Scope>request.queryparam.scope</Scope>

Only one location can be configured per parameter.

For details see Authorize requests using OAuth 2.0.

Configure an authorization endpoint

The authorization code grant type requires you to configure a dedicated 'authorization endpoint'. The authorization endpoint is configured on Apigee Edge by creating two policies:

  • A GenerateAuthCode policy
  • A policy that implements the redirects required by the authorization code grant type

To define endpoints, each of these policies needs to be attached to a unique URI. Once you set up the URIs, you will 'publish' them out-of-band to client app developers. This will enable those developers to invoke the proper URLs to obtain auth codes and access tokens.

Generate authorization code

Authorization code requires you to implement a Login app that is a capable of authenticating app end users. The Login app handles the initial redirect from the client app, and provides a way to authenticate the app end user. After authenticating the user, the Login app calls back to the authorization endpoint, submitting a request that includes the client_id, response_type, and scope.

This request is handled by a policy of type OAuthV2 that specifies the GenerateAuthCode operation. (This policy is attached to the URI that is called only by the Login app, not by the requesting client app.)

GenerateAuthCode Policy

This policy configures an authorization endpoint.

Create a policy of type OAuthV2 that specifies the GenerateAuthorizationCode operations as follows:

<OAuthV2 name="GenerateAuthCode">
  <Operation>GenerateAuthorizationCode</Operation>
  <ExpiresIn>600000</ExpiresIn>
  <GenerateResponse/>
</OAuthV2>

Policy settings

Name Description Default Required?
OAuthV2 The 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 can 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
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

Redirect to login page

The authorization endpoint is responsible for redirecting the inbound request from the client app to the API provider's Login app, where the app end user can safely authenticate and authorize the client app without divulging passwords. This policy serves to redirect requests from the client app to the URL of your Login app, along with relevant information from the client app request.

One way to configure the redirect is by using a RaiseFault Policy. (You could also implement this functionality using an AssignMessage or ServiceCallout policy, or by implementing an HTTP client in JavaScript, Python, or Java.)

The following policy assumes that client app includes three query parameters (defined in the OAuth 2 specification) as part of the request:

  • client_id: The consumer key (API key) of the client app
  • response_type: The response type requested by the client app (in this case auth code)
  • scope: Any scopes included by the client app. A scope equates to a 'permission'. The Login app may optionally display the requested scope(s) to the app end user, to enable the user to provide informed consent on the operations requested by the client app. Authorized scopes are checked when the access token is validated.

Those values are obtained by the policy by accessing variables. (Note: All query parameters on a request message are automatically set as variables by API Services. You do not need to explicitly set these variables before accessing them in this policy.)

<RaiseFault name="RedirectToLoginApp">
  <IgnoreUnresolvedVariables>true</IgnoreUnresolvedVariables>
  <FaultResponse>
    <Set>
    <Headers>
    <Header name="Location">{login_app_URL}?client_id={request.queryparam.client_id}&response_type={request.queryparam.response_type}&scope={request.queryparam.scope}</Header>
    </Headers>
    <Payload contentType="text/plain">{login_app_URL}?client_id={request.queryparam.client_id}&response_type={request.queryparam.response_type}&scope={request.queryparam.scope}
	    </Payload>
    <StatusCode>302</StatusCode>
      <ReasonPhrase>Login App Redirect</ReasonPhrase>
    </Set>
  </FaultResponse>
</RaiseFault>

Policy settings

Name Description Default Required?
RaiseFault The policy type
name The name of the policy, which is referenced in the API proxy Endpoint configuration. N/A Yes
IgnoreUnresolvedVariables If a variable does not resolve, this element determines whether the API proxy continues message processing. N/A Yes
Set An element that indicates a value should be created for the FaultResponse that is generated, providing a way to construct a custom message. N/A Yes
Headers Indicates that a set of HTTP headers should be created on the FaultResponse. In this case, the HTTP header is Location along with the static value for the URL of the Login app. By including this HTTP header and setting the response code to 302, the Web browser that receives the response will automatically redirect the app end user's browser to the URL of the Login app. N/A Yes
Payload The body of the response message that will be generated by this policy. Set the Content-type HTTP header as an attribute of the element, for example text/xml or application/json. The payload in this case sets query parameters to values provided in the client app request, thereby forwarding these values to the Login app. The Login app must implement support for handling these parameters, and it must include these values in the request message that it generates for a successful authentication and authorization. N/A Yes
StatusCode Sets the HTTP status code for the response to 302. A 302 status code causes a Web browser to automatically redirect to the URL specified in the Location header. N/A Yes
ReasonPhrase A human-readable description of the operation indicated by the status code. N/A Yes

Remember that the policy above only demonstrates one way of configuring the redirect. You can also enable redirects using JavaScript, Java, or another type of policy such as AssignMessage.

Configuring the OAuth API proxy

3-legged OAuth requires three endpoints. You can include the three endpoints in a single ProxyEndpoint configuration.

For the client to initiate the three-legged protocol, define the following endpoints and publish the following URIs. (You can use any naming convention that you want. The following are just examples):

  • A URI to redirect the user agent (Web browser) to the provider's Login app:
    http://{org_name}-test.apigee.net/oauth/authorize
  • A URI to obtain an authorization code:
    http://{org_name}-test.apigee.net/oauth/authorizationcode
  • A URI to obtain an access token:
    http://{org_name}-test.apigee.net/oauth/accesstoken

For security in production, you must use HTTPS for these URLs. In this example, we use HTTP for simplicity.

These endpoint URIs are published out-of-band. That is, app developers must be informed of these URIs so that they know how to obtain authorization codes and access tokens before they can access a protected resource.

In API Services, these endpoints are created using a ProxyEndpoint configuration that defines three conditional Flows.

In this example, the respective conditional Flows are named RedirectToLoginApp, GetAuthCode, and GetAccessToken.

A different URI must be assigned to each Flow. (Again, these are just examples. You can name these URIs whatever you want.):

  • RedirectToLoginApp: /oauth/authorize
  • GetAuthCode: /oauth/authorizationcode
  • GetAccessToken: /oauth/accesstoken

With this configuration, to obtain an auth code, an app developer first redirects the app end user's user agent (Web browser) to the Login app by calling:

http://myorg-test.apigee.net/weather/oauth/authorize?client_id={consumer_key}&response_type=code&redirect_uri={redirect_uri}&scope=scope1%20scope2&state={some_string}

The Login app then authenticates the app end user and enables the app end user to authorize the app. (The client app developer has no role in this step.)

The Login app then redirects the user agent to the second URI to initiate the callback that provides an auth code to the client app:

http://myorg-test.apigee.net/weather/oauth/authorizationcode?client_id={consumer_key}&response_type=code&scope=scope1%20scope2&state={some_string}

The OAuthV2 policy attached to the endpoint at /oauth/authorizationcode redirects the app end user's user agent to the requesting client app.

The client app parses the redirect response to extract the authorization code. After obtaining the authorization code, the app uses the code to obtain an access token from the token endpoint at:

http://myorg-test.apigee.net/weather/oauth/accesstoken?code={authorization_code}&redirect_uri={redirect_uri}&grant_type=authorization_code

Along with the request string above, the client app must Base64-encode the consumer key and secret and include the resulting value in the POST request as an HTTP Authorization header.

"Authorization: Basic WExvdEwzUFJ4TmtVR1hoR0FGRFBPcjZmcXR2QWh1WmU6aU5VeUVhT09oOTZLUjNZTA=="

Finally, the app calls http://myorg-test.apigee.net/weather?access_token={access_token} using the access token to retrieve a weather forecast on behalf of the app end user.

Configuring OAuth Flows

The following ProxyEndpoint implements this Flow structure:

<Flows>
  <Flow name="RedirectToLoginApp">
    <!-- This policy flow is triggered when the URI path suffix matches /oauth/authorize -->
    <!-- Publish this URI to developers to use for their 'login' link -->
    <Condition>proxy.pathsuffix == "/oauth/authorize"</Condition>
    <Request>
	<Step><Name>RedirectToLoginPage</Name></Step>
    </Request>
  </Flow>
  <Flow name="GetAuthCode">
    <!-- This policy flow is triggered when the URI path suffix matches /oauth/authorizationcode -->
    <!-- Call this URL from your Login app after you authenticate the user -->
    <!-- The policy will automatically return the auth code in the response to the redirect_uri  -->
    <!-- on file for the requesting app   -->
    <Condition>proxy.pathsuffix == "/oauth/authorizationcode"</Condition>
    <Request>
	<Step><Name>GenerateAuthCode</Name></Step>
    </Request>
  </Flow>
  <Flow name="GetAccessToken">
    <!-- This policy flow is triggered when the URI path suffix matches /oauth/accesstoken -->
    <!-- Publish this URL to app developers to use when obtaining an access token using an auth code   -->
    <Condition>proxy.pathsuffix == "/oauth/accesstoken"</Condition>
    <Request>
	<Step><Name>GenerateAccessToken</Name></Step>
    </Request>
  </Flow>
</Flows>

Once you have deployed the API proxy, the OAuth endpoints you have defined will be available to app developers.

Get help

For help, see Apigee Customer Support.

Help or comments?

  • Something's not working: See Apigee Support
  • Something's wrong with the docs: Click Send Feedback in the lower right.
    (Incorrect? Unclear? Broken link? Typo?)