Skip to content

✨ Add CLI authentication with OAuth device flow#56

Merged
Robdel12 merged 2 commits intomainfrom
rd/cli-login
Oct 16, 2025
Merged

✨ Add CLI authentication with OAuth device flow#56
Robdel12 merged 2 commits intomainfrom
rd/cli-login

Conversation

@Robdel12
Copy link
Contributor

@Robdel12 Robdel12 commented Oct 16, 2025

Summary

Implements a comprehensive authentication system for the Vizzly CLI using OAuth 2.0 device authorization grant flow.

Features

Authentication Commands

  • vizzly login - Browser-based OAuth authentication with auto-filled device code
  • vizzly logout - Clear stored authentication tokens
  • vizzly whoami - Display current user, organizations, and token status
  • vizzly project:select - Configure project-specific token for current directory
  • vizzly project:list - Show all configured projects
  • vizzly project:token - Display project token for current directory
  • vizzly project:remove - Remove project configuration

Token Management

Token Priority (highest to lowest):

  1. CLI flag (--token)
  2. Environment variable (VIZZLY_TOKEN)
  3. Project mapping (~/.vizzly/config.json)
  4. User access token (~/.vizzly/config.json)

Features:

  • Automatic token refresh on 401 responses
  • 30-day token expiry with 5-minute buffer
  • Secure storage in ~/.vizzly/config.json with 0600 permissions
  • Project tokens mapped by directory path
  • Directory traversal for parent project lookups

Developer Experience

  • Browser auto-opens with pre-filled device code
  • Clear prompts and error messages
  • JSON output mode for scripting (--json)
  • Verbose mode for debugging (--verbose)

Technical Implementation

New Files

  • src/commands/login.js - OAuth device flow implementation
  • src/commands/logout.js - Token cleanup
  • src/commands/whoami.js - User info display
  • src/commands/project.js - Project selection/management
  • src/services/auth-service.js - Authentication API client
  • src/utils/global-config.js - Token storage utilities
  • src/utils/browser.js - Cross-platform browser opening

Modified Files

  • src/cli.js - Added new commands
  • src/services/api-service.js - Token refresh on 401, accepts both apiKey and token
  • src/utils/config-loader.js - Token resolution priority logic
  • src/commands/run.js - Minor updates for auth integration

Test Coverage

114 new tests added (698 total, all passing)

  • ✅ Global config utilities (28 tests)
  • ✅ Token resolution priority (16 tests)
  • ✅ AuthService (21 tests)
  • ✅ Login command (11 tests)
  • ✅ Logout command (8 tests)
  • ✅ Whoami command (14 tests)
  • ✅ Project commands (16 tests)

Testing approach:

  • Layered testing (unit tests at service layer, command layer)
  • Mocked HTTP at service level
  • Mocked services at command level
  • 100% coverage of authentication features

Breaking Changes

None - this is purely additive functionality.

Migration Guide

Users can now authenticate in two ways:

Option 1: User authentication (recommended for local development)

vizzly login
vizzly project:select  # Optional: set project-specific token
vizzly run "npm test"

Option 2: Environment variable (recommended for CI)

export VIZZLY_TOKEN=vzt_your_project_token
vizzly run "npm test"

The CLI will automatically use the appropriate token based on priority.

Related Issues

Resolves VIZ-21

Implements comprehensive authentication system for the CLI:

**Authentication Flow:**
- OAuth 2.0 device authorization grant flow
- Browser-based login with auto-filled code
- User/organization context display
- Token refresh with 30-day expiry
- Secure token storage in ~/.vizzly/config.json (0600 perms)

**Commands:**
- `vizzly login` - Authenticate via browser OAuth flow
- `vizzly logout` - Clear stored tokens
- `vizzly whoami` - Display user info and token status
- `vizzly project:select` - Configure project for directory
- `vizzly project:list` - Show all configured projects
- `vizzly project:token` - Display project token
- `vizzly project:remove` - Remove project configuration

**Token Priority (highest to lowest):**
1. CLI flag (--token)
2. Environment variable (VIZZLY_TOKEN)
3. Project mapping (~/.vizzly/config.json)
4. User access token (~/.vizzly/config.json)

**Key Features:**
- Project-specific tokens mapped to directories
- Automatic token refresh on 401 responses
- Graceful fallback through token priority chain
- Directory traversal for project mapping lookup
- JSON output support for scripting

**Test Coverage:**
- 114 new tests (698 total, all passing)
- 100% coverage of auth features:
  - Global config utilities (28 tests)
  - Token resolution priority (16 tests)
  - AuthService (21 tests)
  - Login command (11 tests)
  - Logout command (8 tests)
  - Whoami command (14 tests)
  - Project commands (16 tests)
@claude
Copy link

claude bot commented Oct 16, 2025

Code Review: CLI Authentication with OAuth Device Flow

I've completed a comprehensive review of PR #56. This is an excellent implementation of OAuth device flow authentication! The code is well-structured, thoroughly tested, and follows security best practices.

✅ Strengths

1. Excellent Architecture & Design

  • Clean separation of concerns: Auth logic in AuthService, token storage in global-config.js, commands are thin wrappers
  • Token priority system is well-designed: CLI flag → env var → project mapping → user token
  • Automatic token refresh: The 401 handler in api-service.js:78-122 is elegant and prevents user friction
  • Directory traversal for project lookups: Smart feature that checks parent directories (global-config.js:199-218)

2. Outstanding Test Coverage

  • 114 new tests, all passing - this is exemplary
  • Tests cover edge cases (corrupted config files, expired tokens, rate limiting)
  • Proper layering with mocked dependencies

3. Security Best Practices

  • File permissions: Config files created with 0o600 (global-config.js:77)
  • Graceful permission failures on Windows
  • Token expiry with buffer: 5-minute buffer prevents edge cases
  • Server-side token revocation on logout
  • User-Agent tracking

4. Great Developer Experience

  • Auto-opens browser with pre-filled device code
  • Clear, helpful error messages
  • JSON output mode for scripting
  • Interactive prompts for organization/project selection
  • Backward compatible (no breaking changes)

🔍 Issues & Recommendations

High Priority

1. Command Injection Vulnerability in browser.js 🚨

Location: src/utils/browser.js:20-26

Issue: URLs are not escaped before being passed to shell commands. A malicious URL could execute arbitrary commands.

Fix: Use execFile instead of exec with proper argument arrays to prevent shell injection.

2. Missing Input Validation in Project Commands

Location: src/commands/project.js:88-93

The token extraction logic handles backward compatibility but doesn't validate token format. The fallback String(projectMapping.token) could produce invalid values.

Recommendation: Add validation for token format (should match vzt_... pattern).

Medium Priority

3. Race Condition in Login Flow

Location: src/commands/login.js:77-87

The login command waits for Enter key press, then polls once. Users might press Enter before authorizing in the browser.

Better approach: Implement polling with timeout (e.g., 60 attempts with 5-second intervals).

4. No Token Format Validation

Project tokens should follow format vzt_... but there's no validation. Consider adding a token validator utility.

5. Silent Errors in Logout

Server revocation failures only log to console. In --json mode, users won't see this. Consider logging to stderr.

6. Directory Permissions Not Verified

The directory is created with 0o700, but permissions aren't verified if it already exists.

🔒 Security Assessment

Good:

  • ✅ Tokens stored with restrictive permissions (0o600)
  • ✅ HTTPS enforced for API calls
  • ✅ No tokens logged (only prefixes shown)
  • ✅ Refresh tokens used for token rotation
  • ✅ Server-side revocation on logout

Concerns:

🎯 Overall Assessment

Grade: A- (Excellent work!)

This PR demonstrates:

  • ✅ Strong software engineering fundamentals
  • ✅ Excellent test coverage (114 tests!)
  • ✅ Good security practices
  • ✅ Clean, maintainable code
  • ✅ Great developer experience

Recommendation: Approve with required fix for command injection vulnerability

The command injection issue in browser.js is the only blocking concern. Everything else is polish and can be addressed in follow-up PRs if needed.

🎉 Great Job!

This is a well-thought-out implementation. The OAuth device flow is perfect for CLI tools, the test coverage is exemplary, and the UX is polished. Fix the command injection issue and this is ready to ship!

Files reviewed: 18 changed files, ~4000 lines
Tests: 114 new tests (all passing ✅)
CI Status: All checks passing ✅

- Replace exec() with execFile() to prevent shell injection attacks
- Pass URLs as discrete arguments instead of string interpolation
- Add comprehensive test coverage (16 tests) for all platforms
- Test security scenarios with malicious URL patterns

📚 Add authentication documentation

- Update README with authentication commands and token priority
- Create comprehensive authentication guide (docs/authentication.md)
- Update getting-started.md with auth workflow options
- Add authentication commands to API reference
- Document OAuth device flow, token refresh, and security
@Robdel12 Robdel12 merged commit 62db77d into main Oct 16, 2025
14 checks passed
@Robdel12 Robdel12 deleted the rd/cli-login branch October 16, 2025 05:53
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