Authentication

View Source

Asobi supports multiple authentication methods: username/password, OAuth/OIDC social login (Google, Apple, Microsoft, Discord), Steam, and device-based auth.

Players can link multiple providers to a single account.

Username & Password

The simplest method. Register and login to receive a session token:

curl -X POST http://localhost:8080/api/v1/auth/register \
  -H 'Content-Type: application/json' \
  -d '{"username": "player1", "password": "secret123"}'
{"player_id": "...", "session_token": "...", "username": "player1"}

Use the session token in subsequent requests:

Authorization: Bearer <session_token>

OAuth / Social Login

For game clients, Asobi uses server-side token validation. The game client authenticates with the platform SDK (Google Sign-In, Apple Sign-In, etc.) to obtain an ID token, then sends it to Asobi for validation.

POST /api/v1/auth/oauth

Flow

  1. Player taps "Sign in with Google" in your game
  2. Platform SDK returns an ID token (JWT)
  3. Game client sends the token to Asobi
  4. Asobi validates the JWT against the provider's JWKS
  5. If the identity exists, the player is logged in
  6. If not, a new player account is created and linked

Example

curl -X POST http://localhost:8080/api/v1/auth/oauth \
  -H 'Content-Type: application/json' \
  -d '{"provider": "google", "token": "eyJhbGciOiJSUzI1NiIs..."}'

First-time response (new account created):

{
  "player_id": "...",
  "session_token": "...",
  "username": "google_abc12345_4821",
  "created": true
}

Returning player response:

{
  "player_id": "...",
  "session_token": "...",
  "username": "player1"
}

Supported Providers

Providerprovider valueIssuer
Google"google"https://accounts.google.com
Apple"apple"https://appleid.apple.com
Microsoft"microsoft"https://login.microsoftonline.com/common/v2.0
Discord"discord"https://discord.com
Steam"steam"N/A (custom, see below)

Configuration

Add provider credentials to your sys.config:

{asobi, [
    {oidc_providers, #{
        google => #{
            issuer => <<"https://accounts.google.com">>,
            client_id => <<"YOUR_CLIENT_ID">>,
            client_secret => <<"YOUR_CLIENT_SECRET">>
        },
        apple => #{
            issuer => <<"https://appleid.apple.com">>,
            client_id => <<"YOUR_CLIENT_ID">>,
            client_secret => <<"YOUR_CLIENT_SECRET">>
        }
    }}
]}

Each provider needs a client ID and secret from the respective developer console:

Steam

Steam uses session tickets instead of OIDC. The game client obtains a ticket via ISteamUser::GetAuthSessionTicket and sends the hex-encoded ticket.

curl -X POST http://localhost:8080/api/v1/auth/oauth \
  -H 'Content-Type: application/json' \
  -d '{"provider": "steam", "token": "14000000..."}'

Asobi validates the ticket via the Steam Web API and fetches the player's display name from their Steam profile.

Configuration

{asobi, [
    {steam_api_key, <<"YOUR_STEAM_WEB_API_KEY">>},
    {steam_app_id, <<"YOUR_STEAM_APP_ID">>}
]}

Get your API key from the Steam Partner site.

Linking Providers

Players can link additional providers to their existing account. This allows them to sign in from different platforms (e.g., link both Google and Steam to the same player).

Requires an authenticated session.

curl -X POST http://localhost:8080/api/v1/auth/link \
  -H 'Authorization: Bearer <session_token>' \
  -H 'Content-Type: application/json' \
  -d '{"provider": "discord", "token": "eyJhbGciOi..."}'
{"provider": "discord", "provider_uid": "123456789", "linked": true}

Asobi prevents unlinking the last auth method to avoid locking the player out.

curl -X DELETE http://localhost:8080/api/v1/auth/unlink \
  -H 'Authorization: Bearer <session_token>' \
  -H 'Content-Type: application/json' \
  -d '{"provider": "discord"}'
{"success": true}

WebSocket Authentication

After obtaining a session token (from any auth method), connect to the WebSocket and authenticate:

{
  "type": "session.connect",
  "payload": {"token": "<session_token>"}
}

The token works the same regardless of which provider was used to obtain it.

SDK Integration

Unity (C#)

// Google Sign-In → Asobi
string idToken = googleSignIn.IdToken;
var response = await asobi.Auth.OAuth("google", idToken);
// response.SessionToken is now set automatically

Godot (GDScript)

# Google Sign-In → Asobi
var id_token = google_sign_in.get_id_token()
var result = await asobi.auth.oauth("google", id_token)
# Session token is stored internally

Dart / Flutter / Flame

// Google Sign-In → Asobi
final idToken = googleSignIn.currentUser!.authentication.idToken!;
final result = await asobi.auth.oauth('google', idToken);
// Session token is stored internally

Defold (Lua)

-- Google Sign-In → Asobi
local id_token = google_sign_in.get_id_token()
asobi.auth.oauth("google", id_token, function(result)
    -- Session token is stored internally
end)

Next Steps