Authorization

A significant portion of Dead by Daylight's private API endpoints require authorization from an existing Dead by Daylight account to be used. Authorization is managed through secure token-based authentication, ensuring that only authenticated users can access the requested resources.


OAuth 2.0

Epic Online Services (EOS) uses the OAuth 2.0 protocol for authentication and authorization, supporting common-use cases for web servers and client-side applications. Epic has also introduced custom grant types for some specific use cases. You can read more about how this process works here.

OAuth Server Endpoints
  • https://api.epicgames.dev/epic/oauth/v2/exchange?consumingClientId={consumingClientId}&codeChallenge={codeChallenge}&codeChallengeMethod={codeChallengeMethod}
  • Endpoint for exchanging an authorization code for an access token. consumingClientId is the client application that is making the request, codeChallenge is the value generated from the code verifier (a cryptographically random string) that the client creates, and codeChallengeMethod is the method used to create the codeChallenge. EOS uses the SHA-256 hashing algorithm to secure the code challenge in the Proof Key for Code Exchange (PKCE) flow.

  • https://api.epicgames.dev/epic/oauth/v2/token
  • Endpoint for obtaining an access token, refresh token, and other identity information after an authorization code has been exchanged.

  • https://api.epicgames.dev/epic/oauth/v2/tokenInfo
  • Endpoint for retrieving detailed information about a given access token. When a client sends a valid access token, the endpoint returns metadata about that token.

  • https://api.epicgames.dev/epic/oauth/v2/revoke
  • Endpoint that allows clients to implement a "log out" feature by invalidating tokens, ensuring that any security credentials or access rights associated with the session are removed. This endpoint implements RFC 7009 - OAuth 2.0 Token Revocation.

    Errors

    The endpoints above will return error messages according to the relevant RFC.


    Client Types

    OAuth defines two types of clients: confidential clients and public clients.

    Confidential Clients

    Confidential clients are applications that can securely authenticate with the authorization server. In OAuth 2.0, this involves both a client ID and a client secret.

    The client ID is a public identifier for applications registered with an OAuth 2.0 authorization server. The client ID must be unique across all clients managed by the authorization server to ensure that requests can be correctly attributed to the appropriate application.

    The client secret is a confidential credential that is known exclusively to both the application and the authorization server. It acts as the application's password, playing a crucial role in ensuring secure communication between the application and the server.

    These clients may use the authorization_code, client_credentials, exchange_code, password, and refresh_token grant types.

    Confidential clients can have ID tokens issued to them either symmetrically using their client secret (HS256) or asymmetrically using a private key (RS256) because they can securely store secrets.

    Public Clients

    Public clients, such as applications running in a browser or on a mobile device, cannot use registered client secrets.

    These clients may only use grant types that do not require the use of their client secret. They cannot send a client secret because they can't maintain the confidentiality of the credentials required.

    Because public clients cannot securely hold secrets, ID tokens issued to them must be signed asymmetrically using a private key (RS256) and verified using the corresponding public key.

    Tokens

    When attempting to play Dead by Daylight, the client interacts with Epic Games' OAuth 2.0 authentication system, which provides access tokens, refresh tokens, and ID tokens.

    Access Token

    An access token is issued by the authorization server to allow the client to access protected resources on behalf of the user. This type of token lasts for 2 hours from the time that it is issued.

    Refresh Token

    A refresh token is used to obtain a new access token without requiring the user to re-authenticate. This type of token lasts for 8 hours from the time that it is issued.

    ID Token

    An ID token is part of the OpenID Connect protocol, which provides a standardized way to authenticate and retrieve basic user information, and is used to authenticate the user's identity. It contains user information in the form of claims (for example, Epic Account ID, Epic Account display name, client ID used to authenticate the user with Epic Account Services, and other identity details). This type of token lasts for 2 hours from the time that it is issued.


    Available Scopes

    When the client attempts to connect to Dead by Daylight's servers, it requests specific scopes as part of the OAuth 2.0 authorization flow. The scope "basic_profile friends_list openid presence" defines the resources and permissions the client requires:

  • basic_profile: Allows the client to authenticate the user with Epic Account Services and access basic profile information like the user's screen name. It may also allow certain account actions like making in-game purchases, but the specifics depend on the service integration.
  • friends_list: Grants the client access to the user's list of friends to display in-game, which could be used for social features or multiplayer connections.
  • openid: Allows the client to request an ID token.
  • presence: Allows the client to access and display information about both the user's basic status and game-specific status. Basic status includes generic information such as whether the user is online or offline, what game they are playing (provided the user has agreed to share information about that game), and so on. Game-specific status contains information particular to the game the user is playing, if any.

  • Grant Types

    Authorization Code Grant

    This grant is used by confidential and public clients to exchange an authorization code for an access token. After the user returns to the client via the redirect URL, the application will get the authorization code from the URL and use it to request an access token. You can read about its flow here.

    Note that authenticating with this method only works on clients that have a redirect URL configured. There is no redirect URL configured for the Dead by Daylight client, so I will use this method with fortnitePCGameClient to explain how this process works. Importantly, jaren.wtf's unofficial Epic Games Client Documentation shows that fortnitePCGameClient's client ID is ec684b8c687f479fadea3cb2ad83f5c6 and its client secret is e1f31c211f28413186262d37a13fc84d.

    Method

    1. Determine the client that you want to get an access token for.

    2. Ensure that you are logged in at Epic Games.

    3. Open https://www.epicgames.com/id/api/redirect?clientId=:clientId&responseType=code in your web browser, replacing :clientId with the chosen client ID. In this case, that would be ec684b8c687f479fadea3cb2ad83f5c6.

    4. If performed successfully, then you will receive a response with the following structure:

    {
    "redirect_Url": string,
    "authorizationCode": string,
    "exchangeCode": null,
    "sid": null,
    "ssoV2Enabled": boolean
    }
    Key Type Description
    redirect_Url String The URL where the user will be redirected after authentication. It contains the authorization code as a query parameter, which the client can later exchange for an access token.
    authorizationCode String A temporary authorization code issued after the user successfully logs in. This code is used in the next step to request an access token.
    exchangeCode String (can be null) A code used to exchange for an access token in specific OAuth flows. This field is null if the exchange code hasn't been issued yet or isn't required for this flow.
    sid String (can be null) Represents the session ID (SID) for the user's authentication session. It is null if not applicable or not yet assigned during this process.
    ssoV2Enabled Boolean Indicates whether Single Sign-On (SSO) version 2 is enabled for this authentication flow. If it is true, then the system supports SSOv2, meaning that the user can authenticate across multiple services without re-entering credentials.

    Note that the authorization code expires after 5 minutes. If step 5 is not completed within 5 minutes of following step 3, then you will have to generate a new authorization code.

    5. Send a POST request to https://account-public-service-prod.ol.epicgames.com/account/api/oauth/token:

    Request Headers:

    Content-Type: application/x-www-form-urlencoded
    Authorization: Basic {client_id:client_secret}

    Note that client_id:client_secret needs to be encoded in Base64.

    Request Body:

    grant_type=authorization_code&code={authorizationCode}

    Note that authorizationCode comes from the response in step 4.

    Example: Authenticating to fortnitePCGameClient

    Request Headers:

    Content-Type: application/x-www-form-urlencoded
    Authorization: Basic ZWM2ODRiOGM2ODdmNDc5ZmFkZWEzY2IyYWQ4M2Y1YzY6ZTFmMzFjMjExZjI4NDEzMTg2MjYyZDM3YTEzZmM4NGQ=

    Request Body:

    grant_type=authorization_code&code={authorizationCode}

    If performed successfully, then you will receive a response with the following structure:

    {
    "access_token": string,
    "expires_in": 7200,
    "expires_at": string,
    "token_type": "bearer",
    "refresh_token": string,
    "refresh_expires": 28800,
    "refresh_expires_at": string,
    "account_id": string,
    "client_id": "ec684b8c687f479fadea3cb2ad83f5c6",
    "internal_client": true,
    "client_service": "prod-fn",
    "scope": [
    "basic_profile"
    ],
    "displayName": string,
    "app": "prod-fn",
    "in_app_id": string,
    "device_id": string,
    "product_id": "prod-fn",
    "application_id": string,
    "acr": "urn:epic:loa:aal2",
    "auth_time": string
    }
    Key Type Description
    access_token String The OAuth 2.0 access token that grants temporary access to the application resources.
    expires_in Number The time (in seconds) until the access token expires.
    expires_at String The timestamp (in ISO 8601 format) indicating when the access token will expire.
    token_type String Specifies the token type.
    refresh_token String The token used to obtain a new access token once the original expires.
    refresh_expires Number The time (in seconds) until the refresh token expires.
    refresh_expires_at String The timestamp (in ISO 8601 format) indicating when the refresh token will expire.
    account_id String The ID of the user's account in Epic Games services.
    client_id String The ID of the client making the request, which is typically the application.
    internal_client Boolean Indicates if the client is internal to Epic systems.
    client_service String The service related to the client.
    scope Array The permissions granted to the token, detailing what the client can access.
    displayName String The display name of the user associated with the account.
    app String The application requesting the token.
    in_app_id String The user's ID specific to the application (used within the app).
    device_id String The ID of the device being used for the request.
    product_id String The ID of the product the token is associated with.
    application_id String The ID of the application requesting the token. This may differ from client_id in cases where multiple applications share the same client.
    acr String The strength of the authentication used.
    auth_time String The timestamp (in ISO 8601 format) indicating when authentication occurred.
    Client Credentials Grant

    This grant is used by clients to obtain an access token outside of the context of a user. This is used by clients to access resources about themselves rather than to access a user's resources. You can read about its flow here.

    Method

    1. Determine the client that you want to get an access token for.

    2. Send a POST request to https://api.epicgames.dev/auth/v1/oauth/token:

    Request Headers:

    Content-Type: application/x-www-form-urlencoded
    Authorization: Basic {client_id:client_secret}

    Note that client_id:client_secret needs to be encoded in Base64.

    Request Body:

    grant_type=client_credentials
    Example: Authenticating to Dead by Daylight Client

    You can recover both the client ID and client secret from the Dead by Daylight client by capturing its network traffic as you launch the game from the Epic Games Launcher. Specifically, if you observe the "Authorization" request header of any requests sent to https://api.epicgames.dev/auth/v1/oauth/token or https://api.epicgames.dev/epic/oauth/v2/token, then you will see that the header value is Basic eHl6YTc4OTFzSGQ4NDdVeEI0cG54WjMwT2hRRXFNZXQ6SXdYNEg4bmRDbmE0R1RpRDhMVFkyT3hqSDJncG5uYkt6cTRCaHFkL250RQ==. You can use this website to decode the Base64-encoded text. In this case, eHl6YTc4OTFzSGQ4NDdVeEI0cG54WjMwT2hRRXFNZXQ6SXdYNEg4bmRDbmE0R1RpRDhMVFkyT3hqSDJncG5uYkt6cTRCaHFkL250RQ== decodes into xyza7891sHd847UxB4pnxZ30OhQEqMet:IwX4H8ndCna4GTiD8LTY2OxjH2gpnnbKzq4Bhqd/ntE, meaning that the client ID is xyza7891sHd847UxB4pnxZ30OhQEqMet and the client secret is IwX4H8ndCna4GTiD8LTY2OxjH2gpnnbKzq4Bhqd/ntE.

    Request Headers:

    Content-Type: application/x-www-form-urlencoded
    Authorization: Basic eHl6YTc4OTFzSGQ4NDdVeEI0cG54WjMwT2hRRXFNZXQ6SXdYNEg4bmRDbmE0R1RpRDhMVFkyT3hqSDJncG5uYkt6cTRCaHFkL250RQ==

    Request Body:

    grant_type=client_credentials

    If performed successfully, then you will receive a response with the following structure:

    {
    "access_token": string,
    "token_type": "bearer",
    "expires_at": string,
    "features": [
    "Achievements",
    "AntiCheat",
    "Ecom",
    "Matchmaking",
    "Metrics",
    "PlayerReports",
    "Sanctions",
    "Stats"
    ],
    "organization_id": "o-2ctdycbd3jxm6a26vpz5d4xv872smu",
    "product_id": "2b2299be8ae84d679d4dc57c55af1510",
    "expires_in": 3599
    }
    Key Type Description
    access_token String The OAuth 2.0 access token that grants temporary access to the application resources.
    token_type String Specifies the token type.
    expires_at String The timestamp (in ISO 8601 format) indicating when the access token will expire.
    features Array A list of features enabled for the access token.
    organization_id String A unique identifier for the organization associated with the token.
    product_id String A unique identifier for the product associated with the token.
    expires_in Number The time (in seconds) until the access token expires.
    Exchange Code Grant

    This grant allows a client to exchange a short-lived authorization code for an access token. Note that, because Epic has removed the endpoint that made it possible to get an exchange code through a browser, the only way to get an exchange code at this point is to launch the selected game using the Epic Games Launcher. That being said, you can still recover the access token by capturing the network traffic of a game as you launch it from the Epic Games Launcher. Specifically, if you observe the request sent to https://api.epicgames.dev/epic/oauth/v2/token after launching the game, then you will see a response with the following structure:

    {
    "scope": string,
    "token_type": string,
    "access_token": string,
    "refresh_token": string,
    "id_token": string,
    "expires_in": number,
    "expires_at": string,
    "refresh_expires_in": number,
    "refresh_expires_at": string,
    "account_id": string,
    "client_id": string,
    "application_id": string,
    "selected_account_id": string,
    "merged_accounts": [],
    "acr": string,
    "auth_time": string
    }
    Key Type Description
    scope String The permissions granted to the token, detailing what the client can access.
    token_type String Specifies the token type.
    access_token String The OAuth 2.0 access token that grants temporary access to the application resources.
    refresh_token String The token used to obtain a new access token once the original expires.
    id_token String A token that carries information about the user in the form of claims.
    expires_in Number The time (in seconds) until the access token expires.
    expires_at String The timestamp (in ISO 8601 format) indicating when the access token will expire.
    refresh_expires_in Number The time (in seconds) until the refresh token expires.
    refresh_expires_at String The timestamp (in ISO 8601 format) indicating when the refresh token will expire.
    account_id String The ID of the user's account in Epic Games services.
    client_id String The ID of the client making the request, which is typically the application.
    application_id String The ID of the application requesting the token. This may differ from client_id in cases where multiple applications share the same client.
    selected_account_id String The account ID that was chosen if the user has multiple accounts linked to the service.
    merged_accounts Array An array of account IDs that were merged into the primary account.
    acr String The strength of the authentication used.
    auth_time String The timestamp (in ISO 8601 format) indicating when authentication occurred.
    Example: Authenticating to Dead by Daylight Client

    Request Headers:

    Host: api.epicgames.dev
    Accept-Encoding: identity
    Content-Type: application/x-www-form-urlencoded
    Accept: application/json
    Authorization: Basic eHl6YTc4OTFzSGQ4NDdVeEI0cG54WjMwT2hRRXFNZXQ6SXdYNEg4bmRDbmE0R1RpRDhMVFkyT3hqSDJncG5uYkt6cTRCaHFkL250RQ==
    X-Epic-Correlation-ID: {X-Epic-Correlation-ID}
    User-Agent: EOS-SDK/{X-EOS-Version} ({os_name}/{os_version}.{os_build}.{architecture}) DeadByDaylight/{version}
    X-EOS-Version: {sdk_version}-{build_number}
    Content-Length: {Content-Length}
    ,

    where X-Epic-Correlation-ID is a unique identifier used to track requests across Epic's services, X-EOS-Version is the EOS SDK version followed by the build number, os_name is the name of the operating system, os_version is the version number of the operating system, os_build is the the specific build of the operating system, architecture is the system's architecture, version is the version of the game, sdk_version is the EOS SDK version, build_number is the EOS SDK build number, and Content-Length is the size of the request body in bytes.

    Request Body:

    grant_type=exchange_code&scope=basic_profile+friends_list+presence+openid&exchange_code={exchange_code}&deployment_id={deployment_id}
    ,

    where exchange_code is the exchange code and deployment_id is a unique identifier that represents a specific game deployment integrated with EOS.

    Response:

    {
    "scope": "basic_profile friends_list openid presence",
    "token_type": "bearer",
    "access_token": string,
    "refresh_token": string,
    "id_token": string,
    "expires_in": 7200,
    "expires_at": string,
    "refresh_expires_in": 28800,
    "refresh_expires_at": string,
    "account_id": string,
    "client_id": "xyza7891sHd847UxB4pnxZ30OhQEqMet",
    "application_id": string,
    "selected_account_id": string,
    "merged_accounts": [],
    "acr": "AAL1",
    "auth_time": string
    }
    Refresh Token Grant

    This grant is used by clients to exchange a refresh token for an access token when the access token has expired. This allows clients to continue to have a valid access token without further interaction with the user. You can read about its flow here.

    Method for Authenticating to Dead by Daylight Client

    1. Determine the client that you want to get a refresh token for.

    2. In general, you will receive a refresh_token property at the final step of the authorization code grant. However, as discussed previously, you cannot authenticate to Dead by Daylight using this grant. Instead, in the case of Dead by Daylight, you will receive a refresh_token property at the final step of the exchange code grant. This token lasts for 8 hours and can be exchanged to generate a new access token without requesting the user's consent again.

    3. Launch Dead by Daylight using the Epic Games Launcher while your network traffic capture application is running.

    4. Once you load to the title screen (where Dead by Daylight has you "PRESS SPACE TO CONTINUE"), return to your network traffic capture application.

    5. Find the session associated with the exchange_code grant_type (this will be the request sent to https://api.epicgames.dev/epic/oauth/v2/token).

    6. In the response body, you will see the refresh_token key and its associated value. Right-click on it and left-click on "Copy".

    7. Send a POST request to https://account-public-service-prod.ol.epicgames.com/account/api/oauth/token:

    Request Headers:

    Content-Type: application/x-www-form-urlencoded
    Authorization: Basic eHl6YTc4OTFzSGQ4NDdVeEI0cG54WjMwT2hRRXFNZXQ6SXdYNEg4bmRDbmE0R1RpRDhMVFkyT3hqSDJncG5uYkt6cTRCaHFkL250RQ==

    Request Body:

    grant_type=refresh_token&refresh_token={refresh_token}

    Note that refresh_token comes from the response in step 6.

    8. If performed successfully, then you will receive a response with the following structure:

    {
    "access_token": string,
    "expires_in": 7200,
    "expires_at": string,
    "token_type": "bearer",
    "refresh_token": string,
    "refresh_expires": 28800,
    "refresh_expires_at": string,
    "account_id": string,
    "client_id": "xyza7891sHd847UxB4pnxZ30OhQEqMet",
    "internal_client": false,
    "client_service": "2b2299be8ae84d679d4dc57c55af1510",
    "scope": [
    "basic_profile",
    "friends_list",
    "openid",
    "presence"
    ],
    "displayName": string,
    "app": "2b2299be8ae84d679d4dc57c55af1510",
    "in_app_id": string,
    "device_id": string,
    "product_id": "2b2299be8ae84d679d4dc57c55af1510",
    "sandbox_id": "611482b8586142cda48a0786eb8a127c",
    "deployment_id": string,
    "application_id": string,
    "acr": "urn:epic:loa:aal1",
    "auth_time": string
    }
    Key Type Description
    access_token String The OAuth 2.0 access token that grants temporary access to the application resources.
    expires_in Number The time (in seconds) until the access token expires.
    expires_at String The timestamp (in ISO 8601 format) indicating when the access token will expire.
    token_type String Specifies the token type.
    refresh_token String The token used to obtain a new access token once the original expires.
    refresh_expires Number The time (in seconds) until the refresh token expires.
    refresh_expires_at String The timestamp (in ISO 8601 format) indicating when the refresh token will expire.
    account_id String The ID of the user's account in Epic Games services.
    client_id String The ID of the client making the request, which is typically the application.
    internal_client Boolean Indicates if the client is internal to Epic systems.
    client_service String The service related to the client.
    scope Array The permissions granted to the token, detailing what the client can access.
    displayName String The display name of the user associated with the account.
    app String The application requesting the token.
    in_app_id String The user's ID specific to the application (used within the app).
    device_id String The ID of the device being used for the request.
    product_id String The ID of the product the token is associated with.
    sandbox_id String The environment the API requests and responses belong to.
    deployment_id String A unique identifier that represents a specific game deployment integrated with EOS.
    application_id String The ID of the application requesting the token. This may differ from client_id in cases where multiple applications share the same client.
    acr String The strength of the authentication used.
    auth_time String The timestamp (in ISO 8601 format) indicating when authentication occurred.