Skip to content

Add UserDelegation authentication (OAuth authorization code flow)#70

Draft
jricher wants to merge 14 commits into
mongodb:masterfrom
jricher:atlas-cli-oauth
Draft

Add UserDelegation authentication (OAuth authorization code flow)#70
jricher wants to merge 14 commits into
mongodb:masterfrom
jricher:atlas-cli-oauth

Conversation

@jricher

@jricher jricher commented Jul 2, 2026

Copy link
Copy Markdown

Proposed changes

Adds a UserDelegation authentication mechanism that authenticates to Atlas with the
OAuth 2.0 authorization code flow, alongside the existing device-flow path. Wires the
flow configuration, transparent token refresh at the transport layer, and the profile
fields it needs (authorization server URL, cached server metadata, and token expiry
from expires_in).

The authorization-code client IDs in transport/oauth.go are placeholders that reuse
the production device-flow IDs until distinct client credentials are provisioned.

Also bumps atlas-sdk to its latest release (v20250312021).

Jira ticket: CLOUDP-418563

Depends on: mongodb/go-client-mongodb-atlas#562

Checklist

  • I have signed the MongoDB CLA
  • I have added tests (transport + profile coverage)
  • I have run make fmt

jricher added 14 commits July 1, 2026 12:23
…oauth development

The Go module system requires the replaced module path to match the local
module's declared path. Our local atlas-sdk-go declares v20250312018, so
the replace directive targets that version and transport.go's import is
updated to match. The SDK version itself is otherwise unchanged in behavior.

Assisted-by: Claude Code (claude-sonnet-4-6)
… OAuth AS

Adds UserDelegation as a new AuthMechanism value for sessions created via
the new connect path. FlowForAuthIssuer creates an auth.Config that uses
the AuthServerURL field from the underlying library, keeping it separate
from the existing FlowWithConfig path and its OpsManagerURL/AccountURL
dependencies. Also wires the local go-client-mongodb-atlas checkout via
replace directive.

Assisted-by: Claude Code (claude-opus-4-6)
Routes UserDelegation sessions through NewAccessTokenTransportForAuthIssuer
so that token refresh targets the dedicated OAuth AS (AuthServerURL) instead
of the cloud.mongodb.com proxy. Placed after ServiceAccount in the switch
to preserve the existing UserAccount → ServiceAccount fallthrough behavior.

Assisted-by: Claude Code (claude-opus-4-6)
Stores the discovered OAuth AS metadata as a nested object in the profile
config, with server response and cache expiry kept as separate sub-keys
to avoid collisions with server-defined fields.

Assisted-by: Claude Code (claude-opus-4-6)
…orAuthIssuer

Enables overriding the auth server URL and client ID via atlas config set
or environment variables (MONGODB_ATLAS_AUTH_SERVER_URL, MONGODB_ATLAS_CLIENT_ID),
following the same precedence as FlowWithConfig: profile override wins,
gov default is the fallback.

Assisted-by: Claude Code (claude-opus-4-6)
Adds token_expiry profile field and stops parsing the access token as a
JWT. The expiry is stored at token acquisition time and loaded back
through tokenClaims for compatibility with the existing Token() flow.

Assisted-by: Claude Code (claude-opus-4-6)
UserDelegation reads expiry from the stored token_expiry field without
parsing the access token. All other auth types retain the existing JWT
parsing behavior so that AccessTokenSubject and Token expiry continue
to work for legacy login sessions.

Assisted-by: Claude Code (claude-opus-4-6)
Introduces authServerTransport as a separate transport type that manages
its own token lifecycle using discovered OAuth AS metadata. Reads the
token endpoint from cached metadata and refreshes via RefreshAccessToken.
Follows the same self-contained pattern as NewServiceAccountClientWithHost.

ProfileProvider extended with AuthServerMetadata and SetTokenExpiry so
the transport can read metadata and persist refreshed token expiry.

Assisted-by: Claude Code (claude-opus-4-6)
The note explaining that an unverified JWT parse is intentional on the
legacy path got dropped when the UserDelegation branch was added.
Pulled it back verbatim and grouped it with the existing "all other
auth types" lead-in and the migration TODO.

Assisted-by: Claude Code (claude-opus-4-6)
Earlier commits on this branch added SetTokenExpiry and
AuthServerMetadata to ProfileProvider without regenerating the mock,
breaking go vet on the transport package.

Assisted-by: Claude Code (claude-opus-4-6)
Covers FlowForAuthIssuer client ID and AuthServerURL selection
including the gov defaults and overrides, authServerTransport.RoundTrip
on valid and expired tokens, the missing-token-endpoint error path,
the UserDelegation case in HTTPClientFromProfile, and the new
TokenExpiry, AuthServerURL, AuthServerMetadata profile fields plus
the UserDelegation branch of tokenClaims.

Assisted-by: Claude Code (claude-opus-4-7)
The dedicated AS path requires the atlas scope. The previous setting
of [openid, profile, offline_access] was copied from the legacy
FlowWithConfig device-flow path, which talks to a different AS
(auth.mongodb.com via the cloud.mongodb.com proxy) and does use
OIDC scopes.

Assisted-by: Claude Code (claude-opus-4-7)
Resolve go-client and atlas-sdk from their released module versions
rather than local sibling checkouts.

Assisted-by: Claude Code (claude-opus-4-8)
Match the atlas-sdk version used by the CLI so both modules resolve
the same release.

Assisted-by: Claude Code (claude-opus-4-8)
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.

1 participant