Your own server

Who is this player?

Your own game server checking a player's token, with or without asking us.

The same way Unity does it. The game hands its idToken to your server - in its join message, a header, whatever your netcode uses - and your server checks it without asking us: the token is a JWT signed with our private key, and the public halves are published.

Check four things, and then sub is the player's id:

Check Must be
Signature RS256, by a key in https://www.dasmaffin.com/api/mgds/v1/.well-known/jwks.json (pick it by the token's kid)
iss https://www.dasmaffin.com/api/mgds/v1
aud Your project's id - so a token from somebody else's game is refused
exp In the future. Tokens last an hour, like the access token

The token also carries sid (the session), project_id, sign_in_provider (anonymous, steam, sbox, dasmaffin) and name when the player has one. Cache the key set: it changes only when we add a key, and an old key stays published for as long as tokens it signed can be alive. There is a discovery document at https://www.dasmaffin.com/api/mgds/v1/.well-known/openid-configuration for libraries that want one.

Like Unity's, a token cannot be taken back before it expires: a player who signs out is signed out of MGDS at once, but a server holding their token believes it until its exp. That is the price of your server not having to ask, and why it lasts an hour.

C# (a dedicated server, .NET): with the Microsoft.IdentityModel.Protocols.OpenIdConnect and Microsoft.IdentityModel.JsonWebTokens packages, which fetch and cache the keys themselves:

var keys = new ConfigurationManager<OpenIdConnectConfiguration>(
    "https://www.dasmaffin.com/api/mgds/v1/.well-known/openid-configuration",
    new OpenIdConnectConfigurationRetriever());

async Task<string?> WhoIs(string idToken)
{
    OpenIdConnectConfiguration config = await keys.GetConfigurationAsync();

    TokenValidationResult result = await new JsonWebTokenHandler().ValidateTokenAsync(idToken, new TokenValidationParameters
    {
        ValidIssuer = "https://www.dasmaffin.com/api/mgds/v1",
        ValidAudience = "YOUR-PROJECT-ID",
        IssuerSigningKeys = config.SigningKeys,
    });

    return result.IsValid ? (string)result.Claims["sub"] : null;   // the player's id, or not a player
}

Node: with jose:

import { createRemoteJWKSet, jwtVerify } from 'jose';

const keys = createRemoteJWKSet(new URL('https://www.dasmaffin.com/api/mgds/v1/.well-known/jwks.json'));

const { payload } = await jwtVerify(idToken, keys, {
  issuer: 'https://www.dasmaffin.com/api/mgds/v1',
  audience: 'YOUR-PROJECT-ID',
});
// payload.sub is the player's id; jwtVerify throws for anything else