Authentication with Steam #

In this section, we’ll log into the platform with Steam. This method is appropriate for use in production.

Prerequisites:

Acquire the Steam Application ID and Steamworks Web API key #

This guide assumes that you have already created and published your game on Steam. Consult Valve’s official Steam documentation for further assistance.
  1. Log into Steamworks.
  2. Hover over Users & Permissions, then click Manage Groups.

  1. Select a group or create a new group.

  1. Create or view your Steamworks Web API Key.
Create a key

If a key doesn’t yet exist, you must create one by clicking Create WebAPI Key. It will then appear.

View an existing key

If you selected an existing group which already has a Web API key, you’ll see it listed under the Web API box on the right-hand side.

  1. Take note of your game’s Steam Application ID. Hover over Users & Permissions, then click View Applications. The number that appears in the App Name column beneath the game name is the Steam Application ID.

Configure the Pragma Engine Steam Identity Provider #

  1. Navigate to the pragma-engine/platform/PROJECT/config/ directory and open local-dev.yml.

  2. Insert the following code while making sure to edit in your Application ID and Web API Key:

Be sure to nest the configuration under AccountService.identityProviderPlugins if you already have other identity providers configured.
social:
  shared:
    configs:
      Steam: # credentials are configured here to be used by any service or plugin that needs to make calls to this provider
        class: "pragma.shared.SteamCredentialsConfig"
        config:
          appId: "${steamAppId}"
          steamWebAPIKey: "${steamWebApiKey}"
  pluginConfigs:
    AccountService.identityProviderPlugins:
      plugins:
        Steam:
          class: "pragma.account.SteamIdentityProviderPlugin"
          config:
            sharedConfigKey: "Steam" # must match key under shared - can be customized
            restrictByAppOwnership: false
            restrictByAccountBan: false
            playerLoginEnabled: true
            operatorLoginEnabled: false
            accountLinkingEnabled: true
            accountUnlinkingEnabled: false
            accountLinkingCooldownInDays: 0
            accountLinkingOneAssociationOnly: false
            showPortalLoginButton: false
            visibleToOtherPlayers: true
steamWebAPIKey does not need to be encrypted when running Pragma Engine locally.
  1. Run Pragma Engine via one of the following methods.
Running via Command Line
From your pragma-engine/platform working directory, run ./pragma run to start the platform.
Running in IntelliJ
Run Pragma from the IDE by selecting the ‘Run Pragma’ run configuration from the dropdown in the upper right.

Once the engine has started successfully, it prints the message INFO main - Pragma server startup complete.

Enable Unreal’s Steam plugin #

You will need to replace your_app_id with your app’s Steam App ID, and your_service_identity with an identifier of your choosing for the service that validates the ticket (see the note below).
  1. Open DefaultEngine.ini located in the Unreal Projects/[Project name]/Config directory and add the following configs:
[/Script/Engine.GameEngine]
+NetDriverDefinitions=(DefName="GameNetDriver",DriverClassName="OnlineSubsystemSteam.SteamNetDriver",DriverClassNameFallback="OnlineSubsystemUtils.IpNetDriver")

[OnlineSubsystem]
DefaultPlatformService=Steam

[OnlineSubsystemSteam]
bEnabled=true
SteamDevAppId=your_app_id
DefaultRemoteServiceIdentity=your_service_identity

[/Script/OnlineSubsystemSteam.SteamNetDriver]
NetConnectionClassName="OnlineSubsystemSteam.SteamNetConnection"

[PacketHandlerComponents]
+Components=OnlineSubsystemSteam.SteamAuthComponentModuleInterface

DefaultRemoteServiceIdentity is required when acquiring a ticket with the "WebAPI" token type (used by GetLinkedAccountAuthToken in the login code below). Unreal’s Steam Online Subsystem reads this value and passes it to Steam’s GetAuthTicketForWebApi, which bakes it into the ticket as the identity of the service that will validate it; if it is left unset, ticket acquisition fails with LogOnlineIdentity: Warning: STEAM: FOnlineIdentitySteam::GetLinkedAccountAuthToken DefaultRemoteServiceIdentity not set. The value is an arbitrary string you choose (for example, your game or backend name) - Pragma Engine validates the ticket without requiring a matching identity, so any non-empty value works.

Alternatively, you can skip this config setting and supply the identity inline in the token type, appended after a colon - for example GetLinkedAccountAuthToken(0, TEXT("WebAPI:your_service_identity"), ...). When the token type contains a colon, the part after it is used as the identity and DefaultRemoteServiceIdentity is ignored; the config value is only consulted when the token type has no inline identity (plain "WebAPI"). Use whichever you prefer - the config keeps the identity out of code, while the inline form keeps it next to the call site.

  1. Open [Project Name].Build.cs located in the Unreal Projects/[Project name]/Source/[Project name] directory and add "OnlineSubsystem", "OnlineSubsystemSteam", "Steamworks" to PublicDependencyModuleNames.AddRange. Confirm that your PublicDependencyModuleNames.AddRange follows this structure:
PublicDependencyModuleNames.AddRange(
    new string[] {
        "Core",
        "CoreUObject",
        "Engine",
        "InputCore",
        "PragmaSDK",
        "PragmaSDKAux",
        "OnlineSubsystem",
        "OnlineSubsystemSteam",
        "Steamworks"
    }
);
  1. Open your project in Unreal Editor.
  2. Click on the Edit menu, then Plugins to open the Plugins window.
  3. Ensure that both the Online Subsystem and Online Subsystem Steam plugins are enabled, then restart Unreal Editor.

Integrate Steam login into your game #

We will use the MyPlayerController class we created in Log in from a Game Client to add a Steam login method.

Acquire the Steam ticket with the asynchronous GetLinkedAccountAuthToken method (using the "WebAPI" token type) rather than the synchronous GetAuthToken. The synchronous method returns a ticket immediately - before Steam has finished propagating it to its authentication servers - which can cause the first login attempt to fail with a transient validation error. The asynchronous method waits for Steam’s confirmation callback before handing back the ticket, so the ticket is safe to use as soon as you receive it.
  1. In MyPlayerController.h, declare the following method under the public access modifier:
UFUNCTION(Exec)
void LogInSteam();
  1. In MyPlayerController.cpp, add the following include statements:
#include "OnlineSubsystem.h"
#include "Interfaces/OnlineIdentityInterface.h"
  1. In MyPlayerController.cpp, define the LogInSteam() method. Player->LogIn takes a FGetProviderTokenDelegate instead of a raw token: a token fetched too early can expire while the player waits in the login queue, so the delegate defers the actual Steam ticket request until the SDK is ready to use it, once the player has cleared the queue. The delegate must call OnResult exactly once: with the token on success, or with a failure if the ticket can’t be obtained, which ends the login immediately with that error:
void AMyPlayerController::LogInSteam()
{
  const Pragma::FPlayer::FGetProviderTokenDelegate GetProviderToken =
    Pragma::FPlayer::FGetProviderTokenDelegate::CreateWeakLambda(
      this, [this](Pragma::FPlayer::FProviderTokenReadyDelegate OnResult)
      {
        IOnlineSubsystem* OSS = IOnlineSubsystem::Get(TEXT("STEAM"));
        if (OSS == nullptr)
        {
          OnResult.ExecuteIfBound(Pragma::FPragmaProviderTokenResult::Failure(TEXT("Steam Online Subsystem is unavailable.")));
          return;
        }

        OSS->GetIdentityInterface()->GetLinkedAccountAuthToken(0, TEXT("WebAPI"),
          IOnlineIdentity::FOnGetLinkedAccountAuthTokenCompleteDelegate::CreateWeakLambda(
            this, [OnResult](int32 LocalUserNum, bool bWasSuccessful, const FExternalAuthToken& AuthToken)
            {
              if (!bWasSuccessful || !AuthToken.HasTokenString())
              {
                OnResult.ExecuteIfBound(Pragma::FPragmaProviderTokenResult::Failure(TEXT("Failed to acquire a Steam auth ticket.")));
                return;
              }

              OnResult.ExecuteIfBound(Pragma::FPragmaProviderTokenResult::Success(AuthToken.TokenString));
            }));
      });

  Player->LogIn(
    EPragma_Account_IdProvider::STEAM,
    GetProviderToken,
    Pragma::FPlayer::FLoggedInDelegate::CreateWeakLambda(
      this, [this](const TPragmaResult<>& Result)
      {
        if (Result.IsSuccessful())
        {
          UE_LOG(LogTemp, Display, TEXT("Pragma -- Logged in with Steam."));
        }
        else
        {
          UE_LOG(LogTemp, Error, TEXT("Pragma -- Steam login failed: %s"),
            *Result.GetErrorAsString());
        }
      }));
}
  1. Compile the project in your IDE.

Build a standalone binary #

The Steam Online Subsystem in Unreal Engine does not work in PIE (Play In Editor) mode. It will still work if you run using the “Standalone Game” option.
In the Edit menu under Project Settings…, ensure that your project’s Default GameMode is set to MyGameModeBase before packaging a standalone version of your project.
  1. Build a standalone version of your game by going to the File menu, Package Project, then building a Windows (64-bit) version of the game.

  1. Ensure Pragma is running. Confirm that your Steam client is open and logged in with the same account used to get the Steam App ID.

  2. Navigate to the location of the built project. You should find [Your project name].exe inside the WindowsNoEditor directory.

  3. Create a shortcut to [Your project name].exe, then right-click the shortcut left-click Properties.

  4. In the Shortcut Properties window, add a space and -log to the end of the Target field. The Target field should read path to your executable\[Your project name].exe -log. You will now see a separate log window appear when launching your standalone game via this shortcut.

  5. Open your standalone game using the shortcut you just created.

  6. Run the game, open the in-game console with ~, and type LogInSteam.

  7. If successful, you should see the app you registered with Steam running inside the Steam client. A separate log window should open and you should see a successful login attempt via Steam.

For extra confirmation, you can use the Pragma Portal to verify a successful Steam login.
  1. Navigate to http://localhost:11200/ to load Pragma Portal. Select Sign in with Pragma Unsafe and type in test04.

  2. Confirm you see a player with your Steam display name listed in the Accounts section of the portal. Clicking on this player should show that the identity provider for this player is Steam.