One Identity to Unite Them: The Case for OAuth
In multiplayer games, logins are a necessary part of the product. Not only is it often a player’s first point of interaction with the game, but also an ideal point for creating and/or verifying the player’s identity. As a game developer, if you’re supporting multiple games, wouldn’t it be great to unify the login process and allow players to share their identity across them?
Battle.net is an example that does the unified login process really well. Blizzard launched Battle.net at the end of 1996, just before the launch of Diablo, which was the first game to use the platform. In the subsequent years, they published more multiplayer games, all using the same platform, but with game-specific logins. In 2009, Blizzard launched a new version of Battle.net that provided a unified login for all their multiplayer games, starting with some of their then-recent titles. Since then, all new games by Blizzard have used the Battle.net platform. Later on, after their merger, games published by Activision also got onto the platform. This enabled shared features for these games:
- A friends list
- Presence (“Bob is playing Game A”)
- Cross-game rewards
By eventually building the systems to support this, Blizzard doesn’t have to re-implement these features for every new game that they make. It also creates opportunities for cross-game promotions, and seeing what my friends are playing also builds curiosity and encourages me to check out these other games. Building these systems is a monumental set of tasks in itself, but all of them build on a core feature: aplayer identity across games. So, let’s start there.
For a player’s identity to be ascertained, they first need to log in. The simplest login involves just making a request to the backend and receiving an identifier in response. This identifier is then stored locally on the device, and subsequently used for future requests and logins. It’s a quick way to get started, but also fraught with issues since the information used to identify the player is only stored locally, meaning that the player wouldn’t be able to access the same identity when logging in from another device.
The next step up would be using a username/password login and saving player account information in a database. This solves the issue around access across multiple devices since the player authenticates using their credentials. With this setup, the backend needs to verify the username/password pair before resolving the player’s identity and authorizing them to access the requested game.
This is adequate for a single game, but if there are aspirations for more games using the same login, or third-party integrations, it might be worth considering a push to an industry standard for user authentication. Having a unified player identity system also enables other systems to be built on top of it, like Battle.net’s social features.
An Overview of OAuth
This widely adopted authentication protocol offers a host of advantages, including enhanced security, user convenience, and the ability to create seamless cross-game experiences. Moreover, the ecosystem support is great, with libraries for common backend systems.
Here’s an overview of the components of an OAuth setup.
OAuth Authorization Server: The central service in charge of authenticating users, authorizing clients, and issuing access tokens.
OAuth Client: The application that wants to access data belonging to users.
OAuth Resource Server: The server hosting user data, which is only accessible using a valid access token.
A single server can function as any number of the above. For example, I could have the Authorization Server also be a Resource Server that hosts the users’ profiles.
OAuth Resource Owner: The user that owns some data that is controlled by an OAuth Resource Server.
OAuth supports many flows for obtaining an access token. The most commonly used flow is called the Authorization Code Grant. Here’s an outline of the process:
- The OAuth Client (i.e. the application) directs the user to the OAuth Authorization Server to log in.
- After authenticating successfully, the server will redirect the user to a specified redirect URI controlled by the OAuth Client, along with an authorization code.
- The OAuth Client will then communicate with the OAuth Authorization Server to exchange the authorization code with an access token. This access token can then be used to access resources belonging to the player.
Notice that the player doesn’t have to divulge any credentials to the OAuth Client. This enforces a certain level of security, and if even more security is needed, more controls on the access token’s validity can be added.
How to get started
I want to emphasize again that this is a significant undertaking to get started on, so do be prepared. Even researching what solution would fit your needs best may take some time.
If you already have a backend and want to add OAuth functionality to it, there are libraries or plugins for common server backends, like Java (Spring), Ruby (Rails), Python (Django / Flask), NodeJS, and many more. There are also hosted solutions that support an OAuth flow, like Auth0, or KeyCloak.
Building on top of OAuth
Now that you have a central identity service built using OAuth, you can start to think about and build out the rest of the features that take advantage of this. Soon enough, with enough work put in, some luck, and a lot of troubleshooting, you’ll be able to have your players chatting with each other and offering cohesive experiences across your games!
There are a lot of nuances and details that I’ve left out because it’s already quite dense. One big topic you should definitely get into is security. OAuth has a lot of security considerations built-in, but many of these are optional, and will require configuration.