---
schema_version: "1"
id: dff92f5c634b507e21295bdbb809b1fc38cf6d55191cf5f01e3cc6226df8c328
title: OAuth 2.0 Device Flow for IoT Integration
collection: admin
version: current
locale: en-us
portal_url: https://docs.salesforce.com/admin/current/en-us/xcloud/264-0-0/remoteaccess_oauth_device_flow_ca.md
canonical_url: https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_device_flow_ca.htm&release=264.0.0&type=5
source_site: help.salesforce.com
content_type: documentation
content_hash: 489a3c50a35e5fd861862e580b42df4ed19c3ab84b2325e7d4c63d218443d049
description: To integrate apps that run on devices with limited input or display capabilities, such as Smart TVs, appliances, and other IoT devices, use the OAuth 2.0 device flow. Command-line apps can also use this flow. Users can connect these apps to Salesforce by accessing a browser on a device with more advanced input capabilities, such as a desktop or mobile device.
products:
  - Security
  - Cross Cloud
release: "264"
---
# OAuth 2.0 Device Flow for IoT Integration

To integrate apps that run on devices with limited input or display capabilities, such as Smart TVs, appliances, and other IoT devices, use the OAuth 2.0 device flow. Command-line apps can also use this flow. Users can connect these apps to Salesforce by accessing a browser on a device with more advanced input capabilities, such as a desktop or mobile device.

### Required Editions

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small edition"><colgroup><col></colgroup><tbody><tr class=""><td class="slds-cell-wrap" style="vertical-align:top;">Available in: both Salesforce Classic and Lightning Experience</td></tr><tr class=""><td class="slds-cell-wrap" style="vertical-align:top;">Available in: <strong>All</strong> Editions</td></tr></tbody></table>

![Note](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-xcloud-identity-264-0-0-production-enus/699dab6f-8f1a-4662-b24f-6521d5b747f7/images/icon_note.png)

Note Connected apps creation is restricted as of Spring ‘26. You can continue to use existing connected apps during and after Spring ‘26. However, we recommend using [external client apps](https://help.salesforce.com/s/articleView?id=xcloud.external_client_apps.htm&language=en_US) instead. If you must continue creating connected apps, contact Salesforce Support.

See [New connected apps can no longer be created in Spring ‘26](https://help.salesforce.com/s/articleView?id=005228017&type=1&language=en_US) for more details.

For example, a customer uses a bluetooth device to control their house lights while they’re away for the evening. You can create a connected app for the bluetooth device to enable this flow.

1. The user opens the bluetooth app on their mobile device and clicks Turn On Lights.
2. The connected app posts a request to the Salesforce token endpoint.
3. Salesforce verifies the request and returns a human-readable user code, verification URL, and device code.
4. The bluetooth app displays the device code and instructs the user to enter it at the specified verification URL. The app also begins polling the Salesforce token endpoint for authorization.
5. The user clicks the link to the verification URL and enters the code.
6. The user then authorizes the app to access their protected data, in this case their home’s location.
7. Salesforce sends an access and refresh token to the connected app.
8. The bluetooth app can access the user’s home location and turn on the lights.

Let’s walk through the steps in this authorization flow.

1. [Device Requests Authorization](https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_device_flow_ca.htm&release=264.0.0&type=5)
2. [Salesforce Returns Verification Codes](https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_device_flow_ca.htm&release=264.0.0&type=5)
3. [User Authenticates and Authorizes While Device Polls the Token Endpoint](https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_device_flow_ca.htm&release=264.0.0&type=5)
4. [Salesforce Grants Access Token](https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_device_flow_ca.htm&release=264.0.0&type=5)

## Device Requests Authorization

To initiate the authorization flow, the device—via a connected app—posts an authorization request to the Salesforce token endpoint.

For example:

```
POST /services/oauth2/token  HTTP/1.1
Host: login.salesforce.com
Content-Type: application/x-www-form-urlencoded

response_type=device_code&
client_id=3MVG9PhR6g6B7ps7TTI4cP7Mppg3l7tu.​MRAYULyVqcmA9hGLpHiiS.Q7rO9yjlmffiBUM6tFpYAlXEkRjHb9&scope=api
```

Include these parameters in the request.

![Important](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-xcloud-identity-264-0-0-production-enus/699dab6f-8f1a-4662-b24f-6521d5b747f7/images/icon_important.png)

Important When developing OAuth integrations, always pass sensitive information in the body of a POST request or in a request header. Don't use GET parameters in the URL query string to pass sensitive information. Sensitive information includes but isn't limited to usernames, passwords, OAuth tokens, client secrets, and any personally identifiable information. For more information on security best practices, see [Storing Sensitive Data](https://developer.salesforce.com/docs/atlas.en-us.secure_coding_guide.meta/secure_coding_guide/secure_coding_storing_sensitive_data.htm) in the Secure Coding Guide.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small ">
        <colgroup>
          <col>
          <col>
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d67040e168">Parameter</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d67040e171">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e168 ">
              <code>Request Header</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e171 ">
              <p>The request header contains this information:</p>
              <ul>
                <li>The Salesforce OAuth 2.0 token endpoint. Connected apps send OAuth token
                  requests to this endpoint.</li>

                <li>The authorization server.</li>

                <li>Content type of the request.</li>

              </ul>
            </td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e168 ">
              <code>response_type</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e171 ">The OAuth 2.0 grant type that the connected app requests. The value for this
              flow must be <samp class="parmname">device_code</samp>.</td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e168 ">
              <code>client_id</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e171 ">The consumer key of the connected app. To access the consumer key, from the App
              Manager, find the connected app and select <strong class="uicontrol">View</strong> from the
              dropdown. Then click <strong class="uicontrol">Manage Consumer Details</strong>. You're
              sometimes prompted to verify your identity before you can view the consumer
              key.</td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e168 ">
              <code>scope</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e171 ">Optional. Permissions that define the type of protected resources a connected
              app can access. You assign scopes to a connected app when you build it, and they’re
              included with the OAuth tokens during the authorization flow. If you don’t include
              this parameter, all scopes assigned to the connected app are requested. The scopes
              passed in this parameter must be a subset of the registered scopes. For valid
              parameters, see <a href="https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_tokens_scopes.htm&amp;type=5&amp;language=en_US" target="_blank">OAuth Scopes</a>.</td>

          </tr>
        </tbody>
      </table>

## Salesforce Returns Verification Codes

After verifying the request, Salesforce returns a human-readable user code, verification URL, and device code.

This sample response returns these values with a 200 success status code.

```
HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store

{
"device_code":"M01WRzlQaFI2ZzZCN3BzN1RUSTRjUDdNcHBnM2w3dHUuTVJBWVVMeVZxY21BOWhHTHBIaWlTLlE3ck​85eWpsbWZmaUJVTTZ0RnBZQWxYRWtSakhiOTsxMC4yMi4zNC45MjsxNDc3Njc0NDg3NTA1O1gxRDlTRUVU",
"user_code":"X1D9SEET",
"verification_uri":"https://acme.my.salesforce.com/setup/connect",
"interval":5
}
```

The following parameters are included in the response.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small ">
        <colgroup>
          <col>
          <col>
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d67040e280">Parameter</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d67040e283">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e280 ">
              <code>Response Header</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e283 ">
              <p>The response header contains this information:</p>
              <ul>
                <li>200 success status code</li>

                <li>Content type of the response</li>

                <li>Indication that data isn’t stored in a cache</li>

              </ul>
            </td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e280 ">
              <code>device_code</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e283 ">
              <p>A verification code for the device. This code is valid for 10 minutes. The code
                can include uppercase letters, lowercase letters, and numbers. </p>
              <p style="margin-bottom:0;">Salesforce can
                change how we format device codes at any time. When you develop integrations that
                use this flow, don’t make assumptions about the device code format and
                length.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e280 ">
              <code>user_code</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e283 ">A verification code for the end user, sent as an 8-digit alphanumeric code. The
              user must enter this code at the verification URL. This code is valid for 10
              minutes.</td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e280 ">
              <code>verification_uri</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e283 ">
              <p>The end-user verification URL on the authorization server. The user must enter
                the user code at this verification URL.</p>
              <p>With verification through a My Domain
                login URL or Experience Cloud site URL, the <samp class="parmname">verification_uri</samp>
                reflects the URL that initiated the flow. For example, if the device sends a token
                request to
                <samp class="filepath">https://acme.my.salesforce.com/services/oauth2/token</samp>, the
                <samp class="parmname">verification_uri</samp> is
                <samp class="filepath">https://acme.my.salesforce.com/setup/connect</samp>.
              </p>
              <p style="margin-bottom:0;">Optionally,
                you can add the <code>prompt</code> parameter to your
                <samp class="parmname">verification_uri</samp>.
              </p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e280 ">
              <code>interval</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e283 ">The minimum number of seconds that we recommend waiting between polling
              requests to the token endpoint.</td>

          </tr>
        </tbody>
      </table>

## User Authenticates and Authorizes While Device Polls the Token Endpoint

The client app on the device instructs the user to visit the verification URL on a computer or mobile device and enter the user code. The user opens a browser, navigates to the verification URL, and enters the code displayed on the device. If the code is valid, the user logs in, as needed. After successful login, the user allows the device to access Salesforce account data.

Meanwhile, after displaying the user code and verification URL, the client application on the device polls the token endpoint repeatedly. Polling checks whether the user has authorized access and whether the authorization server has issued the access token.

Here’s an example of a polling request:

```
POST /services/oauth2/token  HTTP/1.1
Host: login.salesforce.com
Content-Type: application/x-www-form-urlencoded

grant_type=device&
client_id=3MVG9PhR6g6B7ps7TTI4cP7Mppg3l7tu.MRAYULyVqcmA9hGLpHiiS.​Q7rO9yjlmffiBUM6tFpYAlXEkRjHb9&code=M01WRzlQaFI2ZzZCN3BzN1RUSTRjUDdNcHBnM2w3dHUu​TVJBWVVMeVZxY21BOWhHTHBIaWlTLlE3ck85eWpsbWZmaUJVTTZ0RnBZQWxYRWtSakhiOTsxMC4yMi4zNC45MjsxNDc3N​jc0NDg3NTA1O1gxRDlTRUVU
```

The polling request contains these parameters, in addition to the header.

 
| Parameter | Description |
| --- | --- |
| `grant_type` | The value must be device for this flow. |
| `client_id` | The consumer key of the connected app. To access the consumer key, from the App Manager, find the connected app and select **View** from the dropdown. Then click **Manage Consumer Details**. You're sometimes prompted to verify your identity before you can view the consumer key. |
| `code` | The authorization server creates an authorization code, which is a short-lived token, and passes it to the client after successful authentication. The client sends the authorization code to the authorization server to obtain an access token and, optionally, a refresh token. |

## Salesforce Grants Access Token

If the user has authorized access, the Salesforce responds with a success message and the access token along with other values. For example:

```
{
"access_token": "00DD00000008Uw2!ARkAQGppKf6n.VwG.EnFSvi731qWh.7vKfaJjL7h49yutIC84gAsxM​rqcE81GjpTjQbDLkytl2ZwosNbIJwUS0X8ahiILj3e"
"refresh_token": "your token here"
"signature": "hJuYICd2IHsjyTcFqTYiOr8THmgDmrcjgWaMp13X6dY="
"scope": "api"
"instance_url": "https://yourInstance.salesforce.com"
"id": "https://login.salesforce.com/id/00DD00000008Uw2MAE/005D0000001cAGmIAM"
"token_type": "Bearer"
"issued_at": "1477674717112"
}
```

These parameters are included in the example response.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small ">
        <colgroup>
          <col>
          <col>
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d67040e507">Parameter</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d67040e510">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e507 ">
              <code>access_token</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e510 ">OAuth token that a connected app uses to request access to a protected resource
              on behalf of the client application. Additional permissions in the form of scopes
              can accompany the access token.</td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e507 ">
              <code>refresh_token</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e510 ">Token obtained from the web server, user-agent, or hybrid app token flow. This
              value is a secret. Take appropriate measures to protect it. This parameter is
              returned only if your connected app is set up with a <code>refresh_token</code>
              scope.</td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e507 ">
              <code>signature</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e510 ">Base64-encoded HMAC-SHA256 signature signed with the
              <code>client_secret</code>. The signature can include the concatenated ID and
              <code>issued_at value</code>, which you can use to verify that the identity
              URL hasn’t changed since the server sent it.
            </td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e507 ">
              <code>scope</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e510 ">
              <p>The scopes associated with the access token.</p>
              <p>Scopes further define the type
                of protected resources that the client can access. You assign scopes to a
                connected app when you build it, and they’re included with the OAuth tokens during
                the authorization flow. </p>
              <p style="margin-bottom:0;">For valid parameters, see <a href="https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_tokens_scopes.htm&amp;type=5&amp;language=en_US" target="_blank">OAuth Scopes</a>.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e507 ">
              <code>instance_url</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e510 ">A URL indicating the instance of the user’s org. For example:
              <code>https://<var>yourInstance</var>.salesforce.com/</code>.
            </td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e507 ">
              <code>id</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e510 ">An identity URL that can be used to identify the user and to query for more
              information about the user. See <a href="https://help.salesforce.com/articleView?id=remoteaccess_using_openid.htm&amp;language=en_US" target="_blank">Identity URLs</a>.</td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e507 ">
              <code>token_type</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e510 ">A <code>Bearer</code> token type, which is used for all responses that
              include an access token.</td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e507 ">
              <code>issued_at</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d67040e510 ">Time stamp of when the signature was created in milliseconds.</td>

          </tr>
        </tbody>
      </table>