You're viewing **Apigee Edge** documentation.  
[Go to the
**Apigee X** documentation](http://cloud.google.com/apigee/docs/api-platform/security/oauth/access-tokens). info

In this topic, we show you how to request access tokens and authorization codes, configure
OAuth 2.0 endpoints, and configure policies **for each supported grant
type**.

> [!NOTE]
> **Note:** These examples show the most basic configurations possible. In particular, the OAuthV2 policy includes many optional configurable elements that are not shown in this topic. For more information on those elements, see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

## Sample code

For your convenience, the policies and endpoints discussed in this topic are available on
GitHub in the [oauth-doc-examples](https://github.com/apigee/api-platform-samples/tree/master/doc-samples/oauth-doc-examples) project
in the Apigee api-platform-samples repository. You can deploy the sample code and try
out the sample requests shown in this topic. See the project README for details.

## Requesting an access token:
authorization code grant type

This section explains how to request an access token using the authorization code grant type
flow. For an introduction to OAuth 2.0 grant types, see [Introduction to OAuth 2.0](https://docs.apigee.com/api-platform/security/oauth/oauth-introduction).

> [!NOTE]
> **Note:** This flow requires you to obtain an authorization code first. See [Requesting authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens#requestAuthCode) below.
>
> For information on encoding the basic authentication header in the following call, see
> "[Encoding basic authentication credentials](https://docs.apigee.com/api-platform/security/oauth/access-tokens#encoding)".

### **Sample
request**

```
$ curl -i -H 'Content-Type: application/x-www-form-urlencoded' \
   -H 'Authorization: Basic c3FIOG9vSGV4VHo4QzAyg5T1JvNnJoZ3ExaVNyQWw6WjRsanRKZG5lQk9qUE1BVQ' \
   -X POST 'https://docs-test.apigee.net/oauth/accesstoken' \
   -d 'code=I9dMGHAN&grant_type=authorization_code&redirect_uri=http://example-callback.com'
```

### **Required
parameters**

By default, these parameters must be `x-www-form-urlencoded` and specified in the
request body (as shown in the sample above); however, it is possible to change this default by
configuring the `<GrantType>`, `<Code>`, and
`<RedirectUri>` elements in the OAuthV2 policy that is attached to this
`/accesstoken` endpoint. For details, see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

- **grant_type** - Must be set to the value `authorization_code`.
- **code** - The authorization code received from the `/authorize` endpoint (or whatever you choose to name it). To request an access token in the authorization code grant type flow, you must first obtain an authorization code. See [Requesting authorization codes](https://docs.apigee.com/api-platform/security/oauth/access-tokens#requestAuthCode) below. See also [Implementing
  the authorization code grant type](https://docs.apigee.com/api-platform/security/oauth/oauth-v2-policy-authorization-code-grant-type).
- **redirect_uri** - You must provide this parameter if the `redirect_uri` parameter was included in the prior authorization code request. If the `redirect_uri` parameter was not included in the authorization code request, and if you do not provide this parameter, then this policy uses the value of the Callback URL that was provided when the developer app was registered.

### **Optional
parameters**

- **state** - A string that will be sent back with the response. Typically used to prevent cross-site request forgery attacks.
- **scope** - Allows you to filter the list of API products with which the minted token can be used. For detailed information on scope, see [Working with OAuth2 scopes](https://docs.apigee.com/api-platform/security/oauth/working-scopes).

### **Authentication**

You must pass the Client ID and Client Secret either as a Basic Authentication header
(Base64-encoded) or as form parameters `client_id` and `client_secret`. You
obtain these values from a registered developer app. See also "[Encoding basic
authentication credentials](https://docs.apigee.com/api-platform/security/oauth/access-tokens#encoding)".

### Sample endpoint

Here's a sample endpoint configuration for generating an access token. It'll execute the
GenerateAccessToken policy, which must be configured to support the authorization_code grant
type.

```
...
       <Flow name="generate-access-token">
            <Description>Generate a token</Description>
            <Request>
                <Step>
                    <Name>GenerateAccessToken</Name>
                </Step>
            </Request>
            <Response/>
            <Condition>(proxy.pathsuffix MatchesPath "/token") and (request.verb = "POST")</Condition>
        </Flow>
...
```

### Sample policy

This is a basic GenerateAccessToken policy that is configured to accept the
`authorization_code` grant type. For information on optional configuration elements
that you can configure with this policy, see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

```
<OAuthV2 name="GenerateAccessToken">
    <Operation>GenerateAccessToken</Operation>
    <ExpiresIn>1800000</ExpiresIn>
    <RefreshTokenExpiresIn>86400000</RefreshTokenExpiresIn>
    <SupportedGrantTypes>
      <GrantType>authorization_code</GrantType>
    </SupportedGrantTypes>
    <GenerateResponse enabled="true"/>
</OAuthV2>
```

### **Returns**

With `<GenerateResponse>` enabled, the policy returns a JSON response that
includes the access token, as shown below. The `authorization_code` grant type creates
an access token and a refresh tokens, so a response might look like this:

```
{
    "issued_at": "1420262924658",
    "scope": "READ",
    "application_name": "ce1e94a2-9c3e-42fa-a2c6-1ee01815476b",
    "refresh_token_issued_at": "1420262924658",
    "status": "approved",
    "refresh_token_status": "approved",
    "api_product_list": "[PremiumWeatherAPI]",
    "expires_in": "1799", //--in seconds
    "developer.email": "tesla@weathersample.com",
    "organization_id": "0",
    "token_type": "BearerToken",
    "refresh_token": "fYACGW7OCPtCNDEnRSnqFlEgogboFPMm",
    "client_id": "5jUAdGv9pBouF0wOH5keAVI35GBtx3dT",
    "access_token": "2l4IQtZXbn5WBJdL6EF7uenOWRsi",
    "organization_name": "docs",
    "refresh_token_expires_in": "86399", //--in seconds
    "refresh_count": "0"
}
```

> [!NOTE]
> **Note:** Yes, it's kind of unusual to specify the expiry values in milliseconds in the policy, but receive them in seconds in the response payload. We are aware.

If `<GenerateResponse>` is set to false, the policy does not return a
response. Instead, it populates the following set of flow variables with data pertaining to the
access token grant.

```
oauthv2accesstoken.{policy-name}.access_token
oauthv2accesstoken.{policy-name}.expires_in //--in seconds
oauthv2accesstoken.{policy-name}.refresh_token
oauthv2accesstoken.{policy-name}.refresh_token_expires_in //--in seconds
oauthv2accesstoken.{policy-name}.refresh_token_issued_at
oauthv2accesstoken.{policy-name}.refresh_token_status
```

For example:

```
oauthv2accesstoken.GenerateAccessToken.access_token
oauthv2accesstoken.GenerateAccessToken.expires_in
oauthv2accesstoken.GenerateAccessToken.refresh_token
oauthv2accesstoken.GenerateAccessToken.refresh_token_expires_in
oauthv2accesstoken.GenerateAccessToken.refresh_token_issued_at
oauthv2accesstoken.GenerateAccessToken.refresh_token_status
```

## Requesting an access token: client
credentials grant type

This section explains how to request an access token using the client credentials grant type
flow. For an introduction to OAuth 2.0 grant types, see [Introduction to OAuth 2.0](https://docs.apigee.com/api-platform/security/oauth/oauth-introduction).

### **Sample
request**

For information on encoding the basic authentication header in the following call, see
"[Encoding basic authentication credentials](https://docs.apigee.com/api-platform/security/oauth/access-tokens#encoding)".

```
$ curl -i -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Authorization: Basic c3FIOG9vSGV4VHoAyg5T1JvNnJoZ3ExaVNyQWw6WjRsanRKZG5lQk9qUE1BVQ' \
  -X POST 'https://docs-test.apigee.net/oauth/accesstoken' \
  -d 'grant_type=client_credentials'
```

### **Required
parameters**

By default, the required grant_type parameter must be `x-www-form-urlencoded` and
specified in the request body (as shown in the sample above); however, it is possible to change
this default by configuring the `<GrantType>` element in the OAuthV2 policy that
is attached to this `/accesstoken` endpoint. For example, you could elect to pass the
parameter in a query parameter. For details, see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

- **grant_type** - Must be set to the value `client_credentials`.

### **Optional
parameters**

- **state** - A string that will be sent back with the response. Typically used to prevent cross-site request forgery attacks.
- **scope** - Allows you to filter the list of API products with which the minted token can be used. For detailed information on scope, see [Working with OAuth2 scopes](https://docs.apigee.com/api-platform/security/oauth/working-scopes).

### **Authentication**

You must pass the Client ID and Client Secret either as a Basic Authentication header
(Base64-encoded) or as form parameters `client_id` and
`client_secret`. You obtain these values from the registered developer app
associated with the request. See also "[Encoding basic authentication
credentials](https://docs.apigee.com/api-platform/security/oauth/access-tokens#encoding)".

### Sample endpoint

Here's a sample endpoint configuration for generating an access token. It'll execute the
GenerateAccessToken policy, which must be configured to support the client_credentials grant
type.

```
...
       <Flow name="generate-access-token">
            <Request>
                <Step>
                    <Name>GenerateAccessToken</Name>
                </Step>
            </Request>
            <Response/>
            <Condition>(proxy.pathsuffix MatchesPath "/token") and (request.verb = "POST")</Condition>
        </Flow>
...
```

### Sample policy

This is a basic GenerateAccessToken policy that is configured to accept the
`client_credentials` grant type. For information on optional configuration elements
that you can configure with this policy, see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

```
<OAuthV2 name="GenerateAccessToken">
    <Operation>GenerateAccessToken</Operation>
    <ExpiresIn>1800000</ExpiresIn> <!-- 30 minutes -->
    <SupportedGrantTypes>
      <GrantType>client_credentials</GrantType>
    </SupportedGrantTypes>
    <GenerateResponse enabled="true"/>
</OAuthV2>
```

### **Returns**

With `<GenerateResponse>` enabled, the policy returns a JSON response. Note
that with the `client_credentials` grant type, refresh tokens are not supported. Only
an access token is minted. For example:

```
{
    "issued_at": "1420260525643",
    "application_name": "ce1e94a2-9c3e-42fa-a2c6-1ee01815476b",
    "scope": "READ",
    "status": "approved",
    "api_product_list": "[PremiumWeatherAPI]",
    "expires_in": "1799", //--in seconds
    "developer.email": "tesla@weathersample.com",
    "organization_id": "0",
    "token_type": "BearerToken",
    "client_id": "5jUAdGv9pBouF0wOH5keAVI35GBtx3dT",
    "access_token": "XkhU2DFnMGIVL2hvsRHLM00hRWav",
    "organization_name": "docs"
}
```

If `<GenerateResponse>` is set to false, the policy does not return a
response. Instead, it populates the following set of flow variables with data pertaining to the
access token grant.

```
oauthv2accesstoken.{policy-name}.access_token
oauthv2accesstoken.{policy-name}.expires_in //--in seconds
```

For example:

```
oauthv2accesstoken.GenerateAccessToken.access_token
oauthv2accesstoken.GenerateAccessToken.expires_in     //--in seconds
```

## Requesting an access token: password grant type

This section explains how to request an access token using the resource owner password
credentials (password) grant type flow. For an introduction to OAuth 2.0 grant types, see
[Introduction to OAuth 2.0](https://docs.apigee.com/api-platform/security/oauth/oauth-introduction).

For more details on the password grant type, including a 4-minute video showing how to
implement it, see [Implementing the password
grant type](https://docs.apigee.com/api-platform/security/oauth/implementing-password-grant-type).

### **Sample
request**

For information on encoding the basic authentication header in the following call, see
"[Encoding basic authentication credentials](https://docs.apigee.com/api-platform/security/oauth/access-tokens#encoding)".

```
$ curl -i -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Authorization: Basic c3FIOG9vSGV4VHo4QzAySVg5T1JvNnJoZ3ExaVNyQWw6WjRsanRKZG5lQk9qUE1BVQ' \
  -X POST https://docs-test.apigee.net/oauth/token \
  -d 'grant_type=password&username=the-user-name&password=the-users-password'
```

### **Required
parameters**

By default, these parameters must be `x-www-form-urlencoded` and specified in the
request body (as shown in the sample above); however, it is possible to change this default by
configuring the `<GrantType>`, `<Username>`, and
`<Password>` elements in the OAuthV2 policy that is attached to this
`/token` endpoint. For details, see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

User credentials are typically validated against a credential store using an LDAP or
JavaScript policy.

- **grant_type** - Must be set to the value `password`.
- **username** - The resource owner's user name.
- **password** - The resource owner's password.

### **Optional
parameters**

- **state** - A string that will be sent back with the response. Typically used to prevent cross-site request forgery attacks.
- **scope** - Allows you to filter the list of API products with which the minted token can be used. For detailed information on scope, see [Working with OAuth2 scopes](https://docs.apigee.com/api-platform/security/oauth/working-scopes).

### **Authentication**

You must pass the Client ID and Client Secret either as a Basic Authentication header
(Base64-encoded) or as form parameters `client_id` and
`client_secret`. You obtain these values from the registered developer app
associated with the request. See also "[Encoding basic authentication
credentials](https://docs.apigee.com/api-platform/security/oauth/access-tokens#encoding)".

### Sample endpoint

Here's a sample endpoint configuration for generating an access token. It'll execute the
GenerateAccessToken policy, which must be configured to support the password grant type.

```
...
       <Flow name="generate-access-token">
            <Request>
                <Step>
                    <Name>GenerateAccessToken</Name>
                </Step>
            </Request>
            <Response/>
            <Condition>(proxy.pathsuffix MatchesPath "/token") and (request.verb = "POST")</Condition>
        </Flow>
...
```

### Sample policy

This is a basic GenerateAccessToken policy that is configured to accept the password grant
type. For information on optional configuration elements that you can configure with this policy,
see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

```
<OAuthV2 name="GenerateAccessToken">
    <Operation>GenerateAccessToken</Operation>
    <ExpiresIn>1800000</ExpiresIn> <!-- 30 minutes -->
    <RefreshTokenExpiresIn>28800000</RefreshTokenExpiresIn> <!-- 8 hours -->
    <SupportedGrantTypes>
      <GrantType>password</GrantType>
    </SupportedGrantTypes>
    <GenerateResponse enabled="true"/>
</OAuthV2>
```

### **Returns**

With `<GenerateResponse>` enabled, the policy returns a JSON response. Note
that with the password grant type, both an access token and refresh token are minted. For
example:

```
{
    "issued_at": "1420258685042",
    "scope": "READ",
    "application_name": "ce1e94a2-9c3e-42fa-a2c6-1ee01815476b",
    "refresh_token_issued_at": "1420258685042",
    "status": "approved",
    "refresh_token_status": "approved",
    "api_product_list": "[PremiumWeatherAPI]",
    "expires_in": "1799", //--in seconds
    "developer.email": "tesla@weathersample.com",
    "organization_id": "0",
    "token_type": "BearerToken",
    "refresh_token": "IFl7jlijYuexu6XVSSjLMJq8SVXGOAAq",
    "client_id": "5jUAdGv9pBouF0wOH5keAVI35GBtx3dT",
    "access_token": "I6daIgMSiUgYX1K2qgQWPi37ztS6",
    "organization_name": "docs",
    "refresh_token_expires_in": "28799", //--in seconds
    "refresh_count": "0"
}
```

If `<GenerateResponse>` is set to false, the policy does not return a
response. Instead, it populates the following set of flow variables with data pertaining to the
access token grant.

```
oauthv2accesstoken.{policy-name}.access_token
oauthv2accesstoken.{policy-name}.expires_in   //--in seconds
oauthv2accesstoken.{policy-name}.refresh_token
oauthv2accesstoken.{policy-name}.refresh_token_expires_in  //--in seconds
oauthv2accesstoken.{policy-name}.refresh_token_issued_at
oauthv2accesstoken.{policy-name}.refresh_token_status
```

For example:

```
oauthv2accesstoken.GenerateAccessToken.access_token
oauthv2accesstoken.GenerateAccessToken.expires_in
oauthv2accesstoken.GenerateAccessToken.refresh_token
oauthv2accesstoken.GenerateAccessToken.refresh_token_expires_in
oauthv2accesstoken.GenerateAccessToken.refresh_token_issued_at
oauthv2accesstoken.GenerateAccessToken.refresh_token_status
```

## Requesting an access token: implicit grant
type

This section explains how to request an access token using the implicit grant type flow. For
an introduction to OAuth 2.0 grant types, see [Introduction to OAuth 2.0](https://docs.apigee.com/api-platform/security/oauth/oauth-introduction).

### **Sample
request**

```
$ curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' \
  'https://docs-test.apigee.net/oauth/implicit?response_type=token&client_id=ABC123&redirect_uri=http://callback-example.com'
```

### **Required
parameters**

By default, these parameters must be query parameters (as shown in the sample above); however,
it is possible to change this default by configuring the `<ResponseType>`,
`<ClientId>`, and `<RedirectUri>` elements in the OAuthV2
policy that is attached to this `/token` endpoint. For details, see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

User credentials are typically validated against a credential store using an LDAP service
callout or JavaScript policy.

- **response_type** - Must be set to the value `token`.
- **client_id** - The client ID of a registered developer app.
- **redirect_uri** - This parameter is mandatory if a Callback URI was not provided when the client developer app was registered. If a Callback URL was provided at client registration, it will be compared to this value and must match exactly.

### **Optional
parameters**

- **state** - A string that will be sent back with the response. Typically used to prevent cross-site request forgery attacks.
- **scope** - Allows you to filter the list of API products with which the minted token can be used. For detailed information on scope, see [Working with OAuth2 scopes](https://docs.apigee.com/api-platform/security/oauth/working-scopes).

### **Authentication**

The implicit grant does not require basic authentication. You do need to pass a client ID as a
request parameter, as explained here.

### Sample endpoint

Here's a sample endpoint configuration for generating an access token. It'll execute the
GenerateAccessTokenImplicitGrant policy.

```
...
       <Flow name="generate-access-token-implicit">
            <Request>
                <Step>
                    <Name>GenerateAccessTokenImplicitGrant</Name>
                </Step>
            </Request>
            <Response/>
            <Condition>(proxy.pathsuffix MatchesPath "/implicit") and (request.verb = "POST")</Condition>
        </Flow>
...
```

### Sample policy

This is a basic GenerateAccessTokenImplicitGrant policy that processes token requests for the
implicit grant type flow. For information on optional configuration elements that you can
configure with this policy, see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

```
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 name="GenerateAccessTokenImplicit">
    <DisplayName>GenerateAccessTokenImplicit</DisplayName>
    <Operation>GenerateAccessTokenImplicitGrant</Operation>
    <GenerateResponse enabled="true"/>
</OAuthV2>
```

### **Returns**

With `<GenerateResponse>` enabled, the policy returns a 302 Location redirect
in the response header. The redirect points to the URL specified in the `redirect_uri`
parameter and is appended with the access token and token expiration time. Note that the implicit
grant type does not support refresh tokens. For example:

```
https://callback-example.com#expires_in=1799&access_token=In4dKm4ueoGZRbIYJhC9yZCmTFw5
```

If `<GenerateResponse>` is set to false, the policy does not return a
response. Instead, it populates the following set of flow variables with data pertaining to the
access token grant.

```
oauthv2accesstoken.{policy-name}.access_token
oauthv2accesstoken.{policy-name}.expires_in  //--in seconds
```

For example:

```
oauthv2accesstoken.GenerateAccessToken.access_token
oauthv2accesstoken.GenerateAccessToken.expires_in   //--in seconds
```

## Requesting an authorization code

If you're using the authorization code grant type flow, you need to obtain an authorization
code before you can request an access token.

### **Sample request**

```
$ curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' \
  'http://myorg-test.apigee.net/oauth/authorize?client_id={consumer_key}&response_type=code'
```

where an OAuthV2 GenerateAuthorizationCode policy is attached at the
`/oauth/authorize` proxy endpoint (see the sample endpoint below).

### **Required
parameters**

By default, these parameters must be query parameters (as shown in the sample above); however,
it is possible to change this default by configuring the `<ResponseType>`,
`<ClientId>`, and `<RedirectUri>` elements in the OAuthV2
policy that is attached to this `/authorize` endpoint. For details, see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

> [!NOTE]
> **Note:** The authorization code flow takes place between a third-party user authentication service and Apigee Edge. The intent of the authorization code grant type flow is that the client app never sees the user's credentials for the resource server.

> [!NOTE]
> **Note:** For a detailed look at this flow, see [Implementing
> the authorization code grant type](https://docs.apigee.com/api-platform/security/oauth/oauth-v2-policy-authorization-code-grant-type).

- **response_type** - Must be set to the value `code`.
- **client_id** - The client ID of a registered developer app.

### **Optional
parameters**

- **redirect_uri** - If a full (not partial) Callback URI is specified in the registered client app, this parameter is optional; otherwise, it is required. The callback is the URL where Edge sends the newly minted auth code. See also [Register apps and manage API
  keys](https://docs.apigee.com/api-platform/publish/creating-apps-surface-your-api).
- **state** - A string that will be sent back with the response. Typically used to prevent cross-site request forgery attacks.
- **scope** - Allows you to filter the list of API products with which the minted token can be used. For detailed information on scope, see [Working with OAuth2 scopes](https://docs.apigee.com/api-platform/security/oauth/working-scopes).

### **Authentication**

Does not require basic authentication, however the client ID of the registered client app must
be supplied in the request.

### Sample endpoint

Here's a sample endpoint configuration for generating an authorization code:

```
<OAuthV2 name="GenerateAuthorizationCode">
  <Operation>GenerateAuthorizationCode</Operation>
    <!--
    ExpiresIn, in milliseconds. The ref is optional. The explicitly specified
    value is the default, when the variable reference cannot be resolved.
        60000 = 1 minute
       120000 = 2 minutes
    -->
  <ExpiresIn>60000</ExpiresIn>
  <GenerateResponse enabled="true"/>
</OAuthV2>
```

### Sample policy

This is a basic GenerateAuthorizationCode policy. For information on optional configuration
elements that you can configure with this policy, see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

```
<OAuthV2 name="GenerateAuthorizationCode">
    <Operation>GenerateAuthorizationCode</Operation>
    <GenerateResponse enabled="true"/>
</OAuthV2>
```

### **Returns**

With `<GenerateResponse>` enabled, the policy returns `?code`
query parameter to the `redirect_uri` (Callback URI) location with the authorization
code attached. It is sent via a 302 browser redirect with the URL in the Location header of the
response. For example: `?code=123456`.

If `<GenerateResponse>` is set to `false`, the policy does not
return a response. Instead, it populates the following set of flow variables with data pertaining
to the authorization code.

```
oauthv2authcode.{policy-name}.code
oauthv2authcode.{policy-name}.scope
oauthv2authcode.{policy-name}.redirect_uri
oauthv2authcode.{policy-name}.client_id
```

For example:

```
oauthv2authcode.GenerateAuthorizationCode.code
oauthv2authcode.GenerateAuthorizationCode.scope
oauthv2authcode.GenerateAuthorizationCode.redirect_uri
oauthv2authcode.GenerateAuthorizationCode.client_id
```

> [!NOTE]
> **Note:** You can also set custom attributes in the OAuthV2 policy. Custom attributes will be returned in the same format pattern as the other variables: `oauthv2.{policy_name}.{attribute_name}`. When you generate an access token from the auth code, the access token will inherit any custom variables set in the auth code. See also [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

## Refreshing an access token

A refresh token is a credential you use to obtain an access token, typically after the access
token has expired or becomes invalid. A refresh token is returned in the response when you
receive an access token.

> [!NOTE]
> **Note:** Existing attributes in an access token cannot be appended/deleted/modified during the `RefreshAccessToken` operation. Values inside the element are not processed in the `RefreshAccessToken` operation. Use `SetOAuthV2Info` policy to update the attributes.

To request a new access token using a refresh token:

### **Sample request**

For information on encoding the basic authentication header in the following call, see
"[Encoding basic authentication credentials](https://docs.apigee.com/api-platform/security/oauth/access-tokens#encoding)".

```
$ curl -X POST \
  -H "Content-type: application/x-www-form-urlencoded" \
  -H 'Authorization: Basic c3FIOG9vSGV4VHo4QzAyg5T1JvNnJoZ3ExaVNyQWw6WjRsanRKZG5lQk9qUE1BVQ' \
  https://myorg-test.apigee.net/my_oauth_endpoint/refresh_accesstoken \
  -d 'grant_type=refresh_token&refresh_token=my-refresh-token'
```

### **Required parameters**

- **grant_type** - Must be set to the value `refresh_token`.
- **refresh_token** - The refresh token associated with the access token you wish to renew.

By default, the policy looks for these as `x-www-form-urlencoded` parameters
specified in the request body, as shown in the example above. To configure an alternate location
for these inputs, you can use the `<GrantType>` and
`<RefreshToken>` elements in the OAuthV2 policy. For details, see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

### **Optional parameters**

- **state** - A string that will be sent back with the response. Typically used to prevent cross-site request forgery attacks.
- **scope** - Allows you to filter the list of API products with which the minted token can be used. For detailed information on scope, see [Working with OAuth2 scopes](https://docs.apigee.com/api-platform/security/oauth/working-scopes).

### **Authentication**

- **client_id**
- **client_secret**

You must pass the Client ID and Client Secret either as a Basic Authentication header
(Base64-encoded) or as form parameters `client_id` and `client_secret`. See
also "[Encoding basic authentication credentials](https://docs.apigee.com/api-platform/security/oauth/access-tokens#encoding)".

When refreshing an access token, there is no re-authentication of the user.

Here's a sample endpoint configuration for generating an access token using a refresh token.
It'll execute the RefreshAccessToken policy.

```
 ...
       <Flow name="generate-refresh-token">
            <Request>
                <Step>
                    <Name>RefreshAccessToken</Name>
                </Step>
            </Request>
            <Response/>
            <Condition>(proxy.pathsuffix MatchesPath "/refresh") and (request.verb = "POST")</Condition>
       </Flow>
...
```

### Sample policy

This is a basic RefreshAccessToken policy that is configured to accept the
`refresh_token` grant type. For information on optional configuration elements that
you can configure with this policy, see [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy).

```
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<OAuthV2 name="RefreshAccessToken">
    <Operation>RefreshAccessToken</Operation>
    <GenerateResponse enabled="true"/>
    <ExpiresIn>1800000</ExpiresIn> <!-- 30 minutes -->
    <RefreshTokenExpiresIn>28800000</RefreshTokenExpiresIn> <!-- 8 hours -->
</OAuthV2>
```

### **Returns**

With `<GenerateResponse>` enabled, the policy returns a JSON response
containing the new access token. The `refresh_token` grant type supports minting both
access and new refresh tokens. For example:

```
{
    "issued_at": "1420301470489",
    "application_name": "ce1e94a2-9c3e-42fa-a2c6-1ee01815476b",
    "scope": "READ",
    "refresh_token_issued_at": "1420301470489",
    "status": "approved",
    "refresh_token_status": "approved",
    "api_product_list": "[PremiumWeatherAPI]",
    "expires_in": "1799", //--in seconds
    "developer.email": "tesla@weathersample.com",
    "token_type": "BearerToken",
    "refresh_token": "8fKDHLryAD9KFBsrpixlq3qPJnG2fdZ5",
    "client_id": "5jUAdGv9pBouF0wOH5keAVI35GBtx3dT",
    "access_token": "jmZ2Hqv3iNsABUtAAsfWR3QGNctw",
    "organization_name": "docs",
    "refresh_token_expires_in": "28799", //--in seconds
    "refresh_count": "2"
}
```

> [!NOTE]
> **Note:** The expiry of the access token and the refresh token noted in the response are 1 second less than specified in the policy configuration. This is due to transit time, and a margin of safety. And yes, it's kind of unusual to specify the expiry values in milliseconds in the policy, but receive them in seconds in the response payload. We are aware.

You should know that after a new refresh token is minted, the original is no longer valid.

The above response is what you get if `<GenerateResponse>` is set to true.
If `<GenerateResponse>` is set to false, the policy does not return a response.
Instead, it populates the following set of context (flow) variables with data pertaining to the
access token grant.

```
oauthv2accesstoken.{policy-name}.access_token
oauthv2accesstoken.{policy-name}.expires_in   //--in seconds
oauthv2accesstoken.{policy-name}.refresh_token
oauthv2accesstoken.{policy-name}.refresh_token_expires_in  //--in seconds
oauthv2accesstoken.{policy-name}.refresh_token_issued_at
oauthv2accesstoken.{policy-name}.refresh_token_status
```

For example:

```
oauthv2accesstoken.RefreshAccessToken.access_token
oauthv2accesstoken.RefreshAccessToken.expires_in
oauthv2accesstoken.RefreshAccessToken.refresh_token
oauthv2accesstoken.RefreshAccessToken.refresh_token_expires_in
oauthv2accesstoken.RefreshAccessToken.refresh_token_issued_at
oauthv2accesstoken.RefreshAccessToken.refresh_token_status
```

## Encoding
basic authentication credentials

When you make an API call to request a token or auth code, it's a good practice, and is
recommended by the OAuth 2.0 specification to pass the client_id and client_secret values as
an HTTP-Basic Authentication header, as described in [IETF RFC 2617](https://tools.ietf.org/html/rfc2617#section-2). To do this, you must
base64-encode the result of joining the two values together with a colon separating them.

In pseudo-code:

```
result = Base64Encode(concat('ns4fQc14Zg4hKFCNaSzArVuwszX95X', ':', 'ZIjFyTsNgQNyxI'))
```

In this example, `ns4fQc14Zg4hKFCNaSzArVuwszX95X` is the client_id and
`ZIjFyTsNgQNyxI` is the client secret.

Regardless of the programming language you use to compute the base64-encoded value, for those
given client credentials, the base64-encoded result is:
`bnM0ZlFjMTRaZzRoS0ZDTmFTekFyVnV3c3pYOTVYOlpJakZ5VHNOZ1FOeXhJOg==`

Then, you can make the token request as follows:

```
$ curl -i -H 'Content-Type: application/x-www-form-urlencoded' \
  -H 'Authorization: Basic bnM0ZlFjMTRaZzRoS0ZDTmFTekFyVnV3c3pYOTVYOlpJakZ5VHNOZ1FOeXhJOg==' \
  -X POST 'https://docs-test.apigee.net/oauth/accesstoken' \
  -d 'grant_type=client_credentials'
```

The `curl` utility will actually create the HTTP Basic header for you, if you use
the -u option. The following is equivalent to the above:

```
$ curl -i -H 'Content-Type: application/x-www-form-urlencoded' \
  -u 'ns4fQc14Zg4hKFCNaSzArVuwszX95X:ZIjFyTsNgQNyxI' \
  -X POST 'https://docs-test.apigee.net/oauth/accesstoken' \
  -d 'grant_type=client_credentials'
```

Other programming environments may have similar shortcuts that automatically generate the
base64-encoded header.

## Hashing tokens in the database

To protect OAuth access and refresh tokens in the event of a database security breach, you can
enable automatic token hashing in your Edge organization. When the feature is enabled, Edge
automatically creates a hashed version of newly generated OAuth access and refresh tokens using
the algorithm you specify. (Information about bulk-hashing existing tokens follows.) The
un-hashed tokens are used in API calls, and Edge validates them against the hashed versions in
the database.

The following organization-level properties control OAuth token hashing.

```
features.isOAuthTokenHashingEnabled = true
features.OAuthTokenHashingAlgorithm = SHA1 | SHA256 | SHA384 | SHA512 | PLAIN
```

If you have existing hashed tokens and want to retain them until they expire, set the
following properties in your organization, where the hashing algorithm matches the existing
algorithm (for example, SHA1, the former Edge default). If the tokens were un-hashed, use
PLAIN.

```
features.isOAuthTokenFallbackHashingEnabled = true
features.OAuthTokenFallbackHashingAlgorithm = SHA1 | SHA256 | SHA384 | SHA512 | PLAIN
```

If you're an Edge cloud customer, contact [Apigee Edge Support](https://docs.apigee.com/api-platform/troubleshoot/support) to set these
properties on your organization and optionally to bulk hash existing tokens.

> [!NOTE]
> **Private Cloud:** For Edge for Private Cloud customers, use the following API call with system administrator credentials.
>
> > [!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.
>
> ```
> curl -u email:password -X PUT -H "Content-Type: application/xml" https://host:port/v1/o/{myorg} \
>   -d '<Organization type="trial" name="MyOrganization">
>     <Properties>
>         <Property name="features.isOAuthTokenHashingEnabled">true</Property>
>         <Property name="features.OAuthTokenHashingAlgorithm">SHA256</Property>
>         <Property name="features.isOAuthTokenFallbackHashingEnabled">true</Property>
>         <Property name="features.OAuthTokenFallbackHashingAlgorithm">SHA1</Property>
>         <Property...(an existing property)
>         <Property...(an existing property)
>         <Property...(an existing property)
>     </Properties>
>   </Organization>'
> ```
>
> ### Bulk hashing existing tokens
>
> Edge also provides a script you can run to hash existing tokens. For more information, see
> the *Edge for Private Cloud Operations Guide* version 4.15.07.00 and later.

## Related topics

- [Implementing the
  client credentials grant type](https://docs.apigee.com/api-platform/security/oauth/oauth-20-client-credentials-grant-type)
- [Implementing
  the authorization code grant type](https://docs.apigee.com/api-platform/security/oauth/oauth-v2-policy-authorization-code-grant-type)
- [API
  security online course](https://www.coursera.org/learn/api-security-apigee-gcp) (includes OAuth)
- [OAuthV2 policy](https://docs.apigee.com/api-platform/reference/policies/oauthv2-policy) -- Has lots of examples showing how to make requests to the authorization server and how to configure the OAuthV2 policy.