Securely Storing Auth Tokens in Unity
Once a player signs in, your game is holding tokens — and where you put them decides whether "signed in once" is a convenience or a liability. Store them carelessly and a leaked refresh token becomes a long-lived key to the player's account. This is how to store auth tokens in Unity without that risk, and which token actually matters most.
PlayerPrefs is the wrong place
PlayerPrefs is the reflexive answer, and it's the wrong one for tokens. It's unencrypted by design — a registry key on Windows, a .plist on macOS and iOS, an XML file under the app's data on Android. That's fine for volume settings. It's not fine for a credential.
On desktop, it's a plainly readable file. On a rooted or jailbroken mobile device, pulling it takes seconds. Drop a refresh token in there and you've left a long-lived account key in the open — the exact thing token expiry was designed to avoid.
Protect the refresh token first
Not all tokens carry the same risk, so spend your effort where it counts.
The access token is short-lived — with Oathwall it expires in about an hour. If it leaks, the window is small and then it's dead. Don't be careless with it (never log it, never send it to analytics), but it isn't the crown jewel.
The refresh token is. It's long-lived — a 30-day rolling session with Oathwall — and its whole job is to mint new access tokens without a login screen. A stolen refresh token is a stolen session. This is the one that belongs in secure storage, full stop.
Where to actually put them
Use the platform's secure store, not a file you rolled yourself:
- iOS: the Keychain. OS-managed, encrypted, the standard home for secrets on Apple platforms.
- Android: the Keystore, typically via
EncryptedSharedPreferencesbacked by a Keystore key, so the data is encrypted at rest and the key never leaves the secure hardware where available. - Desktop (Windows/macOS/Linux): an OS credential store where available, or at minimum app-level encryption. Be honest about the threat model — a determined local attacker with full machine access is hard to stop entirely, so keep sessions revocable and access tokens short.
- WebGL: you can't keep a secret in a browser. Local and session storage are readable by any script on the page. For web, rely on short-lived sessions and httpOnly cookies managed server-side rather than a long-lived client-held refresh token — which is how Oathwall's web side works, using httpOnly Secure cookies.
A few blanket rules regardless of platform: never log tokens, never commit them, never ship them to your own telemetry, and never confuse this with the client secret — that belongs on a server and, with Oathwall, never ships in your build at all.
Let the kit hold them
Secure storage plus rotation plus silent resume is a real amount of platform-specific code. Oathwall's Unity SSO Login Kit does it for you: it stores the session, refreshes it — rotation included — and SilentLogin() resumes a saved session on the next launch.
using PixitGames.SSOLoginKit;
public class LoginManager : SsoClientBase
{
// Resume the stored session on launch. Storage and
// rotation are handled by the kit, not your code.
void Start() => SilentLogin();
protected override void OnLoginSuccess(LoginResult user)
=> Debug.Log($"Welcome back, {user.name}");
}
Storage is one half of keeping a player signed in; the other half is what happens across launches and devices and how you revoke access — that's session management for games. For the token concepts underneath, see access tokens vs refresh tokens.
Frequently asked questions
- Can I store auth tokens in PlayerPrefs?
- You can, but you shouldn't store them there in plaintext. PlayerPrefs is unencrypted — a registry key on Windows, a plist on macOS and iOS, an XML file on Android. On desktop it's a readable file, and on a rooted or jailbroken device it's trivial to pull. A refresh token there is a long-lived key to the account sitting in the open.
- Where should I store a refresh token in Unity?
- In platform-secure storage — the Keychain on iOS and Keystore-backed storage (such as EncryptedSharedPreferences) on Android — so the OS protects it. The refresh token is the sensitive one because it's long-lived; guard it more carefully than the short-lived access token.
- How do I store tokens in a Unity WebGL build?
- You can't store a secret securely in a browser — anything in local or session storage is readable by scripts on the page. For web, lean on short-lived sessions and httpOnly cookies handled by the server rather than keeping a long-lived refresh token in the client. Oathwall uses httpOnly Secure cookies on the web side for this reason.
- Does the Oathwall Unity SDK handle token storage?
- Yes. The SSO Login Kit stores the session and refreshes it for you, including refresh token rotation, and SilentLogin resumes a saved session on the next launch — so you're not hand-rolling secure storage or renewal logic.