> ## Documentation Index
> Fetch the complete documentation index at: https://discord-platform-username.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Account Linking from Your Game

> Implement account linking to connect user accounts between your application and Discord.

export const UserIcon = props => <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path fill="currentColor" d="M12 10a4 4 0 1 0 0-8 4 4 0 0 0 0 8ZM11.53 11A9.53 9.53 0 0 0 2 20.53c0 .81.66 1.47 1.47 1.47h.22c.24 0 .44-.17.5-.4.29-1.12.84-2.17 1.32-2.91.14-.21.43-.1.4.15l-.26 2.61c-.02.3.2.55.5.55h11.7a.5.5 0 0 0 .5-.55l-.27-2.6c-.02-.26.27-.37.41-.16.48.74 1.03 1.8 1.32 2.9.06.24.26.41.5.41h.22c.81 0 1.47-.66 1.47-1.47A9.53 9.53 0 0 0 12.47 11h-.94Z" /></svg>;

export const ListViewIcon = props => <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path fill="currentColor" d="M4 2a2 2 0 1 0 0 4 2 2 0 0 0 0-4ZM4 10a2 2 0 1 0 0 4 2 2 0 0 0 0-4ZM2 20a2 2 0 1 1 4 0 2 2 0 0 1-4 0ZM9 3a1 1 0 0 0 0 2h12a1 1 0 1 0 0-2H9ZM8 12a1 1 0 0 1 1-1h12a1 1 0 1 1 0 2H9a1 1 0 0 1-1-1ZM9 19a1 1 0 1 0 0 2h12a1 1 0 1 0 0-2H9Z" /></svg>;

export const PaintPaletteIcon = props => <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path fill="currentColor" fill-rule="evenodd" d="M19 16h-5a2 2 0 0 0-2 2v2c0 1.66-1.37 3.04-2.96 2.6A11 11 0 1 1 23 12c0 2.2-2 4-4 4ZM13.5 4.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0ZM17.25 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm-9-1.5a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0Zm-3.75 7a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z" clip-rule="evenodd" /></svg>;

## Overview

<Tip>
  New to account linking? Read the [Account Linking overview](/developers/platform/account-linking) to understand what it is, how it works, and which flow to use.
</Tip>

This guide explains how to authenticate users with their existing Discord accounts via OAuth2, enabling seamless login and access to Discord features.

### Flexible Account Options

If a player does not have a Discord account, you can use the SDK to [create a provisional account](/developers/discord-social-sdk/development-guides/using-provisional-accounts) instead so that they can still access your game's features.

### Prerequisites

Before you begin, make sure you have:

* Read the [Core Concepts](/developers/discord-social-sdk/core-concepts) guide to understand:
  * OAuth2 authentication flow
  * Discord application setup
  * SDK initialization
* Set up your development environment with:
  * Discord application created in the [Developer Portal](https://discord.com/developers/applications)
  * Discord Social SDK downloaded and configured
  * Basic SDK integration working (initialization and connection)

If you haven't completed these prerequisites, we recommend first following the [Getting Started](/developers/discord-social-sdk/getting-started) guide.

<Info>
  This feature requires the **Default Presence Scopes** (`openid` and `sdk.social_layer_presence`).
  Use [`Client::GetDefaultPresenceScopes`] when configuring your OAuth2 flow.
  See the [OAuth2 Scopes guide](/developers/discord-social-sdk/core-concepts/oauth2-scopes) for details on all available scopes.
</Info>

[`Client::GetDefaultPresenceScopes`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a7648bd1d2f7d9a86ebd0edb8bef12b5c

***

## Our Authentication Flow

OAuth2 is the standard authentication flow that allows users to sign in using their Discord account. The process follows these steps:

1. [Request authorization](/developers/discord-social-sdk/development-guides/account-linking-with-discord#step-1-request-authorization): Your game sends an authentication request to Discord.
2. [User Approval](/developers/discord-social-sdk/development-guides/account-linking-with-discord#step-2-user-approval): The user approves the request, granting access to your application.
3. [Receive Authorization Code](/developers/discord-social-sdk/development-guides/account-linking-with-discord#step-3-receiving-the-authorization-code): After approval, Discord redirects the user to your app with an authorization code.
4. [Exchange for Tokens](/developers/discord-social-sdk/development-guides/account-linking-with-discord#step-4-exchanging-the-authorization-code-for-an-access-token): The authorization code is exchanged for:
   * Access Token, which is valid for \~7 days
   * Refresh Token, used to obtain a new access token

<Info>
  The OAuth2 flow requires a user's account to be verified
</Info>

### OAuth2 using the Discord Social SDK

* If the Discord client has [overlay support](https://support.discord.com/hc/en-us/articles/217659737-Game-Overlay-101) (Windows only), the OAuth2 login modal appears in your game instead of opening a browser.
* The SDK automatically handles redirects, simplifying the authentication flow.
* Some security measures, such as CSRF protection, are built-in, but you should always follow best practices to secure your app.

***

## Requesting Access Tokens

### Step 0: Configure OAuth2 Redirects

For OAuth2 to work correctly, you must **register the correct redirect URIs** for your app in the [**Discord Developer Portal**](https://discord.com/developers/applications/select/oauth2).

| Platform    | Redirect URI                                                                               |
| ----------- | ------------------------------------------------------------------------------------------ |
| **Desktop** | `http://127.0.0.1/callback`                                                                |
| **Mobile**  | `discord-APP_ID:/authorize/callback` *(replace `APP_ID` with your Discord application ID)* |

### Step 1: Request Authorization

The SDK provides helper methods to simplify OAuth2 login.

Use the [`Client::Authorize`] method to initiate authorization and allow the user to approve access.

#### Authorization Scopes

One of the required arguments to [`Client::Authorize`] is scopes — the set of permissions your game is requesting from the user. The Discord Social SDK provides two helper methods that cover the most common use cases:

| Helper Method                             | Scopes Requested                   | Features Enabled                                                                  |
| ----------------------------------------- | ---------------------------------- | --------------------------------------------------------------------------------- |
| [`Client::GetDefaultPresenceScopes`]      | `openid sdk.social_layer_presence` | Account linking, friends list, rich presence                                      |
| [`Client::GetDefaultCommunicationScopes`] | `openid sdk.social_layer`          | All of the above, plus lobbies, voice chat, direct messaging, and linked channels |

Start with [`Client::GetDefaultPresenceScopes`] unless you know you need the communication features. You can always add more scopes later as your integration expands. See the [OAuth2 Scopes guide](/developers/discord-social-sdk/core-concepts/oauth2-scopes) for full details.

#### Authorization Code Verifier

If you are using [`Client::GetToken`] in [Step 4](/developers/discord-social-sdk/development-guides/account-linking-with-discord#step-4-exchanging-the-authorization-code-for-an-access-token), you will need to specify a "code challenge" and "code verifier" in your requests. We'll spare you the boring details of how that works (woo… crypto), as we've made a simple function to create these for you, [`Client::CreateAuthorizationCodeVerifier`], which you can use to generate the code challenge and verifier.

```cpp theme={null}
// Create a code verifier and challenge if using GetToken
auto codeVerifier = client->CreateAuthorizationCodeVerifier();
discordpp::AuthorizationArgs args{};
args.SetClientId(YOUR_DISCORD_APPLICATION_ID);
args.SetScopes(discordpp::Client::GetDefaultPresenceScopes());
args.SetCodeChallenge(codeVerifier.Challenge());

client->Authorize(args, [client, codeVerifier](discordpp::ClientResult result, std::string code, std::string redirectUri) {
  if (!result.Successful()) {
    std::cerr << "❌ Authorization Error: " << result.Error() << std::endl;
  } else {
    std::cout << "✅ Authorization successful! Next step: exchange code for an access token \n";
  }
});
```

### Step 2: User Approval

After calling [`Client::Authorize`], the SDK will open a browser window, Discord client, or an in-game overlay to prompt the user to approve the request.

### Step 3: Receiving the Authorization Code

Once the user approves the request from Step 2, Discord will redirect the user back to your app with an authorization code that you can use to exchange for an access token.

### Step 4: Exchanging the Authorization Code for an Access Token

#### Server-to-Server Get Token Exchange

If your application uses a backend server and does **not** have `Public Client` enabled, you can manually exchange the authorization code for an access token using the Discord API.

```python theme={null}
import requests

API_ENDPOINT = 'https://discord.com/api/v10'
CLIENT_ID = 'YOUR_CLIENT_ID'
CLIENT_SECRET = 'YOUR_CLIENT_SECRET'

def exchange_code(code, redirect_uri, code_verifier):
    data = {
        'grant_type': 'authorization_code',
        'code': code,
        'redirect_uri': redirect_uri,
        'code_verifier': code_verifier
    }
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    r = requests.post(f'{API_ENDPOINT}/oauth2/token', data=data, headers=headers, auth=(CLIENT_ID, CLIENT_SECRET))
    r.raise_for_status()
    return r.json()
```

#### Example Response

```json theme={null}
{
  "access_token": "<access token>",
  "token_type": "Bearer",
  "expires_in": 604800,
  "refresh_token": "<refresh token>",
  "scope": "sdk.social_layer"
}
```

#### Token Exchange for Public Clients

<Warning>
  This method requires enabling **Public Client** for your app. Most games will not want to ship with this enabled. [Learn more](/developers/discord-social-sdk/core-concepts/oauth2-scopes#oauth2-client-types)
</Warning>

If your app does not have a backend server, enable `Public Client` in the Discord Developer Portal and use [`Client::GetToken`] to automatically exchange the authorization code for a token.

We will also need the code verifier used to generate the code challenge in Step 1.

```cpp theme={null}
client->GetToken(YOUR_DISCORD_APPLICATION_ID, code, codeVerifier.Verifier(), redirectUri,
  [client](discordpp::ClientResult result,
    std::string accessToken,
    std::string refreshToken,
    discordpp::AuthorizationTokenType tokenType,
    int32_t expiresIn,
    std::string scope) {
    std::cout << "🔓 Access token received! Establishing connection...\n";
    // Next step: Update the token in the client and connect to Discord
  });
```

***

## Working with Tokens

Once you've received your access token, you'll want to set the token in the SDK. You can use [`Client::UpdateToken`] to do that. At this point, you're authorized and ready to go! You'll want to store the player's access token and refresh tokens somewhere.

Please note that the `access_token` values do expire. You'll need to use the `refresh_token` to refresh the player's access token.

```cpp theme={null}
client->UpdateToken(discordpp::AuthorizationTokenType::Bearer, ACCESS_TOKEN_VALUE, [client](discordpp::ClientResult result) {
  client->Connect();
);
```

***

## Refreshing Access Tokens

Access tokens expire after 7 days, requiring refresh tokens to get a new one.

### Server-to-Server Token Refresh

If you're handling authentication on your server, send an API request to refresh the token.

```python theme={null}
import requests

API_ENDPOINT = 'https://discord.com/api/v10'
CLIENT_ID = 'YOUR_CLIENT_ID'
CLIENT_SECRET = 'YOUR_CLIENT_SECRET'

def refresh_token(refresh_token):
    data = {
        'grant_type': 'refresh_token',
        'refresh_token': refresh_token
    }
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    r = requests.post(f'{API_ENDPOINT}/oauth2/token', data=data, headers=headers, auth=(CLIENT_ID, CLIENT_SECRET))
    r.raise_for_status()
    return r.json()
```

### Refreshing Access Tokens for Public Clients

<Warning>
  This method requires enabling **Public Client** for your app. Most games will not want to ship with this enabled. [Learn more](/developers/discord-social-sdk/core-concepts/oauth2-scopes#oauth2-client-types)
</Warning>

The easiest way to refresh tokens is using the SDK's [`Client::RefreshToken`] method.

```cpp theme={null}
client->RefreshToken(
      YOUR_DISCORD_APPLICATION_ID, GetRefreshToken(),
      [client](discordpp::ClientResult result, std::string accessToken,
               std::string refreshToken,
               discordpp::AuthorizationTokenType tokenType, int32_t expiresIn,
               std::string scope) {
        if (!result.Successful()) {
          std::cout << "❌ Error refreshing token: " << result.Error()
                    << std::endl;
          return;
        }

        // Update token and connect
        UpdateToken(client, refreshToken, accessToken);
      });
```

***

## Revoking Access Tokens

If a user wants to disconnect their Discord account or if a token is compromised, you can revoke access and refresh tokens.

<Warning>
  When any valid access or refresh token is revoked, all of your application's access and refresh tokens for that user are immediately invalidated.
</Warning>

### Server-to-Server Token Revocation

If your application uses a backend server, you can revoke tokens by making an API request to Discord's token revocation endpoint.

```python theme={null}
import requests

API_ENDPOINT = 'https://discord.com/api/v10'
CLIENT_ID = 'YOUR_CLIENT_ID'
CLIENT_SECRET = 'YOUR_CLIENT_SECRET'

def revoke_token(access_or_refresh_token):
    data = {'token': access_or_refresh_token}
    headers = {'Content-Type': 'application/x-www-form-urlencoded'}
    r = requests.post(f'{API_ENDPOINT}/oauth2/token/revoke', data=data, headers=headers, auth=(CLIENT_ID, CLIENT_SECRET))
    r.raise_for_status()
```

### Revoking Access Tokens for Public Clients

<Warning>
  This method requires enabling **Public Client** for your app. Most games will not want to ship with this enabled. [Learn more](/developers/discord-social-sdk/core-concepts/oauth2-scopes#oauth2-client-types)
</Warning>

The easiest way to revoke tokens is using the SDK's `Client::RevokeToken` method. This will invalidate all access and refresh tokens for the user and they cannot be used again.

```cpp theme={null}
client->RevokeToken(YOUR_DISCORD_APPLICATION_ID,
                    accessToken, // Can also use refresh token
                    [](const discordpp::ClientResult &result) {
                      if (!result.Successful()) {
                        std::cout
                            << "? Error revoking token: " << result.Error()
                            << std::endl;
                        return;
                      }

                      std::cout
                          << "? Token successfully revoked! User logged out."
                          << std::endl;
                      // Handle successful logout (clear stored tokens,
                      // redirect to login, etc.)
                    });
```

### Handling User Initiated Revocation

Users can unlink their account by removing access to your application on their Discord `User Settings -> Authorized Apps` page.

If you would like to be notified when a user unlinks this way, you can [configure you application to listen for the `APPLICATION_DEAUTHORIZED` webhook event](/developers/events/webhook-events#application-deauthorized).
Otherwise, you will know that the user has unlinked because their access token and refresh token (if you have one) will be invalidated.

***

## Next Steps

Now that you've successfully implemented account linking with Discord, you can integrate more social features into your game.

<CardGroup cols={3}>
  <Card title="Design: Signing In" href="/developers/discord-social-sdk/design-guidelines/signing-in" icon={<PaintPaletteIcon />}>
    Design guidelines for account linking and user authentication
  </Card>

  <Card title="Creating a Unified Friends List" href="/developers/discord-social-sdk/development-guides/creating-a-unified-friends-list" icon={<ListViewIcon />}>
    Combine Discord and game friends into a single list for easy management.
  </Card>

  <Card title="Setting Rich Presence" href="/developers/discord-social-sdk/development-guides/setting-rich-presence" icon={<UserIcon />}>
    Display game status and information to Discord friends.
  </Card>
</CardGroup>

Need help? Join the [Discord Developers Server](https://discord.gg/discord-developers) and share questions in the `#social-sdk-dev-help` channel for support from the community.

If you encounter a bug while working with the Social SDK, please report it here:  [https://dis.gd/social-sdk-bug-report](https://dis.gd/social-sdk-bug-report)

***

## Change Log

| Date           | Changes         |
| -------------- | --------------- |
| March 17, 2025 | initial release |

[`Client::Authorize`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#ace94a58e27545a933d79db32b387a468

[`Client::CreateAuthorizationCodeVerifier`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#aba6adc1f978e7bf4c5433c560e1ad704

[`Client::GetDefaultCommunicationScopes`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a71499da752fbdc2d4326ae0fd36c0dd1

[`Client::GetDefaultPresenceScopes`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a7648bd1d2f7d9a86ebd0edb8bef12b5c

[`Client::GetToken`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#aaee636f91fb1ea3465157c20313b702c

[`Client::RefreshToken`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a187af0f99f94b3b9a4ad4302f6a443e7

[`Client::UpdateToken`]: https://discord.com/developers/docs/social-sdk/classdiscordpp_1_1Client.html#a606b32cef7796f7fb91c2497bc31afc4
