# Migrating to OAuth2 Tokens

Existing applications that use the Pre-2017 Authorization (Deprecated) framework need to move to support the new OAuth2 Bearer Tokens. Applications will need to migrate their existing users who already have connected to it to obtain new Oauth2 tokens without requiring users to reauthorize. This can be done by exchanging an old access token for a new refresh token.

### Base URIs <a href="#base_uris" id="base_uris"></a>

When making API calls, the appropriate base URI for the user’s geolocation should be used. .

### Exchanging a Token <a href="#exchangetoken" id="exchangetoken"></a>

In order to support new OAuth2, applications need to exchange old access token for new `accessToken` and `refreshToken` pair. Once obtained, applications should store these `refreshTokens` as part of users authorization data.

The new OAuth2 `accessToken` has a one hour lifetime. Once expired, applications would need to call OAuth2’s `/v0/token` endpoint using a `refresh_grant`, passing in the user’s `refreshtoken` to obtain a fresh `accessToken`.

This is significantly different from how the deprecated /net2/OAuth2’s method of handling access tokens. Partner’s would have to store the new OAuth2 `refreshToken` instead of the old access token. Before making a call to any of the new v4 APIs, it is advisable to request for a new `accessToken` before making the API call.

**Step 1: Obtain Application Token** Clients can exchange OLD tokens for NEW OAuth2 tokens by calling the `exchangeRefreshToken/me` endpoint. In order to call this endpoint, you would first need to obtain an Application Token by calling the `/v0/token` endpoint with the client\_credentials grant.

The endpoint also supports a parameter called “returnType=companyToken” This parameter allows a partner who already has what is known as a “WSAdmin” token for a client, to exchange that token for a Company level refresh token.

**Step 2: Call exchangeRefreshToken**

`POST /appmgmt/v0/legacyApps/{OLDConsumerKey}/exchangeRefreshToken/me`

If you are exchanging a WSAdmin token for a new Company level refresh token:

`POST /appmgmt/v0/legacyApps/{OLDConsumerKey}/exchangeRefreshToken/me?returnType=companyToken`

**Request Header**

<table data-full-width="true"><thead><tr><th>Name</th><th>Type</th><th>Format</th><th>Description</th></tr></thead><tbody><tr><td><code>Authorization</code></td><td><code>string</code></td><td><code>Bearer &#x3C;accessToken></code></td><td><strong>Required</strong> The NEW client_credentials accessToken.</td></tr></tbody></table>

**Request Body**

<table data-full-width="true"><thead><tr><th>Name</th><th>Type</th><th>Format</th><th>Description</th></tr></thead><tbody><tr><td><code>token</code></td><td><code>string</code></td><td> </td><td><strong>Required</strong> The OLD refreshToken</td></tr><tr><td><code>secret</code></td><td><code>string</code></td><td> </td><td><strong>Required</strong> The NEW application client_secret</td></tr></tbody></table>

Sample Curl:

```
curl -H 'Authorization: Bearer <accessToken>' -d '{"token": "1_oaCof444CaiNXg1FFG$Perr19qIo", "secret": "12345"}' -X POST v0/legacyApps/Bwu0mvTHtKYAnBb3Pgu9AW/exchangeRefreshToken/me
```

successful call, responds with

```
200 OK
{
  "token": "8c844478-745c-4c45-adf7-1e2777a50dbf",
  "created": 1479407196809,
  "expired": 1494959196809,
  "scopes": [
    "EXPRPT",
    "LIST",
    "BANK",
    "CCARD"
  ],
}
```

Sample Curl for WSAdmin token exchange for Company level refreh token:

```
curl -H 'Authorization: Bearer <accessToken>' -d '{"token": "1_oaCof444CaiNXg1FFG$Perr19qIo", "secret": "12345"}' -X POST v0/legacyApps/Bwu0mvTHtKYAnBb3Pgu9AW/exchangeRefreshToken/me?returnType=companyToken
```

successful call, responds with

```
200 OK
{
  "token": "8c844478-745c-4c45-adf7-1e2777a50dbf",
  "created": 1479407196809,
  "expired": 1494959196809,
  "scopes": [
    "EXPRPT",
    "LIST",
    "BANK",
    "CCARD"
  ],
}
```

**Step 3: Obtain New Access Token**

Once you have the NEW `refreshToken` from the response (`8c844478-745c-4c45-adf7-1e2777a50dbf`) you can then proceed to call `/v0/token` using the refresh grant to obtain a NEW OAuth2 `accessToken`.

Sample Curl:

```
curl -X POST 'oauth2/v0/token' -d 'client_id=3a55c75e-ac1e-4515-845c-0a4978452828&client_secret=12345&grant_type=refresh_token&refresh_token=8c844478-745c-4c45-adf7-1e2777a50dbf'
```

successful call, responds with:

```
200 OK
{
  "expires_in": 3600,
  "scope": "EXPRPT LIST BANK CCARD",
  "token_type": "Bearer",
  "access_token": "eyJ0...demo...eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsImtpZCI6IjE0NTU2MTQzNDYifQ.eyJjb25jdXIuc2NvcGVzIjpbIkVYUFJQVCIsIkxJU1QiLCJCQU5LIiwiQ0NBUkQiXSwiYXVkIjoiKiIsImNvbmN1ci5wcm9maWxlIjoiaHR0cHM6Ly91cy1ycWEzLmFwaS5jb25jdXJzb2x1dGlvbnMuY29tL3Byb2ZpbGUvdjEvcHJpY2lwYWxzLzc5NmI0NjdmLWRjZDEtNDYzMS1iYTg1LTNlYmQyOGIzNmU4ZiIsImNvbmN1ci52ZXJzaW9uIjoyLCJjb25jdXIudHlwZSI6InVzZXIiLCJjb25jdXIuYXBwIjoiaHR0cHM6Ly91cy1ycWEzLmFwaS5jb25jdXJzb2x1dGlvbnMuY29tL3Byb2ZpbGUvdjEvYXBwcy9lMDEwZTI1ZC1iNGNlLTRjZTMtYTdlNiLCJzdWIiOiI3OTZiNDY3Zi1kY2QxLTQ2MzEtYmE4NS0zZWJkMjhiMzZlOGYiLCJpc3MiOiJodHRwczovL3VzLXJxYTMuYXBpLmNvbmN1cnNvbHV0aW9ucy5jb20iLCJleHAiOjE0Nzk0MTU4NjksImxlZ2FjeV9hcHBsaWNhdGlvbl9pZCI6MTUwMDA2MzY1OSwidXNlclVSSSI6Imh0dHBzOi8vdXMtcnFhMy5hcGkuY29uY3Vyc29sdXRpb25zLmNvbS9wcm9maWxlLXNlcnZpY2UvdjEvdXNlcnMvNzk2YjQ2N2YtZGNkMS00NjMxLWJhODUtM2ViZDI4YjM2ZThmIiwidXNlcnV1aWQiOiI3OTZiNDY3Zi1kY2QxLTQ2MzEtYmE4NS0zZWJkMjhiMzZlOGYiLCJuYmYiOjE0Nzk0MTIyNjksImh0dHBzOi8vYXBpLmNvbmN1cnNvbHV0aW9ucyiaHR0cHM6Ly91cy1ycWEzLmFwaS5jb25jdXJzb2x1dGlvbnMuY29tL3Byb2ZpbGUvdjEvYXBwcy9lMDEwZTI1ZC1iNGNlLTRjZTMtYTdlNC1iNjcwY2IxYWRjYjAiLCJodHRwczovL2FwaS5jb25jdXJzb2x1dGlvbnMuY29tL3Njb3BlcyI6WyJFWFBSUFQiLCJMSVNUIiwiQkFOSyIsIkNDQVJEIl0sImlhdCI6MTQ3OTQxMjI2OX0.I4EeqKZbpfFonitGBZnLBb20NwMjZNNp5e1d3-BRsepEcJSVCVYIV9HAB2EkkopvoLJsAittiZgD0iDwuh2WVgUt_c4QGzNc_-rXRtCIeKyPQRvxUZNQ7y5RTqEQFNo7hrtXiNZ-yV30zlbijP-12XU5Cu4n2VXgRKxvcCUr5j0RcovUc6O0aOR7VTzj4ZbiDdijOEtmKWGluAYyfIlz8XF2aErAB5Jff2fr9UvgHgtbleYV7eBSesvd9hJEk4S-OAtmFoJwLDECLtLcBKyeHnPEe7LmkLYShcflWG2_tYk4ysPIMG6ne5kRNxJKsDbkMItjpXhujBEGi7YIPWtFWQ",
  "refresh_token": "31456dcd-b46a-4292-b2d3-f97033338487"
}
```

### Response Codes <a href="#response_codes" id="response_codes"></a>

**HTTP Status returned by exchangeAccessToken**

<table data-full-width="true"><thead><tr><th>HTTP Status</th><th>Description</th></tr></thead><tbody><tr><td>200</td><td>OK - Successful call, response is in body.</td></tr><tr><td>400</td><td>Bad Request - see list of responses below.</td></tr><tr><td>404</td><td>Not Found</td></tr><tr><td>500</td><td>Server Error, error message is in body.</td></tr><tr><td>503</td><td>Server Timed Out, error message is in body.</td></tr></tbody></table>

**exchangeAccessToken Response Codes**

<table data-full-width="true"><thead><tr><th>CODE</th><th>Description</th></tr></thead><tbody><tr><td>OK</td><td>OK - Successful call, response is in body.</td></tr><tr><td>INVALIDSCOPES</td><td>One or more scopes requested are not a subset of the allowed scopes.</td></tr><tr><td>INVALIDAPP</td><td>Application is invalid</td></tr><tr><td>INVALIDTOKEN</td><td>Bad or expired token</td></tr><tr><td>UNAUTHORIZED</td><td>Invalid credentials</td></tr></tbody></table>

**HTTP Status returned by OAuth2**

<table data-full-width="true"><thead><tr><th>HTTP Status</th><th>Description</th></tr></thead><tbody><tr><td>200</td><td>OK - Successful call, response is in body.</td></tr><tr><td>400</td><td>Bad Request <code>(error, error_description, code)</code></td></tr><tr><td>401</td><td>Unauthorized <code>(error, error_description, code)</code></td></tr><tr><td>403</td><td>Forbidden <code>(error, error_description, code)</code></td></tr><tr><td>404</td><td>Not Found <code>(error, error_description, code)</code></td></tr><tr><td>500</td><td>Server Error, error message is in body.</td></tr><tr><td>503</td><td>Server Timed Out, error message is in body.</td></tr></tbody></table>

4xx class errors have a JSON response with the following fields

```
{
  "code": <number>,
  "error": <error>,
  "error_description": <error_description>
}
```

**/token**

<table data-full-width="true"><thead><tr><th>Code</th><th>Error</th><th>Description</th></tr></thead><tbody><tr><td>5</td><td><code>invalid_grant</code></td><td>Incorrect credentials. Please Retry</td></tr><tr><td>10</td><td><code>invalid_grant</code></td><td>Account is disabled. Please contact support</td></tr><tr><td>11</td><td><code>invalid_grant</code></td><td>Account is disabled. Please contact support</td></tr><tr><td>12</td><td><code>invalid_grant</code></td><td>Logon Denied. Please contact support</td></tr><tr><td>13</td><td><code>invalid_grant</code></td><td>Logon Denied. Please contact support</td></tr><tr><td>14</td><td><code>invalid_grant</code></td><td>Account Locked. Please contact support</td></tr><tr><td>16</td><td><code>invalid_request</code></td><td>user lives elsewhere</td></tr><tr><td>19</td><td><code>invalid_grant</code></td><td>Incorrect credentials. Please Retry</td></tr><tr><td>20</td><td><code>invalid_grant</code></td><td>Logon Denied. Please contact support (typically due to IP restriction)</td></tr><tr><td>51</td><td><code>invalid_request</code></td><td>username was not supplied</td></tr><tr><td>52</td><td><code>invalid_request</code></td><td>password was not supplied</td></tr><tr><td>53</td><td><code>invalid_client</code></td><td>company is not enabled for this client</td></tr><tr><td>54</td><td><code>invalid_scope</code></td><td>requested scope exceeds granted scope</td></tr><tr><td>55</td><td><code>invalid_request</code></td><td>we don’t know this email</td></tr><tr><td>56</td><td><code>invalid_request</code></td><td><code>otp</code> was not supplied</td></tr><tr><td>57</td><td><code>invalid_request</code></td><td><code>channel_type</code> missing</td></tr><tr><td>58</td><td><code>invalid_request</code></td><td><code>channel_handle</code> missing</td></tr><tr><td>59</td><td><code>access_denied</code></td><td>client disabled</td></tr><tr><td>60</td><td><code>invalid_grant</code></td><td>these are not the grants you are looking for</td></tr><tr><td>61</td><td><code>invalid_client</code></td><td>client not found</td></tr><tr><td>62</td><td><code>invalid_request</code></td><td><code>client_id</code> was not supplied</td></tr><tr><td>63</td><td><code>invalid_request</code></td><td><code>client_secret</code> was not supplied</td></tr><tr><td>64</td><td><code>invalid_client</code></td><td>Incorrect credentials. Please Retry</td></tr><tr><td>65</td><td><code>invalid_request</code></td><td><code>grant_type</code> was not supplied</td></tr><tr><td>80</td><td><code>invalid_request</code></td><td>invalid channel type</td></tr><tr><td>81</td><td><code>invalid_request</code></td><td>bad channel handle</td></tr><tr><td>83</td><td><code>invalid_request</code></td><td>otp not found</td></tr><tr><td>84</td><td><code>invalid_request</code></td><td>fact verification failed</td></tr><tr><td>85</td><td><code>invalid_request</code></td><td>otp verification failed</td></tr><tr><td>100</td><td><code>invalid_request</code></td><td>backend does not know about this username</td></tr><tr><td>101</td><td><code>invalid_request</code></td><td>code was not supplied</td></tr><tr><td>102</td><td><code>invalid_request</code></td><td><code>redirect_uri</code> was not supplied</td></tr><tr><td>103</td><td><code>invalid_request</code></td><td>code is bad or expired</td></tr><tr><td>104</td><td><code>invalid_grant</code></td><td><code>redirect_uri</code> does not match the previous grant</td></tr><tr><td>105</td><td><code>invalid_grant</code></td><td>this grant was not issued to you!</td></tr><tr><td>106</td><td><code>invalid_request</code></td><td><code>refresh_token</code> was not supplied</td></tr><tr><td>107</td><td><code>invalid_request</code></td><td>refresh disallowed for app</td></tr><tr><td>108</td><td><code>invalid_grant</code></td><td>bad or expired refresh token</td></tr><tr><td>109</td><td><code>invalid_request</code></td><td><code>loginid</code> was not supplied</td></tr><tr><td>115</td><td><code>invalid_request</code></td><td>unauthenticated client will not be issued token!</td></tr><tr><td>117</td><td><code>invalid_request</code></td><td>nonce is mandatory for this <code>response_type</code></td></tr><tr><td>118</td><td><code>invalid_request</code></td><td>display is invalid</td></tr><tr><td>119</td><td><code>invalid_request</code></td><td>prompt is invalid</td></tr><tr><td>119</td><td><code>invalid_request</code></td><td>prompt must be set to consent for <code>offline_access</code></td></tr><tr><td>120</td><td><code>invalid_request</code></td><td><code>credtype</code> is invalid</td></tr><tr><td>121</td><td><code>invalid_request</code></td><td><code>login_type</code> is invalid</td></tr><tr><td>122</td><td><code>invalid_request</code></td><td>proxies supplied are invalid</td></tr><tr><td>123</td><td><code>invalid_request</code></td><td>principal is disabled</td></tr></tbody></table>
