Step 2. Log in
Implement login so that users can log in to your app with their Steam account without a separate sign-up. Before you begin, complete Step 1. Set up the integration.
For Steam login, how you get credentials depends on the OS the app runs on. Both methods return values that the Hive Axyl authentication server can verify directly, so you log in with the Direct Token flow without an exchange step.
- Windows, macOS: Steam login Add-on
- Android, iOS: Web login session
1. Get Steam credentials
Get Steam credentials with the method that matches the OS the app runs on.
1.1. Windows and macOS
On Windows and macOS, the Steam login Add-on gets an authentication ticket from Steamworks. Because the user is already logged in to the Steam client, no separate login screen appears.
Request an authentication ticket
GetAuthTicketForWebApiAsync
Call ISteamPlugin.GetAuthTicketForWebApiAsync() to get an authentication ticket. The ticket is returned as a hexadecimal string, and you use it as ProviderToken in the login request.
| Field name | Type | Required | Description |
|---|---|---|---|
Identity | string | Required | The identification string that Steamworks uses when it creates the ticket. If you pass an empty string, Steamworks uses its default identifier. Steamworks rejects values longer than 30 characters. |
using Hive.Axyl.Auth.Addon.Steam;
using Hive.Axyl.Core;
using UnityEngine;
// The Add-on is registered only in Windows and macOS builds.
if (!HiveCore.TryResolve<ISteamPlugin>(out var steam))
{
// Not Windows or macOS, or the Add-on is not registered → branch to the web login session
return;
}
var ticketResult = await steam.GetAuthTicketForWebApiAsync(
new GetAuthTicketForWebApiRequest { Identity = string.Empty });
string steamProviderToken; // ProviderToken of the login request
switch (ticketResult)
{
case SteamServiceGetAuthTicketForWebApiResult.Success success:
steamProviderToken = success.Data.TicketHex;
break;
case SteamServiceGetAuthTicketForWebApiResult.NotAuthenticated:
// Not logged in to the Steam client → prompt the user to log in to Steam
return;
case SteamServiceGetAuthTicketForWebApiResult.Failure failure:
HiveError err = failure.Problem;
Debug.LogError($"[{err.Code}] {err.Message} (trace: {err.TraceId})");
return;
// Safety net: unhandled results and unknown new results (UnknownOutcome)
default:
Debug.LogWarning($"Unhandled result: {ticketResult.GetType().Name}");
return;
}
// Steam ID64 of the user currently logged in to the Steam client.
string steamProviderUserId = GetCurrentSteamId64();
GetCurrentSteamId64() is code that the app implements itself to read the current user's Steam ID64 from Steamworks. The Steam login Add-on does not provide this value.
Note
The Hive Axyl authentication server confirms the actual Steam account by checking the authentication ticket with Steam. The Steam ID64 that the app sends does not replace that confirmation process.
Response status
| Response case | Description | App client handling |
|---|---|---|
Success | Ticket issued successfully. Use Data.TicketHex as ProviderToken. | Proceed with external authentication provider login |
NotAuthenticated | When the user is not logged in to the Steam client | Prompt the user to log in to the Steam client |
UnknownOutcome | A new result that this SDK version does not recognize | Log it and handle it conservatively |
Failure | Common Failure. The case where Steamworks has not been initialized (FailedPrecondition) also branches here, and the cause is in Failure.Problem.Code. See Common error handling. | Handle according to the common error handling criteria |
Release the authentication ticket
ReleaseTicket
Steam limits the number of authentication tickets that an app can hold at the same time. If you keep issuing tickets without releasing them, later issuance requests fail, so release the ticket with ReleaseTicket() after you receive the login result.
Release the ticket after you receive the response from Log in with an external authentication provider, whether the login succeeded or failed. If you release it before verification finishes, Steam considers the ticket invalid and login fails.
Call ReleaseTicket() on the Unity main thread. Passing a ticket that was already released or is unknown does nothing.
1.2. OSs other than Windows and macOS
On Android and iOS, open the Steam login page with a web login session and receive Steam's OpenID login result. Because Steam does not send the login result back to the app's own scheme URL, the result returns to the app callback URL through the Hive Axyl relay URL. Use the received result for login as is, without an exchange step.
The app gets Steam credentials in the following order.
- Create a
return_toURL with a new random value and store it. - Build a Steam login request URL that includes the
return_toURL. - Put the app callback URL in
OpenRequest.RedirectUriand open a web login session. - Verify the callback.
- Extract the values for
ProviderUserIdandProviderTokenfrom the callback.
Build the return_to URL
The return_to URL is the URL to which Steam sends the login result. Build it by appending the app callback URL and a random value as query parameters to the Hive Axyl relay URL.
relayTo: The URL-encoded value of the app callback URL{appId}://oauth-callback, to which the Hive Axyl relay URL delivers the results: A cryptographically secure random value that you create anew for every login attempt. The example code generates it withCreateNonce(), defined in Sign in with Apple
Steam returns the return_to URL as is in the login result, so store the URL you created and compare it in Verify the callback. The app callback URL is the value you decided in Relay URL and app callback URL.
Build the login request URL
Build the login request URL by appending the following parameters to the Steam OpenID login endpoint https://steamcommunity.com/openid/login. URL-encode each value.
openid.ns:http://specs.openid.net/auth/2.0openid.mode:checkid_setupopenid.return_to: The URL you created in Build the return_to URLopenid.realm:https://core-api.hiveaxyl.com, the origin of thereturn_toURLopenid.identity:http://specs.openid.net/auth/2.0/identifier_selectopenid.claimed_id:http://specs.openid.net/auth/2.0/identifier_select
Open the web login session
Use OpenAsync() of the web login session to open the login request URL you built. In OpenRequest.RedirectUri, put the app callback URL {appId}://oauth-callback, not the relay URL.
Verify the callback
The Hive Axyl relay URL forwards the query string that Steam sent to the app callback URL without changing it. Even if the user declines Steam login, Steam does not close the window; it returns a callback whose openid.mode is cancel.
So when you receive the callback, check that the callback parameters meet all of the following conditions before you extract the login values. If any condition is not met, stop the login.
- The value of
openid.modeisid_res - The value of
openid.return_toexactly matches the storedreturn_toURL - The value of
openid.claimed_idis in thehttps://steamcommunity.com/openid/id/{Steam ID64}format
Extract the login values
Extract the two values to put in the login request from the callback that passed verification. The web login session does not parse the callback, so the app implements the code that extracts the values itself.
ProviderUserId: The Steam ID64 that followshttps://steamcommunity.com/openid/id/inopenid.claimed_idProviderToken: The entire query string of the callback URL, from after?to before#
For ProviderToken, put the query string exactly as Steam sent it, not a string reassembled from parsed parameters. The Hive Axyl authentication server sends this value to Steam to confirm the authenticity of the login result, so if the parameter order changes or the string is re-encoded, signature verification fails and login is rejected. ExtractQueryString() in the following example is code that the app implements itself to cut out the string from after ? to before # in the callback URL as is.
using System;
using Hive.Axyl.Auth.Addon.WebAuth;
using Hive.Axyl.Core;
if (!HiveCore.TryResolve<IExternalUserAgent>(out var webAuth))
{
return;
}
const string RelayUrl = "https://core-api.hiveaxyl.com/auth/v1/provider/callback";
const string SteamIdPrefix = "https://steamcommunity.com/openid/id/";
const string IdentifierSelect = "http://specs.openid.net/auth/2.0/identifier_select";
string appCallback = "{appId}://oauth-callback";
// Create and store a return_to URL with a new random value for every login attempt.
string returnTo = RelayUrl
+ "?relayTo=" + Uri.EscapeDataString(appCallback)
+ "&s=" + Uri.EscapeDataString(CreateNonce());
string steamLoginUrl = "https://steamcommunity.com/openid/login"
+ "?openid.ns=" + Uri.EscapeDataString("http://specs.openid.net/auth/2.0")
+ "&openid.mode=checkid_setup"
+ "&openid.return_to=" + Uri.EscapeDataString(returnTo)
+ "&openid.realm=" + Uri.EscapeDataString("https://core-api.hiveaxyl.com")
+ "&openid.identity=" + Uri.EscapeDataString(IdentifierSelect)
+ "&openid.claimed_id=" + Uri.EscapeDataString(IdentifierSelect);
var sessionResult = await webAuth.OpenAsync(new OpenRequest {
Url = steamLoginUrl,
RedirectUri = appCallback, // The app callback URL, not the relay URL
});
if (sessionResult is not ExternalUserAgentServiceOpenResult.Success session)
{
// For handling UserCanceled and Failure, see [Web login session](web-auth-session.md)
return;
}
var callback = session.Data.Parameters;
callback.TryGetValue("openid.mode", out string openIdMode);
if (openIdMode != "id_res")
{
// If "cancel", the user declined Steam login → keep the login screen
return;
}
if (!callback.TryGetValue("openid.return_to", out string returnedTo) || returnedTo != returnTo)
{
// Not a response started by this login → stop the login
return;
}
if (!callback.TryGetValue("openid.claimed_id", out string claimedId)
|| !claimedId.StartsWith(SteamIdPrefix, StringComparison.Ordinal)
|| !ulong.TryParse(claimedId.Substring(SteamIdPrefix.Length), out _))
{
// Not in the Steam ID64 format → stop the login
return;
}
string steamProviderUserId = claimedId.Substring(SteamIdPrefix.Length);
string steamProviderToken = ExtractQueryString(session.Data.CallbackUrl);
2. Log in with an external authentication provider
Call Log in with an external authentication provider with the steamProviderUserId and steamProviderToken you got in the previous step. Specify Provider.Steam for ProviderId.
using Hive.Axyl.Auth;
using Hive.Axyl.Core;
IAuthService auth = HiveCore.Resolve<IAuthService>();
var (codeVerifier, codeChallenge) = CreatePkce();
var result = await auth.LoginProviderAsync(new ProviderLoginRequest {
ProviderId = Provider.Steam,
ProviderUserId = steamProviderUserId,
ProviderToken = steamProviderToken,
DeviceKey = deviceKey,
ClientId = "{clientId}",
CodeChallenge = codeChallenge,
CodeChallengeMethod = CodeChallengeMethod.S256,
});
if (result is AuthLoginProviderResult.Success success)
{
// Login succeeded → issue tokens and activate the session.
await StartSessionAsync(success.Data.AuthorizationCode, codeVerifier, success.Data.PlayerId);
}
// For other response cases and the full call parameters, see [Log in with an external authentication provider](provider-login.md)
On Windows and macOS, release the authentication ticket after you receive the result of this call.
CreatePkce() is a helper defined in Create a guest account. For the definition of StartSessionAsync() and the session activation procedure, see Issue tokens and activate the session.