Menu
AWS Architecture Blog·June 29, 2026

Dual-Token Authentication Architecture for Game Servers on AWS

This article details a dual-token authentication system for game servers using Amazon Cognito for player identity and Nakama for game sessions. It outlines an architecture that integrates these systems with distinct token lifecycles, ensuring a seamless player experience. The solution employs AWS services like CloudFront, WAF, ALB, NLB, and ECS Fargate to build a secure, scalable, and highly available routing and authentication layer for real-time game applications.

Read original on AWS Architecture Blog

Overview of Dual-Token Authentication for Game Servers

The core problem addressed is combining a managed identity provider (Amazon Cognito) with a game server's native session system (Nakama) without disrupting gameplay. The proposed solution uses a dual-token approach: Cognito issues a JWT for player identity, which is then exchanged for a Nakama session token via a server-side Go hook. This decouples identity management from game sessions, allowing independent validation and lifecycle management for each token type.

Architecture and Traffic Flow

The architecture features a default-closed routing layer, with Amazon CloudFront as the single HTTPS entry point, providing edge caching and security via AWS WAF. HTTP API traffic is routed through an Application Load Balancer (ALB) to Nakama instances on Amazon ECS Fargate, while WebSocket traffic is handled by a Network Load Balancer (NLB) using TCP passthrough. This separation allows specialized handling for different traffic types.

  1. Client → Amazon Cognito: Player authenticates using SRP-based flow, receiving a JWT access token.
  2. Client → Amazon CloudFront: All requests enter here, inspected by AWS WAF.
  3. CloudFront → ALB (HTTP API): HTTP requests are routed through the ALB, which enforces an explicit allow-list for routes.
  4. CloudFront → NLB (WebSocket): WebSocket traffic is directed to the NLB for TCP passthrough, maintaining persistent connections.
  5. ALB/NLB → Amazon ECS (Nakama): Nakama handles API calls. For auth requests, a Go hook validates the Cognito JWT and extracts the `sub` claim as the Nakama user ID. For other requests, Nakama validates its own session token.

Why Two Load Balancers?

ℹ️

Load Balancer Specialization

The use of both an ALB (Layer 7) and an NLB (Layer 4) is crucial. The ALB provides advanced HTTP features like path-based routing, listener rules, and HTTP-level security, returning `403` for unlisted routes. The NLB, conversely, performs raw TCP passthrough, which is essential for efficient and low-latency WebSocket connections, allowing Nakama to directly manage the connection lifecycle. CloudFront intelligently routes traffic based on URL patterns (`/ws*` to NLB, others to ALB).

Cognito JWT Validation and Session Bridging

The system ensures security by never trusting client-provided identity directly. A server-side Go hook within Nakama validates the Cognito JWT. This involves checking the token format, algorithm (RS256), signature against a cached JWKS, expiry, and issuer/audience claims. Critically, the hook discards any client-sent user ID and overwrites the Nakama user ID with the cryptographically verified `sub` claim from the JWT, preventing impersonation. The JWKS cache implements a thundering herd protection mechanism to efficiently handle key rotation.

go
func validateCognitoJWT(token string, env map[string]string) (string, error) {
    // ... token parsing, header extraction
    if header.Alg != "RS256" { return "", runtime.NewError("unsupported algorithm", 3) }
    // ... fetch public key from JWKS cache
    if err := rsa.VerifyPKCS1v15(pubKey, crypto.SHA256, hash[:], signatureBytes); err != nil { return "", runtime.NewError("invalid token signature", 16) }
    // ... validate claims: expiry, issuer, audience
    return claims.Sub, nil // sub claim becomes the Nakama user ID
}
AWSAmazon CognitoNakamaAuthenticationJWTLoad BalancerWebSocketECS Fargate

Comments

Loading comments...