Gamers Lab Docs

1.5 Tenant Auth Configuration

Section 1 — Studio Accounts

1.5 Tenant Auth Configuration

What Tenant Auth Config Is

By default, all player authentication providers (Steam, Epic, wallet, email) operate with platform-level credentials. Tenant auth configuration allows each tenant to supply their own provider credentials — their own Steam API key, Epic deployment, Sequence project, etc.

When a tenant has a config registered for a provider, the player login flow uses that tenant's credentials instead of the platform defaults. If no config is registered or it is disabled, the login attempt is rejected for that provider on that tenant.

Each config is scoped to exactly one (tenant_id, provider) pair. A tenant can configure multiple providers independently.

Supported Providers

ProviderTenant config supportedRequired config keys
SteamYesapiKey, appId, webApiIdentity
EpicYesclientId, clientSecret, productId, deploymentId
SequenceYesprojectId
EvmWalletYesNone — wallet validation is key-less
EmailYesNone — uses platform email infrastructure
Email One-Time CodeYesNone — uses platform email infrastructure
MockNoTest/dev provider; cannot be tenant-configured

Providers with required keys fail validation if any key is missing at upsert time. Providers with no required keys (EvmWallet, Email, Email One-Time Code) only need to exist and be enabled. Player auth DTOs use the enum-style value EmailOneTimeCode; tenant auth configuration uses the provider string Email One-Time Code.

Storage and Encryption

Config data is stored in bus_tenant_auth_configs.config_data as an encrypted JSONB column.

Encryption is AES-256-GCM using an envelope format:

enc:v2:{keyId}:{nonce_b64}:{cipher_b64}:{tag_b64}
  • 12-byte nonce, 16-byte authentication tag, 256-bit keys
  • Key ring loaded from Encryption:Keys in app configuration
  • Active key identified by Encryption:CurrentKeyId
  • Key rotation is supported — old keys remain in the ring to decrypt existing data

Sensitive field values are masked in all API responses — any configured value is shown as [configured]. Decrypted values are only used internally by the player login flow.

How It Integrates with Player Login

When a player attempts to log in, IAuthProviderConfigGuard runs before the provider validator:

  1. Looks up the tenant's config for the requested provider.
  2. If no config exists or is_enabled = false → login is rejected (422 Unprocessable Entity).
  3. If config exists and is enabled → decrypted config data is passed to the provider validator.

A tenant must explicitly configure each provider they want to support. There is no implicit fallback to platform credentials.

Encrypted configs are cached in shared Redis-backed distributed cache for 5 minutes (auth_config:{tenantId}:{provider}), and each cache hit is decrypted on read. Cache is invalidated on upsert and delete.

Available Operations

All operations require a SaaS JWT with owner or admin role on the tenant.

OperationNotes
List all configs for a tenantReturns all providers with masked values; also lists which providers are available to configure
Get config for a specific providerReturns masked config; 404 if not configured
Create or update a provider configValidates required keys; encrypts and stores; audit-logged
Delete a provider configRemoves the config; invalidates cache; audit-logged

There is no separate enable/disable endpoint — enabling/disabling is done via isEnabled in the upsert request.

Audit Logging

OperationLogged
Config createdYes — provider name, isEnabled state
Config updatedYes — before/after diff of non-sensitive fields; sensitive values not diffed
Config enabled / disabledYes
Config deletedYes

Raw secret values are never written to the audit log.

Limitations

  • No fallback to platform credentials. If a tenant has no config for a provider, logins via that provider are blocked for that tenant.
  • No partial key updates. The upsert replaces the entire config_data dictionary. To update a single key, the caller must re-submit all required keys.
  • Secrets cannot be read back. If a secret is lost, the only option is to re-submit the full config.
  • Mock provider is not configurable.

Code References

  • Controller: GamersLabRestAPI/Saas/Business/Controller/TenantAuthConfigController.cs
  • Service interface: GamersLabRestAPI/Saas/Business/Services/ITenantAuthConfigService.cs
  • Service: GamersLabRestAPI/Saas/Business/Services/TenantAuthConfigService.cs
  • Repository interface: GamersLabRestAPI/Saas/Business/Repositories/ITenantAuthConfigRepository.cs
  • Repository: GamersLabRestAPI/Saas/Business/Repositories/NpgsqlTenantAuthConfigRepository.cs
  • Model: GamersLabRestAPI/Saas/Business/Models/TenantAuthConfigModel.cs
  • DTOs: GamersLabRestAPI/Saas/Business/DTOs/TenantAuthConfigDTOs.cs
  • Provider registry: GamersLabRestAPI/Core/Constants/AuthProviderRegistry.cs
  • Encryption service: GamersLabRestAPI/Saas/Business/Services/EncryptionService.cs
  • PlayerAuth guard: GamersLabRestAPI/PlayerAuth/Services/IAuthProviderConfigGuard.cs

On this page