Skip to content

Two factor authentication (2FA) using a one time password (OTP)

Roberto Graham edited this page Feb 11, 2019 · 2 revisions

Logging in with an account that has 2FA enabled

Note: If you have successfully logged in using 2FA with your device ID before, you should log in without 2FA on next login and supply the same device ID. The internally created device ID is unique to your network card

Using internally created device ID

import io.github.robertograham.fortnite2.implementation.DefaultFortnite.Builder;
import io.github.robertograham.fortnite2.implementation.EpicGamesErrorException;

import java.io.IOException;
import java.util.Scanner;

public final class Main {

    public static void main(final String[] args) {
        try (final var fortnite = Builder.newInstance("epicGamesEmailAddress", "epicGamesPassword")
            .build()) {
            System.out.println("Normal auth success!");
        } catch (final EpicGamesErrorException exception) {
            if ("errors.com.epicgames.common.two_factor_authentication.required".equals(exception.type())
                && exception.jsonObject()
                .isPresent()) {
                final var challengeString = exception.jsonObject()
                    .map((final var jsonObject) -> jsonObject.getString("challenge", null))
                    .orElseThrow();
                System.out.print("Supply 2FA code: ");
                try (
                    final var scanner = new Scanner(System.in);
                    final var fortnite = Builder.newInstance("", "")
                        .setTwoFactorAuthChallengeAndCodePair(challengeString, scanner.next())
                        .build()
                ) {
                    System.out.println("2FA success!");
                } catch (final IOException ioException) {
                    ioException.printStackTrace();
                }
            }
        } catch (final IOException exception) {
            exception.printStackTrace();
        }
    }
}

Using your own device ID

import io.github.robertograham.fortnite2.implementation.DefaultFortnite.Builder;
import io.github.robertograham.fortnite2.implementation.EpicGamesErrorException;

import java.io.IOException;
import java.util.Scanner;

public final class Main {

    public static void main(final String[] args) {
        final var deviceId = "myDeviceId";
        try (final var fortnite = Builder.newInstance("epicGamesEmailAddress", "epicGamesPassword")
            .setDeviceId(deviceId)
            .build()) {
            System.out.println("Normal auth success!");
        } catch (final EpicGamesErrorException exception) {
            if ("errors.com.epicgames.common.two_factor_authentication.required".equals(exception.type())
                && exception.jsonObject()
                .isPresent()) {
                final var challengeString = exception.jsonObject()
                    .map((final var jsonObject) -> jsonObject.getString("challenge", null))
                    .orElseThrow();
                System.out.print("Supply 2FA code: ");
                try (
                    final var scanner = new Scanner(System.in);
                    final var fortnite = Builder.newInstance("", "")
                        .setDeviceId(deviceId)
                        .setTwoFactorAuthChallengeAndCodePair(challengeString, scanner.next())
                        .build()
                ) {
                    System.out.println("2FA success!");
                } catch (final IOException ioException) {
                    ioException.printStackTrace();
                }
            }
        } catch (final IOException exception) {
            exception.printStackTrace();
        }
    }
}

Language-agnostic 2FA flow explanation

  1. With the header X-Epic-Device-ID set to any non-empty value attempt the standard password grant_type request for a token object. Note: If you have successfully logged in using 2FA with this device ID before, you should log in without 2FA on next login and supply the same device ID.
  2. If the account you used has 2FA enabled, this request will fail and a JSON error object with the following structure will be returned:
{
  "errorCode": "errors.com.epicgames.common.two_factor_authentication.required",
  "errorMessage": "Two-Factor authentication required to process request.",
  "messageVars": [],
  "numericErrorCode": 1042,
  "originatingService": "com.epicgames.account.public",
  "intent": "prod",
  "challenge": "unique value to be used later"
}
  1. Now find your 2FA code either from an email sent to the account in use's email address or from an authenticator app
  2. With the SAME VALUE SET FOR HEADER X-Epic-Device-ID make the following request:
Method: POST
URL: https://account-public-service-prod03.ol.epicgames.com/account/api/oauth/token
Headers: [Authorization: "basic <epicGamesLauncherToken>"], [Content-Type: "application/x-www-form-urlencoded"]
Body:
    grant_type: otp
    otp: <your 2FA code>
    challenge: <value of the "challenge" field in the previous JSON error object>
  1. The above request will return the standard token object used to obtain an exchange code