OathWall

OAuth 2.0 Explained for Game Developers

The Oathwall Team4 min read

OAuth 2.0 is the machinery behind every "Sign in with Google" button in every game you've played. It's not complicated once you see the shape of it — but the way it's usually explained assumes you're building a website with a server, and a game is neither. This walks through OAuth 2.0 the way it actually applies to a Unity or Unreal game, and points out exactly where games don't fit the standard picture.

What OAuth 2.0 is (and isn't)

OAuth 2.0 is an authorization framework. Its original job was letting one app access your data on another — "let this app see your Google Calendar" — without you handing over your Google password. Access, not identity.

Login is a layer on top. OpenID Connect extends OAuth 2.0 with an id_token: a signed statement of who the user is. So the "Sign in with Google" button is OAuth 2.0 handling the permission dance, with OpenID Connect turning the result into a proof of identity. Most providers in a game — Google, Apple, Discord, Facebook — work this way. (Steam is the exception; it uses the older OpenID 2.0 and returns an identity directly.)

The four roles

Every OAuth flow has the same cast. Naming them makes the rest obvious:

  • Resource owner — the player. They own the account.
  • Client — your game. It wants to know who the player is.
  • Authorization server — the provider (Google, Discord). It authenticates the player and issues tokens.
  • Resource server — the API that holds the player's data (e.g., Google's userinfo endpoint).

The whole flow is just these four passing messages in a fixed order.

The authorization code flow, step by step

There are a few OAuth flows, but only one is correct for a game: the authorization code flow. Here's the whole thing:

  1. Your game sends the player to the provider's authorization URL, along with your client ID and a redirect URI.
  2. The player signs in and approves. You never see their password — that happens entirely on the provider's page.
  3. The provider redirects back to your redirect URI with a short-lived authorization code. This code is not a token; it's a one-time voucher.
  4. Your server exchanges that code for tokens, sending the code plus your client secret in a direct server-to-server call.
  5. The provider returns an access token (and often a refresh token and an id_token).

Notice step 4. The code-for-token exchange needs the client secret, and it happens server-to-server — not in the browser, not on the device. That single detail is the reason games have trouble.

Why your game is a "public client"

OAuth splits clients into two kinds. A confidential client can keep a secret — it's a server in a locked room. A public client cannot, because it runs somewhere the user controls.

A game is a public client. It runs on the player's phone or PC, where the entire build can be unpacked and its strings read. So step 4 above is a trap: to do the token exchange you need the client secret, but you have nowhere safe to put it. Ship it in the build and it's public in minutes. Leave it out and you can't complete the flow yourself.

There are two real answers. One is PKCE, an extension that lets a public client complete the flow without a static secret. The other is to move step 4 off the device entirely — have a confidential server do the exchange for you.

Where Oathwall fits

Oathwall is that confidential server. It holds your client secret, runs the code-for-token exchange, and hands your game the finished result. Your game does steps 1 and 2 — open the provider, let the player sign in — and receives the player identity back. Steps 3, 4, and 5, the parts that need a secret and a server, never touch your build.

In Unity, that reduces the whole thing to a method call:

using PixitGames.SSOLoginKit;

public class LoginManager : SsoClientBase
{
    public void OnLoginButton() => StartLogin("google");

    protected override void OnLoginSuccess(LoginResult user)
    {
        // The code exchange already happened server-side.
        // You just get the player.
        Debug.Log($"Signed in: {user.name} via {user.provider}");
    }
}

If you want to see this run against a real provider, the Google Sign-In in Unity guide is the end-to-end version, and what SSO means sets the bigger picture. To understand why refresh matters after login, read access vs. refresh tokens.

Oathwall is available on the Unity Asset Store.

Frequently asked questions

Is OAuth 2.0 the same as login?
Not exactly. OAuth 2.0 is an authorization framework — it's about granting access. When it's used with OpenID Connect (which adds an id_token), it becomes login. The 'Sign in with Google' button you see in games is OAuth 2.0 plus OpenID Connect.
What is the authorization code flow?
It's the OAuth 2.0 flow where the provider first returns a short-lived code to your redirect URI, and that code is then exchanged for tokens in a separate server-to-server call using the client secret. It keeps tokens off the front channel and is the correct flow for games.
Why is my game a 'public client'?
Because it can't keep a secret. A confidential client is a server that can hold a client secret safely. A game runs on the player's device, where anyone can inspect the build, so it's a public client. Public clients use PKCE instead of relying on a secret in the app.
Do I have to implement OAuth 2.0 myself?
No. You can, but it means handling redirect URIs, the code exchange, a client secret you can't ship, token storage, and every provider's quirks. A hosted service like Oathwall acts as the confidential client for you, so your game just receives the result.