Skip to content

Add sovereign cloud support (GCCH, DoD, China)#500

Merged
corinagum merged 6 commits intomainfrom
cg/sovereign-cloud
Apr 13, 2026
Merged

Add sovereign cloud support (GCCH, DoD, China)#500
corinagum merged 6 commits intomainfrom
cg/sovereign-cloud

Conversation

@corinagum
Copy link
Copy Markdown
Collaborator

@corinagum corinagum commented Apr 3, 2026

Summary

  • Introduces CloudEnvironment type with predefined presets (PUBLIC, US_GOV, US_GOV_DOD, CHINA) bundling all cloud-specific service endpoints
  • Threads cloud environment through App, TokenManager, ApiClient, JwtValidator, and ServiceTokenValidator
  • Supports CLOUD environment variable and programmatic AppOptions.cloud configuration
  • Adds graphScope to CloudEnvironment for cloud-aware Microsoft Graph token acquisition

Note

graphBaseUrl (Graph API endpoint per cloud) is intentionally deferred. This PR focuses on auth/token acquisition. Graph API routing is a separate concern and the Graph client already accepts a baseUrlRoot override.

Sources

Test plan

  • npm run build -- 34/34 tasks pass
  • npm test -- 591 tests pass
  • E2E: Echo bot with CLOUD=USGov against real GCCH tenant -- JWT validated, echo reply sent
  • Copilot review feedback addressed

🤖 Generated with Claude Code

@corinagum corinagum force-pushed the cg/sovereign-cloud branch 3 times, most recently from 837bcd3 to 3a57872 Compare April 6, 2026 21:26
@corinagum corinagum marked this pull request as ready for review April 6, 2026 21:26
@corinagum corinagum requested a review from Copilot April 7, 2026 20:52
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds first-class sovereign cloud support by introducing a CloudEnvironment abstraction (public, US Gov, DoD, China) and threading it through token acquisition, API client configuration, and JWT validation so endpoints/issuers/JWKS can vary by cloud.

Changes:

  • Added CloudEnvironment presets plus helpers (fromName, withOverrides) and exported them from the auth package.
  • Threaded cloud through App, TokenManager, API client settings, and JWT validators (including support for CLOUD env var).
  • Updated service token validation to use cloud-specific issuer and JWKS metadata-derived keys endpoint, with accompanying tests.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/api/src/auth/cloud-environment.ts Defines cloud presets + name/override helpers for sovereign endpoints.
packages/api/src/auth/cloud-environment.spec.ts Adds tests covering presets, fromName, and withOverrides.
packages/api/src/auth/index.ts Re-exports cloud-environment from the auth barrel.
packages/api/src/clients/api-client-settings.ts Allows default OAuth/token service URL to come from CloudEnvironment.
packages/api/src/clients/index.ts Threads optional cloud into client settings merging.
packages/apps/src/app.ts Resolves cloud from options or CLOUD env var and passes it through to API/auth components.
packages/apps/src/token-manager.ts Uses cloud bot scope/authority endpoints for token acquisition.
packages/apps/src/middleware/auth/jwt-validator.ts Adds loginEndpoint support for JWKS URI construction and issuer prefix validation.
packages/apps/src/middleware/auth/service-token-validator.ts Uses cloud issuer + OpenID metadata-derived JWKS keys URI.
packages/apps/src/middleware/auth/service-token-validator.spec.ts Adds sovereign cloud test coverage for issuer/JWKS URI selection.
packages/apps/src/middleware/jwt-validation-middleware.ts Accepts cloud param and passes it into service token validation.
packages/apps/src/http/http-server.ts Passes cloud into ServiceTokenValidator during server initialization.
Comments suppressed due to low confidence (1)

packages/apps/src/token-manager.ts:75

  • getGraphToken() still uses the public cloud scope (https://graph.microsoft.com/.default) even when the token authority is switched via cloud.loginEndpoint. In sovereign clouds, Graph typically has different resource/scope values (e.g. https://graph.microsoft.us/.default), so token acquisition can fail or produce a token for the wrong audience. Consider adding a Graph scope/base URL to CloudEnvironment and using it here instead of the hard-coded constant.
  async getGraphToken(tenantId?: string): Promise<IToken | null> {
    return await this.getToken(DEFAULT_GRAPH_TOKEN_SCOPE, this.resolveTenantId(tenantId, DEFAULT_TENANT_FOR_GRAPH_TOKEN));
  }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@corinagum corinagum force-pushed the cg/sovereign-cloud branch from 3a57872 to 3e3064e Compare April 8, 2026 23:30
rido-min
rido-min previously approved these changes Apr 9, 2026
@rajan-chari
Copy link
Copy Markdown
Contributor

Review note: Graph token scope needs to vary per cloud

Great work on sovereign cloud support! One gap I noticed: getGraphToken() in token-manager.ts still hardcodes the public cloud Graph scope:

const DEFAULT_GRAPH_TOKEN_SCOPE = 'https://graph.microsoft.com/.default';

This will fail for sovereign clouds — the Graph API endpoint domain differs per cloud, and using the wrong audience returns AADSTS500011 or AADSTS650001.

Correct Graph scopes per cloud

Cloud Graph Scope
Public https://graph.microsoft.com/.default
US Gov (GCC High) https://graph.microsoft.us/.default
US Gov (DoD) https://dod-graph.microsoft.us/.default
China (21Vianet) https://microsoftgraph.chinacloudapi.cn/.default

Note: DoD uses dod-graph.microsoft.us, not graph.microsoft.us — the two US Gov presets need different graph scopes.

Reference: Microsoft Graph national cloud deployments

Suggested fix

  1. Add a graphScope field to CloudEnvironment
  2. Set it correctly in all 4 cloud presets
  3. TokenManager.getGraphToken() reads cloud.graphScope instead of the hardcoded constant

Small change — one new field on the type, one line update in token-manager.ts.

Corina Gum and others added 4 commits April 10, 2026 09:30
Introduce CloudEnvironment type with predefined presets (PUBLIC, US_GOV,
US_GOV_DOD, CHINA) bundling all cloud-specific service endpoints. Thread
cloud environment through App, TokenManager, ApiClient, JwtValidator, and
ServiceTokenValidator so previously hardcoded endpoints are configurable
per cloud.

Supports programmatic configuration via AppOptions.cloud or CLOUD
environment variable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- CloudEnvironment: preset values, fromName(), withOverrides(), frozen checks
- ServiceTokenValidator: verify cloud-specific issuer and JWKS URI for US_GOV/CHINA
- JwtValidator: loginEndpoint for JWKS URI construction and issuer prefix validation

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@corinagum corinagum force-pushed the cg/sovereign-cloud branch from 8f9d0b2 to 634f391 Compare April 10, 2026 16:31
heyitsaamir
heyitsaamir previously approved these changes Apr 10, 2026
@corinagum corinagum merged commit b18aecc into main Apr 13, 2026
7 checks passed
@corinagum corinagum deleted the cg/sovereign-cloud branch April 13, 2026 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants