You're viewing **Apigee Edge** documentation.  
[Go to the
**Apigee X** documentation](http://cloud.google.com/apigee/docs/api-platform/reference/policies/oauthv2-policy). info
![](https://docs.apigee.com/static/api-platform/images/icon_policy_security.jpg)

### What

OAuthV2 is a multi-faceted policy for performing OAuth 2.0 grant type operations. This is the
primary policy used to configure OAuth 2.0 endpoints on Apigee Edge.

> [!NOTE]
> **Hybrid**: If you're using Apigee hybrid, note that OAuthV2 access tokens and refresh tokens are hashed by default when stored in the runtime Cassandra database. Hashing prevents the tokens from being used if the database were compromised.

> [!WARNING]
> **Note** : The OAuthV2 policy returns certain non-[RFC-compliant](https://tools.ietf.org/html/rfc6749) response elements. For example, the policy returns a token property, `"token_type":"BearerToken"`, where the compliant token property is `"token_type":"Bearer"`. For details on these non-compliant response elements, see [Non-RFC-compliant behavior](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy#non-rfc-compliant-behavior).

**Tip:** If you want to learn more about OAuth on Apigee Edge, see
the [OAuth home page](https://docs.apigee.com/api-platform/security/oauth/oauth-home). It provides links
to resources, samples, videos, and more. See the [advanced
OAuth sample](https://github.com/apigee/api-platform-samples/tree/master/sample-proxies/oauth-advanced) on GitHub for a good demonstration of how this policy is used in a working
application.

### Samples

### VerifyAccessToken

### VerifyAccessToken

This OAuthV2 policy configuration (with the VerifyAccessToken operation) verifies that an
access token submitted to Apigee Edge is valid. When this policy operation is triggered, Edge
looks for a valid access token in the request. If the access token is valid, the request is
allowed to proceed. If invalid, all processing stops and an error is returned in the
response.

```
<OAuthV2 async="false" continueOnError="false" enabled="true" name="OAuth-v20-2">
    <DisplayName>OAuth v2.0 2</DisplayName>
    <Operation>VerifyAccessToken</Operation>
    <AccessTokenPrefix>Bearer</AccessTokenPrefix> <!-- Optional, default is Bearer -->
</OAuthV2>
```

Note: Only OAuth 2.0 Bearer Tokens are supported. Message Authentication
Code (MAC) tokens are not supported.

For example:

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


By default, Edge accepts access tokens in the `Authorization` header with
the `Bearer` prefix. You can change this default with the `<AccessToken>`
element.

### GenerateAccessToken

### Generating access tokens

For examples showing how to request access tokens for each of the supported grant types,
see [Requesting access tokens and
authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens). The topic includes examples of these operations:

- [Authorization code](https://docs.apigee.com/api-platform/security/oauth/access-tokens#requestinganaccesstokenauthorizationcodegranttype)
- [Client credentials](https://docs.apigee.com/api-platform/security/oauth/access-tokens#requestinganaccesstokenclientcredentialsgranttype)
- [Implicit](https://docs.apigee.com/api-platform/security/oauth/access-tokens#requestinganaccesstokenimplicitgranttype)
- [Password](https://docs.apigee.com/api-platform/security/oauth/access-tokens#requestinganaccesstokenpasswordgranttype)

### GenerateAuthorizationCode

### Generate authorization code

For examples showing how to request authorization codes, see [Requesting an
authorization code](https://docs.apigee.com/api-platform/security/oauth/access-tokens#requestinganauthorizationcode).

### RefreshAccessToken

### Refresh an access token

For examples showing how to request access tokens using a refresh token, see [Refreshing an
access token](https://docs.apigee.com/api-platform/security/oauth/access-tokens#refreshinganaccesstoken).

### Response flow token

### Generate an access token on the response flow

Sometimes you may need to generate an access token in the response flow. For example, you
may do this in response to some custom validation done in a backend service. In this example,
the use case requires both an access token and a refresh token, ruling out the implicit grant
type. In this case, we'll use the password grant type to generate the token. As you'll see,
the trick to making this work is to pass in an Authorization request header with a JavaScript
policy.

First, let's look at the sample policy:

```
<OAuthV2 enabled="true" continueOnError="false" async="false" name="generateAccessToken">
    <Operation>GenerateAccessToken</Operation>
    <AppEndUser>Doe</AppEndUser>
    <UserName>jdoe</UserName>
    <PassWord>jdoe</PassWord>
    <GrantType>grant_type</GrantType>
    <ClientId>a_valid_client_id</ClientId>
    <SupportedGrantTypes>
        <GrantType>password</GrantType>
    </SupportedGrantTypes>
</OAuthV2>
```

If you put this policy on the response flow, it will fail with a 401 UnAuthorized error
even though the correct login parameters are specified in the policy. To solve this problem,
you need to set an Authorization request header.

The Authorization header must contain a Basic access scheme with the Base64-encoded
client_id:client_secret.

You can add this header with a JavaScript policy placed just before the OAuthV2 policy,
like this. The "local_clientid" and "local_secret" variables must be previously set and
available in the flow:

```
var client_id = context.getVariable("local_clientid");
var client_secret = context.getVariable("local_secret");
context.setVariable("request.header.Authorization","Basic "+CryptoJS.enc.Base64.stringify(CryptoJS.enc.Latin1
                                      .parse(client_id + ':' + client_secret)));
```

See also "[Encoding basic
authentication credentials](https://docs.apigee.com/api-platform/security/oauth/access-tokens#encoding)".

## Element reference

The policy reference describes the elements and attributes of the OAuthV2 policy.

> [!NOTE]
> **Note:** The way you configure this policy, and the elements you need to specify, depend on which operation you want the policy to perform. For example, if you are implementing the authorization code grant type, then you will require four separate OAuthV2 policies to perform authorization code generation, access code generation, access code validation, and refresh token generation. This reference lists all of the elements that can be used with this policy.
>
> If you want to see configurations for specific grant type use cases, refer to the [OAuth home page](https://docs.apigee.com/api-platform/security/oauth/oauth-home) for a list of grant type
> implementations. In particular, see the [advanced
> OAuth sample](https://github.com/apigee/api-platform-samples/tree/master/sample-proxies/oauth-advanced) on GitHub for a good demonstration of how this policy is used in a
> working application.

The sample policy shown below is one of many possible configurations. This sample shows an
OAuthV2 policy configured for the GenerateAccessToken operation. It includes required and
optional elements. Refer to the element descriptions in this section for details.

```
<OAuthV2 name="GenerateAccessToken">
  <!-- 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>
```

## \<OAuthV2\> attributes

```
<OAuthV2 async="false" continueOnError="false" enabled="true" name="MyOAuthPolicy">
```

The following table describes attributes that are common to all policy parent elements:

| Attribute | Description | Default | Presence |
|---|---|---|---|
| `name` | The internal name of the policy. The value of the `name` attribute can contain letters, numbers, spaces, hyphens, underscores, and periods. This value cannot exceed 255 characters. Optionally, use the `<DisplayName>` element to label the policy in the management UI proxy editor with a different, natural-language name. | N/A | Required |
| `continueOnError` | Set to `false` to return an error when a policy fails. This is expected behavior for most policies. Set to `true` to have flow execution continue even after a policy fails. | false | Optional |
| `enabled` | Set to `true` to enforce the policy. Set to `false` to *turn off* the policy. The policy will not be enforced even if it remains attached to a flow. | true | Optional |
| `async` | This attribute is deprecated. | false | Deprecated |

## \<DisplayName\> element

Use in addition to the `name` attribute to label the policy in the
management UI proxy editor with a different, natural-language name.

```
<DisplayName>Policy Display Name</DisplayName>
```

| Default | N/A If you omit this element, the value of the policy's `name` attribute is used. |
| Presence | Optional |
| Type | String |
|---|---|

## \<AccessToken\> element

```
<AccessToken>request.header.access_token</AccessToken>
```

By default, VerifyAccessToken expects the access token to be sent in the `Authorization`
header.
You can change that default using this element. For
example `request.queryparam.access_token` indicates that the access token
should be present as a query parameter named `access_token`.
Example where `<AccessToken>request.header.access_token</AccessToken>` is specified:

<br />

```
curl https://myorg-myenv.apigee.net/oauth2/validate -H "access_token:Rft3dqrs56Blirls56a"
```
Example where `<AccessToken>request.queryparam.access_token</AccessToken>` is specified:

<br />

```
curl "https://myorg-myenv.apigee.net/oauth2/validate?access_token:Rft3dqrs56Blirls56a"
```

|---|---|
| **Default:** | N/A |
| **Presence:** | Optional |
| **Type:** | String |
| **Used with operations:** | - VerifyAccessToken |

## \<AccessTokenPrefix\> element

```
<AccessTokenPrefix>Bearer</AccessTokenPrefix>
```

By default, VerifyAccessToken expects the access token to be sent in an Authorization header
as a Bearer token. For example:

```
-H "Authorization: Bearer Rft3dqrs56Blirls56a"
```

Currently, Bearer is the only supported prefix.

|---|---|
| **Default:** | Bearer |
| **Presence:** | Optional |
| **Type:** | String |
| **Valid values:** | Bearer |
| **Used with operations:** | - VerifyAccessToken |

## \<AppEndUser\> element

```
<AppEndUser>request.queryparam.app_enduser</AppEndUser>
```

In cases where the app end user ID must be sent to the authorization server, this element lets
you specify where Edge should look for the end user ID. For example, it could be sent as a query
parameter or in an HTTP header.

For example `request.queryparam.app_enduser` indicates that the
AppEndUser should be present as a query parameter, as, for
example, `?app_enduser=ntesla@theramin.com`. To require the AppEndUser in an HTTP
header, for example, set this value to `request.header.app_enduser`.

Providing this setting enables you to include an app end user ID in the access token. This
feature is useful if you want to be able to retrieve or revoke OAuth 2.0 access tokens by end
user ID. For more information, see [Enable retrieval and revocation of OAuth 2.0 access tokens by end user ID, app id, or
both](https://docs.apigee.com/api-platform/security/oauth/enable-retrieval-and-revocation-oauth-20-access-tokens-end-user-id-app-id-or-both).

|---|---|
| **Default:** | N/A |
| **Presence:** | Optional |
| **Type:** | String |
| **Valid values:** | Any flow variable accessible to the policy at runtime. |
| **Used with grant types:** | - authorization_code - implicit - password - client_credentials |

## \<Attributes/Attribute\>

```
<Attributes>
    <Attribute name="attr_name1" ref="flow.variable" display="true|false">value1</Attribute>
    <Attribute name="attr_name2" ref="flow.variable" display="true|false">value2</Attribute>
</Attributes>
```

Use this element to add custom attributes to an access token or authorization code. For
example, you may wish to embed a user ID or session identifier in an access token that can be
extracted and checked at runtime.

This element lets you specify a value in a flow variable or from a literal string. If you
specify both a variable and a string, the value specified in the flow variable is used. If the
variable cannot be resolved, then the string is the default.

For more information on using this element, see [Customizing Tokens and
Authorization Codes](https://docs.apigee.com/api-platform/security/oauth/customizing-access-tokens).

> [!NOTE]
> **Notes:**
>
> You can create up to 18 custom attributes.
>
> If you add custom attributes to an authorization code, those attributes will be
> inherited by the access token generated from that code.

### Displaying or hiding custom attributes in the
response

Remember that if you set the GenerateResponse element of this policy to **true**,
the full JSON representation of the token is returned in the response, including any custom
attributes that you set. In some cases, you might want to hide some or all of your custom
attributes in the response so that they are not visible to client apps.

By default, custom attributes do appear in the response. If you want to hide them, you can set
the **display** parameter to **false**. For example:

```
<Attributes>
    <Attribute name="employee_id" ref="employee.id" display="false"/>
    <Attribute name="employee_name" ref="employee.name" display="false"/>
</Attributes>
```

The value of the `display` attribute is not
persisted. Let's say you generate an access token with custom attributes that you want to hide in the
generated response. Setting `display=false` accomplishes that goal. However, if a new
access token is generated later using a refresh token, the original custom attributes from the
access token will show up in the refresh token response. This is because Edge does not remember that
the `display` attribute was originally set to `false` in the generate access token policy--the custom
attribute is simply part of the access token's metadata.

You will see the same behavior if you add custom attributes to an authorization code--when an
access token is generated using that code, those custom attributes will show up in the access token
response. Again, this may not be the behavior you intend.

To hide custom
attributes in these cases, you have these choices:

- Explicitly reset the custom attributes in the refresh token policy and set their display to false. In this case, you may need to retrieve the original custom values from the original access token using the GetOAuthV2Info policy.
- Use a postprocessing JavaScript policy to manually extract any custom attributes that you do not want to see in the response.

See also [Customizing Tokens and
Authorization Codes](https://docs.apigee.com/api-platform/security/oauth/customizing-access-tokens).

|---|---|
| **Default:** | `N/A` |
| **Presence:** | Optional |
| **Valid values:** | - `name` -The attribute name - `ref` - The value of the attribute. Can come from a flow variable. - `display` - (Optional) Lets you specify whether or not custom attributes appear in the response. If `true`, custom attributes appear in the response (If `GenerateResponse` is also enabled). If `false`, custom attributes are not included in the response. Default value is `true`. See [Displaying or hiding custom attributes in the response](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy#displayorhide). |
| **Used with grant types:** | - authorization_code - implicit - password - client_credentials - refresh_token - Can also be used with the GenerateAuthorizationCode operation. |

## \<ClientId\> element

```
<ClientId>request.formparam.client_id</ClientId>
```

In several cases, the client app must send the client ID to the authorization server. This element
specifies that Apigee should look for the client ID in the flow variable
`request.formparam.client_id`. Setting `ClientId`
to any other variable is not supported.
See also [Requesting access tokens and authorization
codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens).

|---|---|
| **Default:** | request.formparam.client_id (a x-www-form-urlencoded and specified in the request body) |
| **Presence:** | Optional |
| **Type:** | String |
| **Valid values:** | The flow variable: `request.formparam.client_id` |
| **Used with grant types:** | - authorization_code - password - implicit - client_credentials Can also be used with the GenerateAuthorizationCode operation. |

## \<Code\> element

```
<Code>request.queryparam.code</Code>
```

In the authorization grant type flow, the client must submit an authorization code to the
authorization server (Apigee Edge). This element lets you specify where Edge should look for the
authorization code. For example, it could be sent as a query parameter, HTTP header, or form
parameter (the default).

The variable, `request.queryparam.auth_code` indicates that the
authorization code should be present as a query parameter, as, for
example, `?auth_code=AfGlvs9`. To require the authorization code in an HTTP
header, for example, set this value to `request.header.auth_code`. See also
[Requesting access tokens and
authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens).

|---|---|
| **Default:** | request.formparam.code (a x-www-form-urlencoded and specified in the request body) |
| **Presence:** | optional |
| **Type:** | String |
| **Valid values:** | Any flow variable accessible to the policy at runtime |
| **Used with grant types:** | authorization_code |

## \<ExpiresIn\> element

```
<ExpiresIn>10000</ExpiresIn>
```

Enforces the expiry time of access tokens and authorization codes in milliseconds. (For
refresh tokens, use `<RefreshTokenExpiresIn>`.) The expiry time value is a
system-generated value plus the `<ExpiresIn>` value. If
`<ExpiresIn>` is set to **-1** , the token or code expires as per the [maximum OAuth access token expiration](https://docs.apigee.com/api-platform/reference/limits#oauth).
If `<ExpiresIn>` is not specified, the system applies a
default value configured at the system level.

The expiry time can also be set at runtime using either a hard-coded, default value or by
referencing a flow variable. For example, you can store a token expiration value in a key value
map, retrieve it, assign it to a variable, and reference it in the policy. For example,
`kvm.oauth.expires_in`.

With **Apigee Edge for Public Cloud** , Edge keeps the
following entities in cache for a minimum of 180 seconds after the entities are *accessed*.

- OAuth access tokens. This means that a revoked token may still succeed for up to three minutes, until its cache limit expires.
- Key Management Service (KMS) entities (Apps, Developers, API Products).
- Custom attributes on OAuth tokens and KMS entities.

The following stanza specifies a flow variable and a default value as well. Note that the flow
variable value takes precedence over the specified default value.

```
<ExpiresIn ref="kvm.oauth.expires_in">
    3600000 <!--default value in milliseconds-->
</ExpiresIn>
```

Edge does not support a way to force the expiration of a token after it has been created.
If you need to force token expiration (for example, based on a condition), a possible solution is
described in [this Apigee Community post](https://discuss.google.dev/t/is-there-a-way-to-update-expiry-time-of-an-existing-access-token/7293).

By default, expired access tokens are purged from the Apigee
Edge system automatically 3 days after expiration. See also [Purging access
tokens](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy#purge)

**Private Cloud:** For an Edge for Private Cloud installation, the default
value is set by the `conf_keymanagement_oauth_auth_code_expiry_time_in_millis` property.
To set this property:

1. Open the `message-processor.properties` file in an editor. If the file does not exist, create it:

   ```
   vi /opt/apigee/customer/application/message-processor.properties
   ```
2. Set the property as desired:

   ```
   conf_keymanagement_oauth_auth_code_expiry_time_in_millis=3600000
   ```
3. Make sure the properties file is owned by the "apigee" user:

   ```
   chown apigee:apigee /opt/apigee/customer/application/message-processor.properties
   ```
4. Restart the Message Processor.

   ```
   /opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
   ```

|---|---|
| **Default:** | If not specified, the system applies a default value configured at the system level. |
| **Presence:** | Optional |
| **Type:** | Integer |
| **Valid values:** | - Any positive, non-zero integer. Specify the expiry time in **milliseconds** . Although the value of this element is in milliseconds, the value set in the token's `expires_in` property and in the `expires_in` flow variable is expressed in seconds. - **-1** will expire as per the [maximum OAuth access token expiration](https://docs.apigee.com/api-platform/reference/limits#oauth). **NOTE:** Specifying any other negative integer or zero causes a deployment error. See also [Antipattern: Set a long expiration time for OAuth tokens](https://docs.apigee.com/api-platform/antipatterns/oauth-long-expiration). |
| **Used with grant types:** | - authorization_code - implicit - password - client_credentials - refresh_token Also used with GenerateAuthorizationCode operation. |

> [!NOTE]
> **Note:** Note that if ExpiresIn is set to **-1** you will see the following expiration value in the generated token: `"expires_in" :
> "0"`.

## \<ExternalAccessToken\> element

```
<ExternalAccessToken>request.queryparam.external_access_token</ExternalAccessToken>
```

Tells Apigee Edge where to find an external access token (an access token not generated by
Apigee Edge).

The variable `request.queryparam.external_access_token` indicates that
the external access token should be present as a query parameter, as, for
example, `?external_access_token=12345678`. To require the external access token
in an HTTP header, for example, set this value
to `request.header.external_access_token`. See also [Using Third-Party OAuth
Tokens](https://docs.apigee.com/api-platform/security/oauth/use-third-party-oauth-system).

## \<ExternalAuthorization\> element

```
<ExternalAuthorization>true</ExternalAuthorization>
```

If this element is false or not present, then Edge validates the client_id and client_secret
normally against the Apigee Edge authorization store. Use this element when you want to work with
third-party OAuth tokens. For details on using this element, see [Using Third-Party OAuth
Tokens](https://docs.apigee.com/api-platform/security/oauth/use-third-party-oauth-system).

|---|---|
| **Default:** | false |
| **Presence:** | Optional |
| **Type:** | Boolean |
| **Valid values:** | true or false |
| **Used with grant types:** | - authorization_code - password - client_credentials |

## \<ExternalAuthorizationCode\> element

```
<ExternalAuthorizationCode>request.queryparam.external_auth_code</ExternalAuthorizationCode>
```

Tells Apigee Edge where to find an external auth code (an auth code not generated by
Apigee Edge).

The variable `request.queryparam.external_auth_code` indicates that
the external auth code should be present as a query parameter, as, for
example, `?external_auth_code=12345678`. To require the external auth
code
in an HTTP header, for example, set this value
to `request.header.external_auth_code`. See also [Using Third-Party OAuth
Tokens](https://docs.apigee.com/api-platform/security/oauth/use-third-party-oauth-system).

## \<ExternalRefreshToken\> element

```
<ExternalRefreshToken>request.queryparam.external_refresh_token</ExternalRefreshToken>
```

Tells Apigee Edge where to find an external refresh token (a refresh token not generated by
Apigee Edge).

The variable `request.queryparam.external_refresh_token` indicates that
the external refresh token should be present as a query parameter, as, for
example, `?external_refresh_token=12345678`. To require the external refresh token
in an HTTP header, for example, set this value
to `request.header.external_refresh_token`. See also [Using Third-Party OAuth
Tokens](https://docs.apigee.com/api-platform/security/oauth/use-third-party-oauth-system).

## \<GenerateResponse\> element

```
<GenerateResponse enabled='true'/>
```

If set to `true`, the policy generates and returns a response. For example, for
GenerateAccessToken, the response might be like:

```
{
  "issued_at" : "1467841035013",
  "scope" : "read",
  "application_name" : "e31b8d06-d538-4f6b-9fe3-8796c11dc930",
  "refresh_token_issued_at" : "1467841035013",
  "status" : "approved",
  "refresh_token_status" : "approved",
  "api_product_list" : "[Product1, nhl_product]",
  "expires_in" : "1799",
  "developer.email" : "edward@slalom.org",
  "token_type" : "BearerToken",
  "refresh_token" : "rVSmm3QaNa0xBVFbUISz1NZI15akvgLJ",
  "client_id" : "Adfsdvoc7KX5Gezz9le745UEql5dDmj",
  "access_token" : "AnoHsh2oZ6EFWF4h0KrA0gC5og3a",
  "organization_name" : "cerruti",
  "refresh_token_expires_in" : "0",
  "refresh_count" : "0"
}
```

If `false`, no response is sent. Instead, a set of flow variables are populated
with values related to the policy's function. For example, a flow variable called
`oauthv2authcode.OAuthV2-GenerateAuthorizationCode.code` gets populated with the newly
minted auth code. Note that **expires_in** is expressed in seconds in the
response.

|---|---|
| **Default:** | false |
| **Presence:** | Optional |
| **Type:** | string |
| **Valid values:** | true or false |
| **Used with grant types:** | - implicit - password - client_credentials - refresh_token - Also can be used with the GenerateAuthorizationCode operation. |

## \<GenerateErrorResponse\> element

```
<GenerateErrorResponse enabled='true'/>
```

If set to `true`, the policy generates and returns a response if the
ContinueOnError attribute is set to true. If `false` (the default), no
response is sent. Instead, a set of flow variables are populated with values related to the
policy's function.

|---|---|
| **Default:** | false |
| **Presence:** | Optional |
| **Type:** | string |
| **Valid values:** | true or false |
| **Used with grant types:** | - implicit - password - client_credentials - refresh_token - Also can be used with the GenerateAuthorizationCode operation. |

## \<GrantType\>

```
<GrantType>request.queryparam.grant_type</GrantType>
```

Tells the policy where to find the grant type parameter that is passed in a request. Per the
OAuth 2.0 specification, the grant type must be supplied with requests for access tokens and
authorization codes. The variable can be a header, query parameter, or form parameter
(default).

For example `request.queryparam.grant_type` indicates that the Password
should be present as a query parameter, as, for example, `?grant_type=password`.
To require the grant type in an HTTP header, for example, set this value
to `request.header.grant_type`. See also [Requesting access tokens and authorization
codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens).

|---|---|
| **Default:** | request.formparam.grant_type (a x-www-form-urlencoded and specified in the request body) |
| **Presence:** | Optional |
| **Type:** | string |
| **Valid values:** | A variable, as explained above. |
| **Used with grant types:** | - authorization_code - password - implicit - client_credentials - refresh_token |

## \<Operation\> element

```
<Operation>GenerateAuthorizationCode</Operation>
```

The OAuth 2.0 operation executed by the policy.

|---|---|
| **Default:** | If `<Operation>` is not specified, Edge looks at the list of `<SupportedGrantTypes>`. Only operations on those grant types will be successful. In other words, you can omit `<Operation>` if you specify a `<GrantType>` in the `<SupportedGrantTypes>` list. If neither `<Operation>` nor `<SupportedGrantTypes>` are specified, the default grant type is authorization_code. That is, authorization_code grant type requests will succeed, but all others will fail. |
| **Presence:** | Optional |
| **Type:** | String |
| **Valid values:** | - `GenerateAccessToken` - Generates an access token. See also [Requesting access tokens and authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens). - `GenerateAccessTokenImplicitGrant` - Generates an access token for the implicit grant type. See also [Requesting access tokens and authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens). - `GenerateAuthorizationCode` - Generates an auth code. Used with the authorization code grant type. See also [Requesting access tokens and authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens). - `RefreshAccessToken` - Exchange a refresh token for a new access token. See also [Requesting access tokens and authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens). - `VerifyAccessToken` - Verifies that an access token sent in a request is valid. See the VerifyAccessToken sample above and "[Verifying access tokens](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy#verifying)". - `InvalidateToken` - Revokes an access token. After a token has been revoked, clients cannot use that token to call a protected API. See also [Approving and revoking access tokens](https://docs.apigee.com/api-platform/security/oauth/validating-and-invalidating-access-tokens). - `ValidateToken` - Reinstates or "approves" an access token that was previously revoked. See also [Approving and revoking access tokens](https://docs.apigee.com/api-platform/security/oauth/validating-and-invalidating-access-tokens). |

## \<PassWord\> element

```
<PassWord>request.queryparam.password</PassWord>
```

**This element is used with the** **password grant type only** . With
the password grant type, user credentials (password and username) must be made available to the
OAuthV2 policy. The `<PassWord>` and `<UserName>` elements are
used to specify variables where Edge can find these values. If these elements are not specified,
the policy expects to find the values (by default) in form parameters named `username`
and `password`. If the values are not found, the policy throws an error. You can use
the `<PassWord>` and `<UserName>` elements to reference any
flow variable containing the credentials.

For example, you can pass the password in a token request using a query parameter and set the
element like this:
`<PassWord>request.queryparam.password</PassWord>``.` To
require the password in an HTTP header, set this value
to `request.header.password`.

The OAuthV2 policy doesn't do anything else with these credential values; Edge is simply
verifying that they are present. It is up to the API developer to retrieve the values request and
send them to an identity provider before the token generation policy executes.

See also [Requesting access tokens
and authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens).

|---|---|
| **Default:** | request.formparam.password (a x-www-form-urlencoded and specified in the request body) |
| **Presence:** | Optional |
| **Type:** | String |
| **Valid values:** | Any flow variable available to the policy at runtime. |
| **Used with grant types:** | password |

## \<RedirectUri\> element

```
<RedirectUri>request.queryparam.redirect_uri</RedirectUri>
```

Specifies where Edge should look for the `redirect_uri` parameter in the
request.

### About redirection URIs

Redirection URIs are used with the authorization code and implicit grant types. The redirect
URI tells the authorization server (Edge) where to send an authorization code (for the auth code
grant type) or access token (for the implicit grant type). It's important to understand when this
parameter is required, when it is optional, and how it is used:

- (required) If a Callback URL is registered with the developer app that is associated with
  the request's client keys, and if the `redirect_uri` is present in the request,
  then the two must match exactly. If they do not match, an error is returned. For information
  on registering developer apps on Edge and specifying a Callback URL, see [Register apps and manage API
  keys](https://docs.apigee.com/api-platform/publish/creating-apps-surface-your-api).

  > [!NOTE]
  > **Note:** To ensure that Edge checks for an exact match between "Callback URL" and "redirect_uri" (as opposed to a forward match), set the following property in your organization: `features.isStrictOAuthUriValidation = true`. The default is false (forward match).
  >
  > If you're a cloud customer, contact [Apigee Edge Support](https://docs.apigee.com/api-platform/troubleshoot/support) to enable
  > the property. If you're an Apigee Edge for Private Cloud customer, set the flag using the
  > following API PUT call with System Administrator credentials.
  >
  > ```
  > curl -u email:password -X PUT -H "Content-type:application/xml" http://host:port/v1/o/{myorg} -d \
  > "<Organization type="trial" name="MyOrganization">
  >     <Properties>
  >         <Property name="features.isStrictOAuthUriValidation">true</Property>
  >         <!-- other existing org properties -->
  >     </Properties>
  > </Organization>"
  > ```
  >
  > > [!WARNING]
  > > **Warning:** When you update the organization with the API call, be sure to include all the existing organization properties in the payload. If you don't, all existing organization properties are overwritten by only the properties you set with this call.
  >
- (optional) If a Callback URL is registered, and the `redirect_uri` is missing from the request, then Edge redirects to the registered Callback URL.
- (required) If a Callback URL is not registered, then the `redirect_uri` is required. Note that in this case, Edge will accept ANY URL. **This case can present a
  security issue,** **and therefore should only be used with trusted client
  apps.** If client apps are not trusted, then the best practice is to always require the registration of a Callback URL.

You can send this parameter in a query parameter or in a header. The
variable `request.queryparam.redirect_uri` indicates that the RedirectUri
should be present as a query parameter, as, for
example, `?redirect_uri=login.myapp.com`. To require the RedirectUri in an HTTP
header, for example, set this value to `request.header.redirect_uri`. See
also [Requesting access tokens and
authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens).

|---|---|
| **Default:** | request.formparam.redirect_uri (a x-www-form-urlencoded and specified in the request body) |
| **Presence:** | Optional |
| **Type:** | String |
| **Valid values:** | Any flow variable accessible in the policy at runtime |
| **Used with grant types:** | - authorization_code - implicit Also used with the GenerateAuthorizationCode operation. |

## \<RefreshToken\> element

```
<RefreshToken>request.queryparam.refreshtoken</RefreshToken>
```

When requesting an access token using a refresh token, you must supply the refresh token in
the request. This element lets you specify where Edge should look for the refresh token. For
example, it could be sent as a query parameter, HTTP header, or form parameter (the default).

The variable `request.queryparam.refreshtoken` indicates that the refresh
token should be present as a query parameter, as, for
example, `?refresh_token=login.myapp.com`. To require the RefreshToken in an HTTP
header, for example, set this value to `request.header.refresh_token`. See
also [Requesting access tokens and
authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens).

|---|---|
| **Default:** | request.formparam.refresh_token (a x-www-form-urlencoded and specified in the request body) |
| **Presence:** | Optional |
| **Type:** | String |
| **Valid values:** | Any flow variable accessible in the policy at runtime |
| **Used with grant types:** | - refresh_token |

## \<RefreshTokenExpiresIn\> element

```
<RefreshTokenExpiresIn>1000</RefreshTokenExpiresIn>
```

Enforces the expiry time of refresh tokens in milliseconds. The expiry time value is a system
generated value plus the `<RefreshTokenExpiresIn>` value. If
`<RefreshTokenExpiresIn>` is set to **-1** , the refresh token
expires as per the [maximum OAuth refresh token expiration](https://docs.apigee.com/api-platform/reference/limits#oauth). If `<RefreshTokenExpiresIn>` is not specified,
the system applies a default value configured at the system level. Contact [Apigee Edge Support](https://docs.apigee.com/api-platform/troubleshoot/support) for more
information about default system settings.

The expiry time can also be set at runtime using either a hard-coded, default value or by
referencing a flow variable. For example, you can store a token expiration value in a key value
map, retrieve it, assign it to a variable, and reference it in the policy. For
example, `kvm.oauth.expires_in`.

The following stanza specifies a flow variable and a default value as well. Note that the flow
variable value takes precedence over the specified default value.

```
<RefreshTokenExpiresIn ref="kvm.oauth.expires_in">
    3600000 <!--default value in milliseconds-->
</RefreshTokenExpiresIn>
```

**Private Cloud:** For an Edge for Private Cloud installation, the default
value is set by the `conf_keymanagement_oauth_refresh_token_expiry_time_in_millis` property.
To set this property:

1. Open the `message-processor.properties` file in an editor. If the file does not exist, create it:

   ```
   vi /opt/apigee/customer/application/message-processor.properties
   ```
2. Set the property as desired:

   ```
   conf_keymanagement_oauth_refresh_token_expiry_time_in_millis=3600000
   ```
3. Make sure the properties file is owned by the "apigee" user:

   ```
   chown apigee:apigee /opt/apigee/customer/application/message-processor.properties
   ```
4. Restart the Message Processor.

   ```
   /opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
   ```

|---|---|
| **Default:** | 63072000000 ms (2 years) **(effective Aug 05, 2024)** |
| **Presence:** | Optional |
| **Type:** | Integer |
| **Valid values:** | - Any positive, non-zero integer. Specifies the expiry time in milliseconds. - **-1** will expire as per the [maximum OAuth refresh token expiration](https://docs.apigee.com/api-platform/reference/limits#oauth). **NOTE:** Specifying any other negative integer or zero causes a deployment error. See also [Antipattern: Set a long expiration time for OAuth tokens](https://docs.apigee.com/api-platform/antipatterns/oauth-long-expiration). |
| **Used with grant types:** | - authorization_code - password - refresh_token |

## \<ResponseType\> element

```
<ResponseType>request.queryparam.response_type</ResponseType>
```

This element informs Edge which grant type the client app is requesting. It is used only with
the authorization code and implicit grant type flows.

By default, Edge looks for the response type value in a `response_type` query
parameter. If you wish to override this default behavior, use the \<ResponseType\> element to
configure a flow variable containing the response type value. For example, if you set this
element to `request.header.response_type`, Edge looks for the response type to be
passed in the request header. See also [Requesting access tokens and authorization
codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens).

|---|---|
| **Default:** | request.formparam.response_type (a x-www-form-urlencoded and specified in the request body) |
| **Presence:** | Optional. Use this element if you wish to override the default behavior. |
| **Type:** | String |
| **Valid values:** | Either `code` (for the authorization code grant type) or `token` (for the implicit grant type) |
| **Used with grant types:** | - implicit - Also used with the GenerateAuthorizationCode operation. |

## \<ReuseRefreshToken\> element

```
<ReuseRefreshToken>true</ReuseRefreshToken>
```

When set to `true`, the existing refresh token is reused until it expires. If
`false`, a new refresh token is issued by Apigee Edge when a valid refresh token is
presented.

|---|---|
| **Default:** | `false` |
| **Presence:** | optional |
| **Type:** | boolean |
| **Valid values:** | `true` or `false` |
| **Used with grant type:** | - refresh_token |

## \<Scope\> element

```
<Scope>request.queryparam.scope</Scope>
```

If this element is present in one of the GenerateAccessToken or GenerateAuthorizationCode
policies, it is used to specify which scopes to grant the token or code. These values are
typically passed to the policy in the request from a client app. You can configure the element to
take a flow variable, giving you the option to choose how the scopes are passed in a request. In
the following example, `request.queryparam.scope` indicates that the scope should
be present as a query parameter, as, for example, `?scope=READ`. To require the
scope in an HTTP header, for example, set this value
to `request.header.scope`.

If this element appears in a "VerifyAccessToken" policy, then it is used to specify which
scopes the policy should enforce. In this type of policy, the value must be a "hard coded" scope
name -- you can't use variables. For example:

```
<Scope>A B</Scope>
```

See also [Working with OAuth2
scopes](https://docs.apigee.com/api-platform/security/oauth/working-scopes) and [Requesting access tokens
and authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens).

|---|---|
| **Default:** | No scope |
| **Presence:** | Optional |
| **Type:** | String |
| **Valid values:** | If used with Generate\* policies, a flow variable. If used with VerifyAccessToken, a space-separated list of scope names (strings). |
| **Used with grant types:** | - authorization_code - implicit - password - client_credentials - Can also be used with the GenerateAuthorizationCode and VerifyAccessToken operations. |

## \<State\> element

```
<State>request.queryparam.state</State>
```

In cases where the client app must send the state information to the authorization server,
this element lets you specify where Edge should look for the state values. For example, it could
be sent as a query parameter or in an HTTP header. The state value is typically used as a
security measure to prevent CSRF attacks.

For example `request.queryparam.state` indicates that the state should be
present as a query parameter, as, for example, `?state=HjoiuKJH32`. To require
the state in an HTTP header, for example, set this value
to `request.header.state`. See also See also [Requesting access tokens and authorization
codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens).

|---|---|
| **Default:** | No state |
| **Presence:** | Optional |
| **Type:** | String |
| **Valid values:** | Any flow variable accessible to the policy at runtime |
| **Used with grant types:** | - All - Can also be used with the GenerateAuthorizationCode operation |

## \<StoreToken\> element

```
 <StoreToken>true</StoreToken>
```

Set this element to `true` when the `<ExternalAuthorization>`
element is `true`. The `<StoreToken>` element tells Apigee Edge to
store the external access token. Otherwise, it will not be persisted.

|---|---|
| **Default:** | false |
| **Presence:** | Optional |
| **Type:** | Boolean |
| **Valid values:** | true or false |
| **Used with grant types:** | - authorization_code - password - client_credentials |

## \<SupportedGrantTypes\>/\<GrantType\>
element

```
<SupportedGrantTypes>
    <GrantType>authorization_code</GrantType>
    <GrantType>client_credentials</GrantType>
    <GrantType>implicit</GrantType>
    <GrantType>password</GrantType>
</SupportedGrantTypes>
```

Specifies the grant types supported by an OAuth token endpoint on Apigee Edge. An endpoint may
support multiple grant types (that is, a single endpoint can be configured to distribute access
tokens for multiple grant types.) For more on endpoints, see [Understanding OAuth
endpoints](https://docs.apigee.com/api-platform/security/oauth/configuring-oauth-endpoints-and-policies). The grant type is passed in token requests in a `grant_type`
parameter.

If no supported grant types are specified, then the only allowed grant types are
`authorization_code` and `implicit`. See also the [\<GrantType\>](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy#granttype) element (which is a higher-level element that is used to
specify where Apigee Edge should look for the `grant_type` parameter that is passed in
a client request. Edge will make sure that the value of the `grant_type` parameter
matches one of the supported grant types).

|---|---|
| **Default:** | authorization _code and implicit |
| **Presence:** | Required |
| **Type:** | String |
| **Valid values:** | - client_credentials - authorization_code - password - implicit |

## \<Tokens\>/\<Token\> element

Used with the ValidateToken and InvalidateToken operations. See also [Approving and
revoking access tokens](https://docs.apigee.com/api-platform/security/oauth/validating-and-invalidating-access-tokens). The \<Token\> element identifies the flow variable that defines
the source of the token to be revoked. If developers are expected to submit access tokens as
query parameters named `access_token`, for example,
use `request.queryparam.access_token`.

## \<UserName\> element

```
<UserName>request.queryparam.user_name</UserName>
```

**This element is used with the** **password grant type only** . With
the password grant type, user credentials (password and username) must be made available to the
OAuthV2 policy. The `<PassWord>` and `<UserName>` elements are
used to specify variables where Edge can find these values. If these elements are not specified,
the policy expects to find the values (by default) in form parameters named `username`
and `password`. If the values are not found, the policy throws an error. You can use
the `<PassWord>` and `<UserName>` elements to reference any
flow variable containing the credentials.

For example, you can pass the username in a query parameter and set the
`<UserName>` element like this:
`<UserName>request.queryparam.username</UserName>``.`To require
the username in an HTTP header, set this value
to `request.header.username`.

The OAuthV2 policy doesn't do anything else with these credential values; Edge is simply
verifying that they are present. It is up to the API developer to retrieve the values request and
send them to an identity provider before the token generation policy executes.

See also [Requesting access tokens
and authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens).

|---|---|
| **Default:** | request.formparam.username (a x-www-form-urlencoded and specified in the request body) |
| **Presence:** | Optional |
| **Type:** | String |
| **Valid values:** | Any variable setting. |
| **Used with grant types:** | password |

## Verifying access
tokens

Once a token endpoint is set up for an API proxy, a corresponding OAuthV2 policy that
specifies the `VerifyAccessToken` operation is attached to the Flow that exposes the
protected resource.

For example, to ensure that all requests to an API are authorized, the following policy
enforces access token verification:

```
<OAuthV2 name="VerifyOAuthAccessToken">
  <Operation>VerifyAccessToken</Operation>
</OAuthV2>
```

The policy is attached to the API resource to be protected. To ensure that all requests to an
API are verified, attach the policy to the ProxyEndpoint request PreFlow, as follows:

```
<PreFlow>
  <Request>
    <Step><Name>VerifyOAuthAccessToken</Name></Step>
  </Request>
</PreFlow>
```

The following optional elements can be used to override the default settings for the
VerifyAccessToken operation.

| Name | Description |
|---|---|
| Scope | A space-delimited list of scopes. Verification will succeed if at least one of the scopes listed is present in the access token. For example, the following policy will check the access token to ensure that it contains at least one of the scopes listed. If READ or WRITE is present, verification will succeed. ``` <OAuthV2 name="ValidateOauthScopePolicy"> <Operation>VerifyAccessToken</Operation> <Scope>READ WRITE</Scope> </OAuthV2> ``` |
| AccessToken | The variable where the access token is expected to be located. For example `request.queryparam.accesstoken`. By default, the access token is expected to be presented by the app in the Authorization HTTP header, according to the [OAuth 2.0 specification](https://tools.ietf.org/html/draft-ietf-oauth-v2-31). Use this setting if the access token is expected to be presented in a non-standard location, such as a query parameter, or an HTTP header with a name other than Authorization. |

See also [Verifying access
tokens](https://docs.apigee.com/api-platform/security/oauth/using-access-tokens) and [Requesting access tokens
and authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens).

## Specifying request variable locations

For each grant type, the policy makes assumptions about the location or required information
in request messages. These assumptions are based on 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 handling an authorization 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.

## Flow variables

The flow variables defined in this table are populated when the respective OAuth policies are
executed, and hence are available to other policies or applications executing in the API proxy
flow.

### VerifyAccessToken operation

The VerifyAccessToken operation executes, a large number of flow variables are populated
in the proxy's execution context. These variables give you properties related to the access
token, developer app, developer, and company. You can use an AssignMessage or JavaScript policy,
for example, to read any of these variables and use them as needed later in the flow. These
variables can also be useful for debugging purposes.

> [!NOTE]
> **Note:** API product variables will be populated automatically if the API products are configured with valid environment, proxies, and API resources (derived from the `proxy.pathsuffix`). Explicitly setting flow.resource.name variable is not required.
>
> Where the API products are not configured with valid environments and API proxies, then
> `flow.resource.name` must explicitly be set to populate API product variables in the
> flow. For details on product configuration, see [Using the Edge management
> API to Publish APIs](https://docs.apigee.com/api-platform/publish/using-edge-management-api-publish-apis).

**Token-specific variables**

| Variables | Description |
|---|---|
| `organization_name` | The name of the organization where the proxy is executing. |
| `developer.id` | The ID of the developer associated with the registered client app. |
| `developer.app.name` | The name of the developer associated with the registered client app. |
| `client_id` | The client ID of the registered client app. |
| `grant_type` | The grant type associated with the request. |
| `token_type` | The token type associated with the request. |
| `access_token` | The access token that is being verified. |
| `accesstoken.{custom_attribute}` | A named custom attribute in the access token. |
| `issued_at` | The date the access token was issued expressed in Unix epoch time in milliseconds. |
| `expires_in` | The expiration time for the access token. Expressed in **seconds** . Although the `ExpiresIn` element sets the expiration in milliseconds, in the token response and flow variables, the value is expresed in seconds. |
| `status` | The status of the access token (e.g., approved or revoked). |
| `scope` | The scope (if any) associated with the access token. |
| `apiproduct.<custom_attribute_name>` | A named custom attribute of the API product associated with the registered client app. |
| `apiproduct.name` | The name of the API product associated with the registered client app. |
| `revoke_reason` | (Apigee hybrid only) Indicates why the access token is revoked. Value can be `REVOKED_BY_APP`, `REVOKED_BY_ENDUSER`, `REVOKED_BY_APP_ENDUSER`, or `TOKEN_REVOKED`. |

**App-specific variables**

These variables are related to the Developer App that is associated with the token.

| Variables | Description |
|---|---|
| `app.name` |   |
| `app.id` |   |
| `app.accessType` |   |
| `app.callbackUrl` |   |
| `app.status` | approved or revoked |
| `app.scopes` |   |
| `app.appFamily` |   |
| `app.apiproducts` |   |
| `app.appParentStatus` |   |
| `app.appType` | For example: Developer |
| `app.appParentId` |   |
| `app.created_by` |   |
| `app.created_at` |   |
| `app.last_modified_at` |   |
| `app.last_modified_by` |   |
| `app.{custom_attributes}` | A named custom attribute of the registered client app. |

**Developer-specific variables**

If the app.appType is "Company", then company attributes are populated and if app.appType is
"Developer", then developer attributes are populated.

| Variables | Description |
|---|---|
| **Developer-specific variables** |   |
| `developer.id` |   |
| `developer.userName` |   |
| `developer.firstName` |   |
| `developer.lastName` |   |
| `developer.email` |   |
| `developer.status` | active or inactive |
| `developer.apps` |   |
| `developer.created_by` |   |
| `developer.created_at` |   |
| `developer.last_modified_at` |   |
| `developer.last_modified_by` |   |
| `developer.{custom_attributes}` | A named custom attribute of the developer. |

**Company-specific variables**

If the app.appType is "Company", then company attributes are populated and if app.appType is
"Developer", then developer attributes are populated.

| Variables | Description |
|---|---|
| `company.id` |   |
| `company.displayName` |   |
| `company.apps` |   |
| `company.appOwnerStatus` |   |
| `company.created_by` |   |
| `company.created_at` |   |
| `company.last_modified_at` |   |
| `company.last_modified_by` |   |
| `company.{custom_attributes}` | A named custom attribute of the company. |

### GenerateAuthorizationCode
operation

These variables are set when the GenerateAuthorizationCode operation executes
successfully:

**Prefix:** `oauthv2authcode.{policy_name}.{variable_name}`

**Example:** `oauthv2authcode.GenerateCodePolicy.code`

| Variable | Description |
|---|---|
| `code` | The authorization code generated when the policy executes. |
| `redirect_uri` | The redirect URI associated with the registered client app. |
| `scope` | The optional OAuth scope passed in the client request. |
| `client_id` | The client ID passed in the client request. |

### GenerateAccessToken and
RefreshAccessToken operations

These variables are set when the GenerateAccessToken and RefreshAccessToken operations execute
successfully. Note that refresh token variables do not apply for the client credentials grant
type flow.

**Prefix:** `oauthv2accesstoken.{policy_name}.{variable_name}`

**Example:** `oauthv2accesstoken.GenerateTokenPolicy.access_token`

| Variable name | Description |
|---|---|
| `access_token` | The access token that was generated. |
| `client_id` | The client ID of the developer app associated with this token. |
| `expires_in` | The expiry value for the token. See the [\<ExpiresIn\>](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy#expiresin) element for details. Note that in the response, **expires_in** is expressed in **seconds**. |
| `scope` | List of available scopes configured for the token. See [Working with OAuth2 scopes](https://docs.apigee.com/api-platform/security/oauth/working-scopes). |
| `status` | Either `approved` or `revoked`. |
| `token_type` | Is set to `BearerToken`. |
|   |   |
| `developer.email` | The email address of the registered developer who owns the developer app associated with the token. |
| `organization_name` | The org where the proxy executes. |
| `api_product_list` | A list of the products associated with the token's corresponding developer app. |
|   |   |
| `refresh_count` |   |
| `refresh_token` | The refresh token that was generated. Note that refresh tokens are not generated for the client credentials grant type. |
| `refresh_token_expires_in` | The lifespan of the refresh token, in seconds. |
| `refresh_token_issued_at` | This time value is the string representation of the corresponding 32-bit timestamp quantity. For example, 'Wed, 21 Aug 2013 19:16:47 UTC' corresponds to the timestamp value of 1377112607413. |
| `refresh_token_status` | Either `approved` or `revoked`. |

### GenerateAccessTokenImplicitGrant

These variables are set when the GenerateAccessTokenImplicit operation executes successfully
for the implicit grant type flow.

**Prefix:** `oauthv2accesstoken.{policy_name}.{variable_name}`

**Example:** `oauthv2accesstoken.RefreshTokenPolicy.access_token`

| Variable | Description |
|---|---|
| `oauthv2accesstoken.access_token` | The access token generated when the policy executes. |
| `oauthv2accesstoken.{policy_name}.expires_in` | The expiry value for the token, in seconds. See the [\<ExpiresIn\>](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy#expiresin) element for details. |

## Error reference


This section describes the fault codes and error messages that are returned and fault variables that are set by Edge when this policy triggers an error.
This information is important to know if you are developing fault rules to
handle faults. To learn more, see [What you need to know
about policy errors](https://docs.apigee.com/api-platform/fundamentals/what-you-need-know-about-policy-errors) and [Handling
faults](https://docs.apigee.com/api-platform/fundamentals/fault-handling).

### Runtime errors

These errors can occur when the policy executes.

> [!IMPORTANT]
> **Tip:** Use [API Monitoring](https://docs.apigee.com/api-monitoring) to investigate fault codes and diagnose issues faster. See [Set up a policy fault code alert](https://docs.apigee.com/api-monitoring/alerts-notifications#fault-code-alert) for an example. See [Fault code reference](https://docs.apigee.com/api-monitoring/fault-codes) for a complete list of all fault codes that you can handle with API Monitoring.

| Fault code | HTTP status | Cause | Thrown by operations |
|---|---|---|---|
| `steps.oauth.v2.access_token_expired` | 401 | The access token is expired. | VerifyAccessToken InvalidateToken |
| `steps.oauth.v2.access_token_not_approved` | 401 | The access token was revoked. | VerifyAccessToken |
| `steps.oauth.v2.apiresource_doesnot_exist` | 401 | The requested resource does not exist any of the API products associated with the access token. | VerifyAccessToken |
| `steps.oauth.v2.FailedToResolveAccessToken` | 500 | The policy expected to find an access token in a variable specified in the `<AccessToken>` element, but the variable could not be resolved. | GenerateAccessToken |
| `steps.oauth.v2.FailedToResolveAuthorizationCode` | 500 | The policy expected to find an authorization code in a variable specified in the `<Code>` element, but the variable could not be resolved. | GenerateAuthorizationCode |
| `steps.oauth.v2.FailedToResolveClientId` | 500 | The policy expected to find the Client ID in a variable specified in the `<ClientId>` element, but the variable could not be resolved. | GenerateAccessToken GenerateAuthorizationCode GenerateAccessTokenImplicitGrant RefreshAccessToken |
| `steps.oauth.v2.FailedToResolveRefreshToken` | 500 | The policy expected to find a refresh token in a variable specified in the `<RefreshToken>` element, but the variable could not be resolved. | RefreshAccessToken |
| `steps.oauth.v2.FailedToResolveToken` | 500 | The policy expected to find a token in a variable specified in the `<Tokens>` element, but the variable could not be resolved. | ValidateToken InvalidateToken |
| `steps.oauth.v2.InsufficientScope` | 403 | The access token presented in the request has a scope that does not match the scope specified in the verify access token policy. To learn about scope, see [Working with OAuth2 scopes](https://docs.apigee.com/api-platform/security/oauth/working-scopes). | VerifyAccessToken |
| `steps.oauth.v2.invalid_access_token` | 401 | The access token sent from the client is invalid. | VerifyAccessToken |
| `steps.oauth.v2.invalid_client` | 401 | This error name is returned when the `<GenerateResponse>` property of the policy is set to **true** and the client ID sent in the request is invalid. Check to be sure you are using the correct client key and secret values for the Developer App associated with your proxy. Typically, these values are sent as a Base64 encoded Basic Authorization header. **Note:** It is recommended that you change existing fault rule conditions to catch both the `invalid_client` and `InvalidClientIdentifier` names. See the [16.09.21 Release Notes](https://docs.apigee.com/release/notes/160921-apigee-edge-public-cloud-release-notes) for more information and an example. | GenerateAccessToken RefreshAccessToken |
| `steps.oauth.v2.InvalidRequest` | 400 | This error name is used for multiple different kinds of errors, typically for missing or incorrect parameters sent in the request. If `<GenerateResponse>` is set to `false`, use fault variables (described below) to retrieve details about the error, such as the fault name and cause. | GenerateAccessToken GenerateAuthorizationCode GenerateAccessTokenImplicitGrant RefreshAccessToken |
| `steps.oauth.v2.InvalidAccessToken` | 401 | The authorization header does not have the word "Bearer", which is required. For example: `Authorization: Bearer your_access_token` | VerifyAccessToken |
| `steps.oauth.v2.InvalidAPICallAsNoApiProductMatchFound` | 401 | The API proxy is not in the Product associated with the access token. **Tips:** Be sure that the product associated with the access token is configured correctly. For example, if you use wildcards in resource paths, be sure the wildcards are being used correctly. See [Create API products](https://docs.apigee.com/api-platform/publish/create-api-products) for details. See also [this Apigee Community post](https://discuss.google.dev/t/oauth2-0-access-token-verification-throws-invalid-api-call-as-no-apiproduct-match-found-error/17064) for more guidance on causes for this error. | VerifyAccessToken |
| `steps.oauth.v2.InvalidClientIdentifier` | 500 | This error name is returned when the `<GenerateResponse>` property of the policy is set to **false** and the client ID sent in the request is invalid. Check to be sure you are using the correct client key and secret values for the Developer App associated with your proxy. Typically, these values are sent as a Base64 encoded Basic Authorization header. <br /> **Note:** In this situation, this error used to be called `invalid_client`. It is recommended that you change existing fault rule conditions to catch both the `invalid_client` and `InvalidClientIdentifier` names. See the [16.09.21 Release Notes](https://docs.apigee.com/release/notes/160921-apigee-edge-public-cloud-release-notes) for more information and an example. | GenerateAccessToken RefreshAccessToken |
| `steps.oauth.v2.InvalidParameter` | 500 | The policy must specify either an access token or an authorization code, but not both. | GenerateAuthorizationCode GenerateAccessTokenImplicitGrant |
| `steps.oauth.v2.InvalidTokenType` | 500 | The `<Tokens>/<Token>` element requires you to specify the token type (for example, `refreshtoken`). If the client passes the wrong type, this error is thrown. | ValidateToken InvalidateToken |
| `steps.oauth.v2.MissingParameter` | 500 | The response type is `token`, but no grant types are specified. | GenerateAuthorizationCode GenerateAccessTokenImplicitGrant |
| `steps.oauth.v2.UnSupportedGrantType` | 500 | The client specified a grant type that is unsupported by the policy (not listed in the \<SupportedGrantTypes\> element). **Note:** There is currently a bug where unsupported grant type errors are not thrown correctly. If an unsupported grant type error occurs, the proxy does not enter the Error Flow, as expected. | GenerateAccessToken GenerateAuthorizationCode GenerateAccessTokenImplicitGrant RefreshAccessToken |

### Deployment errors

These errors can occur when you deploy a proxy containing this policy.

| Error name | Cause |
|---|---|
| `InvalidValueForExpiresIn` | For the `<ExpiresIn>` element, valid values are positive integers and `-1`. |
| `InvalidValueForRefreshTokenExpiresIn` | For the `<RefreshTokenExpiresIn>` element, valid values are positive integers and `-1`. |
| `InvalidGrantType` | An invalid grant type is specified in the `<SupportedGrantTypes>` element. See the policy reference for a list of valid types. |
| `ExpiresInNotApplicableForOperation` | Be sure that the operations specified in the \<Operations\> element support expiration. For example, the VerifyToken operation does not. |
| `RefreshTokenExpiresInNotApplicableForOperation` | Be sure that the operations specified in the \<Operations\> element support refresh token expiration. For example, the VerifyToken operation does not. |
| `GrantTypesNotApplicableForOperation` | Be sure that the grant types specified in \<SupportedGrantTypes\> are supported for the specified operation. |
| `OperationRequired` | You must specify an operation in this policy using the `<Operation>` element. **Note:** If the `<Operation>` element is missing, the UI throws a schema validation error. |
| `InvalidOperation` | You must specify a valid operation in this policy using the `<Operation>` element. **Note:** If the `<Operation>` element is invalid, the UI throws a schema validation error. |
| `TokenValueRequired` | You must specify a token `<Token>` value in the `<Tokens>` element. |

### Fault variables

These variables are set when this policy triggers an error at runtime.

> [!NOTE]
> **Note:** You an use these variables to create Fault Rule conditions. These variables are populated when an error occurs if **`<GenerateResponse>`** is set to **`false`** . If `<GenerateResponse>` is `true`, the policy returns a response to the client immediately if an error occurs -- the error flow is skipped and these variables are not populated. For more information, see [What you need to
> know about policy errors](https://docs.apigee.com/api-platform/fundamentals/what-you-need-know-about-policy-errors).

| Variables | Where | Example |
|---|---|---|
| `fault.name="fault_name"` | <var translate="no">fault_name</var> is the name of the fault, as listed in the [Runtime errors](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy#runtime-errors) table above. The fault name is the last part of the fault code. | `fault.name = "InvalidRequest"` |
| `oauthV2.policy_name.failed` | <var translate="no">policy_name</var> is the user-specified name of the policy that threw the fault. | `oauthV2.GenerateAccesstoken.failed = true` |
| `oauthV2.policy_name.fault.name` | <var translate="no">policy_name</var> is the user-specified name of the policy that threw the fault. | `oauthV2.GenerateAccesstoken.fault.name = InvalidRequest` **Note** : For the VerifyAccessToken operation, the fault name includes this suffix: `keymanagement.service` For example: `keymanagement.service.invalid_access_token` |
| `oauthV2.policy_name.fault.cause` | <var translate="no">policy_name</var> is the user-specified name of the policy that threw the fault. | `oauthV2.GenerateAccesstoken.cause = Required param : grant_type` |

### Example error response

These responses are sent back to the client if the `<GenerateResponse>`
element is **true**.

> [!NOTE]
> **Note:** For error handling, the best practice is to trap the `errorcode` part of the error response. Do not rely on the text in the `faultstring`, because it could change.

If `<GenerateResponse>` is **true** , the policy returns errors
in this format for operations that generate tokens and codes. For a complete list, see see
[OAuth HTTP error
response reference](https://docs.apigee.com/api-platform/reference/policies/oauth-http-status-code-reference).

```
{"ErrorCode" : "invalid_client", "Error" :"ClientId is Invalid"}
```

If `<GenerateResponse>` is **true** , the policy returns errors
in this format for verify and validate operations. For a complete list, see see [OAuth HTTP error
response reference](https://docs.apigee.com/api-platform/reference/policies/oauth-http-status-code-reference).

```
{  
   {  
      "fault":{  
         "faultstring":"Invalid Access Token",
         "detail":{  
            "errorcode":"keymanagement.service.invalid_access_token"
         }
      }
   }
```

### Example fault rule

```
<FaultRule name=OAuthV2 Faults">
    <Step>
        <Name>AM-InvalidClientResponse</Name>
        <Condition>(fault.name = "invalid_client") OR (fault.name = "InvalidClientIdentifier")</Condition>
    </Step>
    <Step>
        <Name>AM-InvalidTokenResponse</Name>
        <Condition>(fault.name = "invalid_access_token")</Condition>
    </Step>
    <Condition>(oauthV2.failed = true) </Condition>
</FaultRule>
```

<br />

## Policy schema

Each policy type is defined by an XML schema (`.xsd`). For reference, [policy
schemas](https://github.com/apigee/api-platform-samples/tree/master/schemas/policy) are available on GitHub.

## Working with the default OAuth
configuration

Each organization (even a free trial org) on Apigee Edge is provisioned with an OAuth token
endpoint. The endpoint is preconfigured with policies in the API proxy
called **oauth** . You can begin using the token endpoint as soon as you create
an account on [Apigee Edge](https://accounts.apigee.com/accounts/sign_up). For
details, see [Understanding OAuth
endpoints](https://docs.apigee.com/api-platform/security/oauth/configuring-oauth-endpoints-and-policies).

## Purging access tokens

By default, OAuth2 tokens are purged from the Apigee Edge system 3 days (259200 seconds)
after both the access token and refresh token (if it exists) have expired. In some cases,
you may want to change this default. For example, you may want to shorten the purge time to
save disk space if a large number of tokens are being generated.

If you are on **Edge for Private Cloud**, you can change this default by setting
organization properties as explained in this section. (The 3-day purge of expired tokens
applies to Edge for Private Cloud version 4.19.01 and later. For earlier versions, the
default purge interval is 180 days.)

### Updating purge settings for Edge Private Cloud 4.16.01 and later versions

**Note:** Only tokens generated **after** these settings are
applied are affected; the settings do not apply to tokens that were generated earlier.

> [!NOTE]
> **Private Cloud:**
>
> 1. Open this file for editing:
>
>    ```
>    /opt/apigee/customer/application/message-processor.properties
>    ```
> 2. Add the following property to set the number of seconds to wait before purging a token after it expires:
>
>    ```
>    conf_keymanagement_oauth.access.token.purge.after.seconds=<number of seconds>
>    ```
> 3. Restart the message processor. For example:
>
>    ```
>    /opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
>    ```
>
> If the access token never expires, then it will never be purged. You can set token expiration in the OAuthV2 policy using the `<ExpiresIn>` and `<RefreshTokenExpiresIn>` attributes.

### Updating purge
settings for Edge Private Cloud 4.15.07

**Note:** Only tokens generated **after** these settings are applied
are affected; the settings do not apply to tokens that were generated earlier.

> [!NOTE]
> **Private Cloud:**
>
> 1. Set positive values for the `<ExpiresIn>` and
>    `<RefreshTokenExpiresIn>` attributes in the OAuthV2 policy. Values are in
>    milliseconds. For example:
>
>    ```
>    <ExpiresIn>1000</ExpiresIn>
>    <RefreshTokenExpiresIn>10000</RefreshTokenExpiresIn>
>    ```
> 2. Redeploy the proxy.
>
> 3. Use this API to update the token purge properties for your organization:
>
>    ```
>    POST https://<host-name>/v1/organizations/<org-name>
>    ```
>
>    Payload:
>
>    ```
>    <Organization name="AutomationOrganization">
>     <Description>Desc</Description>
>     <Properties>
>         <Property name="keymanagement.oauth20.access.token.purge">true</Property>
>         <Property name="keymanagement.oauth20.access.token.purge.after.seconds">120</Property>
>     </Properties>
>    </Organization>
>    ```
> 4. Restart the message processor. For example:
>
>    ```
>    /opt/apigee/apigee-service/bin/apigee-service edge-message-processor restart
>    ```
>
>    This API sets the token purge property to true for the organization called
>    AutomationOrganization. In this case, the access token will be purged from the database 120
>    seconds after both the token and refresh token expire.
>
> See also [\<ExpiresIn\> element](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy#expiresin).

## Non-RFC-compliant behavior


The OAuthV2 policy returns a token response that
contains certain non-[RFC-compliant](https://tools.ietf.org/html/rfc6749) properties.
The following table shows the non-compliant
properties returned by the OAuthV2 policy and the corresponding compliant properties.

> [!NOTE]
> **NOTE** : If you require that these elements be compliant, you can create a policy, such as a JavaScript or AssignMessage policy, to transform the policy output into a compliant format. For example, see the solution outlined in [Error: Access denied when calling proxy](https://www.drupal.org/docs/8/modules/apigee-api-catalog/use-smartdocs-with-apigee-edge#s-error-access-denied-when-calling-proxy) or the [sample OAuth2 solution](https://github.com/kurtkanaskie/oauth-compliant) provided on GitHub.

| OAuthV2 returns: | The RFC-compliant property is: |
|---|---|
| `"token_type":"BearerToken"` | `"token_type":"Bearer"` |
| `"expires_in":"3600"` | `"expires_in":3600` (The compliant value is a number, not a string.) |

Also, the error response for an expired refresh token when `grant_type = refresh_token` is:

```
{"ErrorCode" : "InvalidRequest", "Error" :"Refresh Token expired"}
```


However, the RFC-compliant response is:

```
{"error" : "invalid_grant", "error_description" :"refresh token expired"}
```

## Related topics

- [Introduction to OAuth
  2.0](https://docs.apigee.com/api-platform/security/oauth/oauth-introduction)