-
Notifications
You must be signed in to change notification settings - Fork 1
[Feature] Add OAuth2 authentication and profile management system #12
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Implements a comprehensive authentication system with OAuth2 PKCE flow and multi-profile support: Authentication Features: - OAuth2 login with PKCE (Proof Key for Code Exchange) flow using Braintrust MCP endpoints - API key authentication fallback for headless/CI environments - Automatic token refresh for expired OAuth2 tokens - Profile-based credential storage in ~/.config/bt/config.json - Support for multiple named profiles with --profile flag (default: "DEFAULT") Profile Management: - Store API URL, access token, refresh token, expiry, org_name, and default project per profile - bt auth login - OAuth2 or API key login - bt auth token - Display current token and TTL - bt auth logout - Remove profile Credential Resolution: - Priority: --api-key flag > profile auth > SDK fallback - OAuth2 tokens work without org_name (JWT contains identity) - API keys require org_name for x-bt-org-name header - Project resolution: --project flag > BRAINTRUST_DEFAULT_PROJECT env > profile.project Projects API Updates: - Conditional org_name handling for OAuth2 vs API key authentication - list_projects, create_project, get_project_by_name support both auth methods Test Coverage: - 20 new tests for auth.rs covering PKCE generation, token refresh, OAuth parsing - 10 new tests for config.rs covering profile CRUD operations - All 51 unit tests passing Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
| // OAuth2 tokens don't need org_name filtering | ||
| "/v1/project".to_string() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
they do, actually. in fact, oauth tokens are not scoped to orgs, but api keys are.
in general, this code should be not any different based on what type of token you use.
| /// Auth profile to use | ||
| #[arg(long, env = "BRAINTRUST_PROFILE", default_value = "DEFAULT")] | ||
| pub profile: String, | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is an auth profile in the context of braintrust?
| pub struct LoginArgs { | ||
| /// Profile name to use | ||
| #[arg(long, default_value = "DEFAULT")] | ||
| pub profile: String, | ||
|
|
||
| /// API URL (defaults to https://api.braintrust.dev) | ||
| #[arg(long)] | ||
| pub api_url: Option<String>, | ||
|
|
||
| /// Use API key instead of OAuth2 (for headless/CI) | ||
| #[arg(long)] | ||
| pub api_key: bool, | ||
|
|
||
| /// Optional default project for this profile | ||
| #[arg(long)] | ||
| pub project: Option<String>, | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these arguments should not be duplicated from the base
| return Ok(orgs[selection].clone()); | ||
| } | ||
|
|
||
| // Fallback: prompt user for org name with helpful guidance |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these fallbacks are usually bugs
| .context("failed to parse OAuth discovery response") | ||
| } | ||
|
|
||
| fn generate_code_verifier() -> String { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would rather use an oauth library
Summary
Implements a comprehensive authentication system with OAuth2 PKCE flow and multi-profile support:
Authentication Features:
~/.config/bt/config.json--profileflag (default: "DEFAULT")Profile Management:
bt auth login- OAuth2 or API key loginbt auth token- Display current token and TTLbt auth logout- Remove profileCredential Resolution:
--api-keyflag > profile auth > SDK fallbackorg_name(JWT contains identity)org_nameforx-bt-org-nameheader--projectflag >BRAINTRUST_DEFAULT_PROJECTenv >profile.projectProjects API Updates:
org_namehandling for OAuth2 vs API key authenticationlist_projects,create_project,get_project_by_namesupport both auth methodsTest Coverage:
Recording
cli_update.mov