Skip to content

feat: add OAuth2 authentication with PKCE support#84

Merged
nspringdd merged 9 commits intomainfrom
oauth2-auth-implementation
Feb 4, 2026
Merged

feat: add OAuth2 authentication with PKCE support#84
nspringdd merged 9 commits intomainfrom
oauth2-auth-implementation

Conversation

@nspringdd
Copy link
Contributor

@nspringdd nspringdd commented Jan 30, 2026

Summary

Adds OAuth2 authentication capability to the Datadog API Claude Plugin, enabling secure user authentication via browser-based login flow with PKCE protection. This is an alternative to API key authentication - users can now choose to authenticate either way.

Note: This PR adds OAuth2 authentication infrastructure only. No changes were made to the code generation functionality or how the plugin generates Datadog API client code.

What Users Can Do

With OAuth2 authentication, users can:

  • Login via browser: auth login opens Datadog authorization page
  • Check auth status: auth status shows current token state
  • Refresh tokens: auth refresh manually refreshes access token
  • Logout: auth logout clears stored tokens

OAuth2 Features

Feature Description
PKCE Flow Secure authorization code flow with S256 challenge method
Dynamic Client Registration Each CLI installation registers as a unique OAuth client
Secure Token Storage OS keychain (macOS/Windows/Linux) with encrypted file fallback
Automatic Token Refresh Background refresh before token expiration
Multi-site Support Works with all Datadog sites (US1, EU1, US3, US5, AP1, staging)

New Dependency

  • @napi-rs/keyring (^1.2.0): Native OS keychain integration for secure token storage (macOS Keychain, Windows Credential Manager, Linux Secret Service)

Supported OAuth Scopes

The OAuth flow requests access to these Datadog capabilities:

Category Scopes
Dashboards dashboards_read, dashboards_write
Monitors monitors_read, monitors_write, monitors_downtime
APM/Traces apm_read
SLOs slos_read, slos_write, slos_corrections
Incidents incident_read, incident_write
Synthetics synthetics_read, synthetics_write, synthetics_global_variable_*, synthetics_private_location_*
Security security_monitoring_signals_read, security_monitoring_rules_read, security_monitoring_findings_read, security_monitoring_suppressions_read, security_monitoring_filters_read
RUM rum_apps_read, rum_apps_write, rum_retention_filters_read, rum_retention_filters_write
Infrastructure hosts_read
Users user_access_read, user_self_profile_read
Cases cases_read, cases_write
Events events_read
Logs logs_read_data, logs_read_index_data
Metrics metrics_read, timeseries_query
Usage usage_read

Security Model

  • Per-installation client IDs: Each CLI installation gets a unique client_id via Dynamic Client Registration
  • Granular revocation: Revoke access for one installation without affecting others
  • No shared secrets: No hardcoded client credentials in the codebase
  • PKCE protection: Prevents authorization code interception attacks
  • CSRF protection: State parameter validation on OAuth callbacks

New Files

File Purpose
src/lib/auth/dcr-types.ts DCR TypeScript interfaces
src/lib/auth/dcr-client.ts DCR API client
src/lib/auth/client-credentials-storage.ts Secure storage for DCR credentials
src/lib/auth/oauth-client.ts OAuth2 PKCE flow implementation
src/lib/auth/token-refresher.ts Automatic token refresh
src/lib/auth/callback-server.ts Local HTTP server for OAuth callback
src/lib/auth/token-storage.ts Token storage abstraction
src/lib/auth/token-storage-factory.ts Storage factory for keychain/file selection
src/lib/auth/commands.ts CLI auth commands

Test Plan

  • Unit tests for all new modules (268 tests passing)
  • Manual test: Fresh login with DCR registration
  • Manual test: Re-login with existing DCR client
  • Manual test: Token refresh
  • Manual test: Logout and re-login
  • Manual test: Multi-site support (US1, EU1, staging)

Response by Claude 🤖

Implement OAuth2 Authorization Code Grant flow with PKCE for browser-based
authentication as an alternative to API keys.

New features:
- OAuth2 PKCE flow with secure code verifier/challenge generation
- Local callback server for receiving authorization codes
- Secure token storage at ~/.datadog/oauth_tokens.json (0600 permissions)
- Automatic token refresh with request deduplication
- CLI commands: auth login, logout, status, refresh

Changes:
- Add src/lib/auth/ module with oauth-client, token-storage, callback-server,
  token-refresher, and commands
- Update config.ts to support both API key and OAuth authentication
- Update client.ts with OAuthHttpLibrary for Bearer token auth
- Add OAuth error types to error-handler.ts
- Add auth command routing to index.ts
- Add .claude/ to .gitignore

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@datadog-official
Copy link

datadog-official bot commented Jan 30, 2026

✅ Library Vulnerabilities

🎉 All green!

📚 No new vulnerable libraries detected

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 3febc6f | Docs | Datadog PR Page | Was this helpful? Give us feedback!

…scopes

Updated DEFAULT_OAUTH_SCOPES to include all Datadog OAuth2 scopes that map
to current plugin tools. This enables OAuth authentication to work with the
full range of plugin functionality that has available scopes.

Scopes added:
- Monitors: monitors_read, monitors_write, monitors_downtime
- APM/Traces: apm_read
- SLOs: slos_read, slos_write, slos_corrections
- Incidents: incident_read, incident_write
- Synthetics: full read/write scopes including global variables and private locations
- Security: monitoring signals, rules, findings, suppressions, filters
- RUM: apps and retention filter scopes (rum_read/metrics not yet available)
- Infrastructure: hosts_read
- Users: user_access_read, user_self_profile_read
- Cases: cases_read, cases_write
- Events: events_read
- Metrics: metrics_read, timeseries_query (metrics_write not yet available)
- Usage: usage_read

Note: Some tools cannot use OAuth yet due to missing scopes:
- Logs (logs_read not available)
- Metrics submit (metrics_write not available)
- RUM events search (rum_read not available)
- Key Management (api_keys_*, app_keys_* not available)
- Fleet Automation (fleet_* not available)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Implement secure token storage using @napi-rs/keyring to store OAuth
tokens in the operating system's native secure storage:
- macOS: Keychain
- Windows: Credential Manager
- Linux: Secret Service (libsecret)

This provides hardware-backed encryption where available and eliminates
the security risk of storing tokens as plaintext JSON files.

Key changes:
- Add SecureTokenStorage class using @napi-rs/keyring
- Add TokenStorageFactory with auto-detection and fallback logic
- Add token migration from legacy file storage to keychain
- Rename TokenStorage to FileTokenStorage (with backward-compat alias)
- Add ITokenStorage interface for storage abstraction
- Update commands.ts to show storage backend in status
- Add DD_TOKEN_STORAGE env var for explicit backend selection

Selection priority:
1. DD_TOKEN_STORAGE=file → use file storage
2. DD_TOKEN_STORAGE=keychain → use keychain (fail if unavailable)
3. Auto-detect: try keychain, fall back to file with warning

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@nspringdd
Copy link
Contributor Author

One pretty clear downside of this approach is the lack of API key == no obvious way to use the send metrics or events functionality. Need to think about this a bit more

@platinummonkey
Copy link
Collaborator

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 42ea88e4b2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

The auth module is a CLI tool that requires console output for user
interaction (login prompts, status messages, error feedback). This
silences the DD Static Analyzer warnings for intentional console usage.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
nspringdd and others added 3 commits February 2, 2026 14:59
Implement RFC 7591 Dynamic Client Registration to replace hardcoded
OAuth client ID with per-installation dynamically registered clients.

Changes:
- Add dcr-types.ts with DCR interfaces and constants
- Add dcr-client.ts with registerClient() and getOrRegisterClient()
- Add client-credentials-storage.ts with keychain and file backends
- Update oauth-client.ts to require clientId parameter (no defaults)
- Update commands.ts to integrate DCR into login flow
- Update token-refresher.ts to use stored clientId for refresh
- Update callback-server.ts to prefer DCR-registered ports
- Remove hardcoded DATADOG_CLI_CLIENT_ID constant
- Fix RUM scope typos (rum_retention_filters_read/write)
- Add unit tests for all new modules

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix race condition in CallbackServer between start() and waitForCallback()
  by buffering callback results and using polling instead of duplicate handlers
- Add explicit comment for empty callback in test
- Fix test expectation for DCR redirect URIs (127.0.0.1 not localhost)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@nspringdd
Copy link
Contributor Author

@codex review

@chatgpt-codex-connector
Copy link

To use Codex here, create a Codex account and connect to github.

@nspringdd nspringdd marked this pull request as ready for review February 2, 2026 22:44
- Add OAuth as the primary authentication method with full command reference
- Document auth login, logout, status, and refresh commands
- Move API/APP key configuration to fallback option for CI/CD environments
- Add OAuth troubleshooting sections for expired tokens and browser issues
- Update security best practices to prioritize OAuth authentication
- Highlight secure OS keychain storage in Security First section

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@platinummonkey
Copy link
Collaborator

@codex review

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 456f1ea250

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Previously, findAvailablePort() would fall back to scanning ports
8000-9000 if the preferred ports (8000, 8080, 8888, 9000) were all
in use. However, only these four ports are registered with DCR, so
using any other port would result in an invalid_redirect_uri error.

Now the function only tries DCR-registered ports and throws a clear
error message if none are available, instead of silently failing with
a confusing OAuth error later.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@nspringdd nspringdd merged commit c2be571 into main Feb 4, 2026
4 checks passed
@nspringdd nspringdd deleted the oauth2-auth-implementation branch February 4, 2026 14:59
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.

2 participants