OAuth 2.0 / OpenID Connect Integration

Gaijin SSO implements OAuth 2.0 Authorization Code Flow with OpenID Connect 1.0.

        %%{init: {'theme': 'default', 'flowchart': {'curve': 'basis', 'nodeSpacing': 100}}}%%

sequenceDiagram
    participant User
    participant Client
    participant AuthServer

    User->>Client: Open login page
    rect rgb(191, 223, 255)
        Client->>AuthServer: GET /proxy/oauth/authorize
    end
    AuthServer->>User: Request login & consent
    User->>AuthServer: Enter credentials & consent
    AuthServer->>Client: Redirect with authorization code

    rect rgb(191, 223, 255)
        Client->>AuthServer: POST /proxy/oauth/token (authorization_code)
    end
    AuthServer->>Client: access_token + id_token (+refresh_token)

    rect rgb(191, 223, 255)
        Client->>AuthServer: GET /proxy/oauth/userinfo (Bearer access_token)
    end
    AuthServer->>Client: user profile (email, nickname, etc.)

    alt Refresh token
        rect rgb(191, 223, 255)
            Client->>AuthServer: POST /proxy/oauth/token (refresh_token)
        end
        AuthServer->>Client: new access_token + id_token (+refresh_token)
    end

    alt Revoke refresh token
        rect rgb(191, 223, 255)
            Client->>AuthServer: POST /proxy/oauth/token/revoke
        end
        AuthServer->>Client: {"status":"ok"}
    end

    alt JWT → OAuth ID token
        rect rgb(191, 223, 255)
            Client->>AuthServer: POST /proxy/oauth/exchange (Bearer JWT)
        end
        AuthServer->>Client: id_token + expires_in
    end

    alt OAuth access token → User JWT
        rect rgb(191, 223, 255)
            Client->>AuthServer: POST /proxy/oauth/exchangeToken (Bearer access_token)
        end
        AuthServer->>Client: user JWT
    end
    

Environments

Production Environment: https://login.gaijin.net


OIDC Configuration

GET /.well-known/openid-configuration

Returns the OpenID Connect configuration for the SSO server.


Authorization

Initiates the Authorization Code flow.

Request

Redirect the user to the authorization endpoint with the following parameters.

GET /proxy/oauth/authorize

  • response_type string required

    Must be code.

  • response_mode string required

    Must be query.

  • client_id string required

    Client identifier, issued together with client_secret.

  • redirect_uri string required

    Full redirect URI. Hostname must match configuration for the given client_id.

  • scope string required

    Space-separated list of scopes:

    • openid

      Standard OpenID Connect scope required for authentication and obtaining an ID token.

    • offline_access

      Allows the client to receive a refresh token and access resources without requiring the user to re-authenticate.

    • email

      Adds the user’s email address to the id_token.

    • profile

      Adds the user’s nickname to the id_token.

    • trust

      Adds email_verified and phone_verified fields to the UserInfo response.

  • state string optional (recommended)

    Random string to bind ID token to authentication session. Used for CSRF protection.

    The value is generated by the client application and included in the authentication request. After successful authorization, the same value will be returned in the redirect_uri as a query parameter. The client application must verify that the returned state matches the originally sent value to ensure that the response corresponds to the authentication request initiated by the application.

  • nonce string required

    Random string used to associate the authentication request with the returned ID token and mitigate replay attacks. The value is included in the authentication request and later verified in the returned ID token.

Request example
GET /proxy/oauth/authorize
    ?response_type=code
    &response_mode=query
    &client_id=demo-client
    &redirect_uri=https%3A%2F%2Fclient.example.com%2Fcallback
    &scope=openid%20offline_access%20email%20profile
    &state=af0ifjsldkj
    &nonce=n-0S6_WzA2Mj

Response

If the request is successful, the user will be redirected to the redirect_uri with:

  • code string required

    Authorization code used to obtain the ID token in the next step.

  • state string required

    The value originally provided in the request for client-side verification of the authentication response.

Response example
redirect_uri?code=<authorization_code>&state=<state>

If an error occurs during authorization, the user will be redirected to the redirect_uri with the following query parameters:

  • error string required

    Error code.

  • error_description string required

    Human-readable error message.

Response example
redirect_uri?error=<error>&error_description=<description>

Token (Authorization Code / Refresh Token)

Exchanges an authorization code for tokens or refreshes tokens using a refresh token.

Request

POST /proxy/oauth/token

Exchanges the authorization code obtained from the authorization step for an access token and ID token.

Headers:

  • Authorization string required

    Bearer <token>, where token is the SHA1 hash of:

    redirect_uri + client_secret
    
  • Content-Type string required

    Supported values:

    • application/json

    • application/x-www-form-urlencoded

Body parameters:

  • grant_type string required

    Must be authorization_code.

  • code string required

    Authorization code received during the authorization step.

  • redirect_uri string required

    Redirect URI used during authorization. Must match the URI used in the previous step.

Request example
{
  "grant_type": "authorization_code",
  "code": "SplxlOBeZQQYbYS6WxSbIA",
  "redirect_uri": "https://client.example.com/callback"
}

POST /proxy/oauth/token

Requests new tokens using a refresh token.

Headers:

  • Authorization string required

    Bearer <token>, where token is the SHA1 hash of:

    redirect_uri + client_secret
    
  • Content-Type string required

    Supported values:

    • application/json

    • application/x-www-form-urlencoded

Body parameters:

  • grant_type string required

    Must be refresh_token.

  • refresh_token string required

    Refresh token previously issued by the authorization server.

  • redirect_uri string required

    Redirect URI associated with the client.

Request example
{
  "grant_type": "refresh_token",
  "refresh_token": "eyJhbGciOiJSUzI1NiIs...",
  "redirect_uri": "https://client.example.com/callback"
}

Response

  • access_token string required

    Token used to access protected resources.

  • id_token string required

    JSON Web Token (JWT) containing identity information about the user.

  • token_type string required

    Always Bearer.

  • expires_in integer required

    Lifetime of the access token in seconds.

  • refresh_token string optional

    Issued only if the requested scopes include offline_access.

    Refresh tokens are rotated — only the most recently issued token remains valid.

Response example
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "id_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "eyJhbGciOiJSUzI1NiIs..."
}
  • error string required

    Error code.

  • error_description string required

    Human-readable error message.

Response example
{
  "error": "invalid_grant",
  "error_description": "Authorization code is invalid or expired"
}

ID Token Payload

Structure of the id_token JWT payload.

{
  "typ": "id_token",
  "aud": [
    "https://login.gaijin.net",
    "client_id"
  ],
  "azp": "client_id",
  "iss": "https://login.gaijin.net",
  "exp": 1664805016,
  "iat": 1664804416,
  "kid": "381476",
  "sub": "11644295",
  "email": "user@example.com",
  "nickname": "player",
  "nonce": "random_string"
}

Additional fields:

  • email — present if the email scope was requested

  • nickname — present if the profile scope was requested

Refresh Token Payload

Structure of the refresh_token JWT payload.

{
  "typ": "refresh_token",
  "aud": [
    "https://login.gaijin.net",
    "client_id"
  ],
  "azp": "client_id",
  "iss": "https://login.gaijin.net",
  "exp": 1664805016,
  "iat": 1664804416,
  "kid": "381476",
  "sub": "11644295",
  "scopes": "openid offline_access"
}

Token lifetime

Token Lifetime
OAuth session 10 minutes
ID token 1 hour
Access token 1 hour
Refresh token 30 days

JWT Signature Validation (Required)

It is important to verify the JWT signature because:

  • tokens travel over public networks

  • signing keys may be rotated or revoked

  • compromised application keys must be invalidated safely

Public signing keys can be obtained from:

GET /proxy/oauth/keys

Example:

https://login.gaijin.net/proxy/oauth/keys

The response is provided in JWKS format.

Recommended validation flow:

  1. Receive a JWT from the user.

  2. Check that the iss (issuer) is trusted (equals https://login.gaijin.net).

  3. Check whether the kid exists in the local key cache.

  4. If found, verify the signature.

  5. If not found, request the key set from the JWKS endpoint.

  6. Cache the key and verify the token.

If verification fails, the user should re-authenticate.


UserInfo

Returns user profile information associated with the provided access token.

Tip

This endpoint is compatible with the OpenID Connect UserInfo specification.

Request

GET /proxy/oauth/userinfo

Retrieves information about the authenticated user.

Headers:

  • Authorization string required

    Bearer <access_token>, where access_token is the access token obtained from the token endpoint.

Request example
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

Response

  • status string required

    • “ok”

  • sub string required

    Unique identifier of the user.

  • email string optional

    User email address. Returned only if email was included in scope.

  • email_verified boolean optional

    Indicates whether the user’s email address has been verified. Returned only if trust was included in scope.

  • nickname string optional

    User nickname. Returned only if profile was included in scope.

  • phone_verified boolean optional

    Indicates whether the user’s phone number has been verified. Returned only if trust was included in scope.

Response example
{
  "status": "ok",
  "sub": "11644295",
  "email": "user@example.com",
  "email_verified": true,
  "nickname": "player123",
  "phone_verified": false
}
  • error string required

    Error code.

  • error_description string required

    Human-readable description of the error.

Response example
{
  "error": "invalid_token",
  "error_description": "Access token is invalid or expired"
}

Revoke Refresh Token

Revokes a refresh token. This may be required if the token is compromised or the user session must be terminated.

Tip

This endpoint is conceptually similar to OAuth Token Revocation (RFC 7009).

Request

POST /proxy/oauth/token/revoke

Revokes a previously issued refresh token.

Content-Type:

Supported formats:

  • application/json

  • application/x-www-form-urlencoded

Body parameters:

  • client_id string required

    Client identifier issued during application registration.

  • client_secret string required

    Secret associated with the specified client_id.

  • refresh_token string required

    Refresh token that should be revoked.

Request example
{
  "client_id": "demo-client",
  "client_secret": "secret-value",
  "refresh_token": "eyJhbGciOiJSUzI1NiIs..."
}

Response

  • status string required

    Operation result. Returns ok if the refresh token was successfully revoked.

Response example
{
  "status": "ok"
}
  • error string required

    Error code.

  • error_description string required

    Human-readable description of the error.

Response example
{
  "error": "invalid_request",
  "error_description": "Refresh token is invalid or already revoked"
}

JWT to OAuth ID Token Exchange

Exchanges an existing user JWT for an OAuth-compatible ID token that can be used with OAuth-protected services.

Request

POST /proxy/oauth/exchange

Exchanges a regular user JWT for an OAuth id_token.

Headers:

  • Authorization string required

    Bearer <jwt>, where jwt is the user JWT that should be exchanged for an OAuth ID token.

Request example
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

Response

  • id_token string required

    OAuth ID token issued for the provided user JWT.

  • expires_in integer required

    Lifetime of the issued ID token in seconds.

Response example
{
  "expires_in": 600,
  "id_token": "eyJhbGciOiJSUzI1NiIs..."
}
  • error string required

    Error code.

  • error_description string required

    Human-readable description of the error.

Response example
{
  "error": "invalid_token",
  "error_description": "Provided JWT is invalid or expired"
}

Access Token to User JWT Exchange

Exchanges an OAuth access token for a user JWT.

Request

POST /proxy/oauth/exchangeToken

Exchanges an OAuth access_token for a user JWT.

The resulting JWT will include additional claims:

  • auth = openid

  • typ = exchanged_token

Headers:

  • Authorization string required

    Bearer <access_token>, where access_token is the access token obtained from the OAuth token endpoint.

Request example
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

Response

  • token string required

    User JWT generated from the provided access token.

    The token contains additional claims indicating that it was created through the OAuth exchange process.

Response example
{
  "token": "eyJhbGciOiJSUzI1NiIs..."
}
  • error string required

    Error code.

  • error_description string required

    Human-readable description of the error.

Response example
{
  "error": "invalid_token",
  "error_description": "Access token is invalid or expired"
}