Skip to content

feat: implement OAuth PKCE browser login#20

Merged
gnapse merged 4 commits into
mainfrom
feat/oauth-pkce-login
Jan 26, 2026
Merged

feat: implement OAuth PKCE browser login#20
gnapse merged 4 commits into
mainfrom
feat/oauth-pkce-login

Conversation

@gnapse

@gnapse gnapse commented Jan 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements #7 - OAuth PKCE flow for browser-based authentication.

Changes

New files

  • src/lib/pkce.ts - PKCE utilities (code verifier, challenge, state)
  • src/lib/oauth-server.ts - Local HTTP callback server with state validation
  • src/lib/oauth.ts - OAuth URL builder and token exchange

Modified files

  • src/commands/auth.ts - Integrated OAuth flow into login command
  • src/lib/auth.ts - Added client ID config support
  • package.json - Added open dependency

How it works

  1. User runs ol auth login
  2. Prompted for base URL and OAuth client ID
  3. PKCE code verifier/challenge generated
  4. Local callback server starts on random port
  5. Browser opens to Outline's OAuth authorize endpoint
  6. User authorizes → redirected to local server
  7. Server validates state, extracts auth code
  8. Code exchanged for access token (with code_verifier)
  9. Token saved to config

Backwards compatibility

  • ol auth login --token <token> preserved for manual API token auth
  • Client ID remembered in config for future logins
  • Supports OUTLINE_OAUTH_CLIENT_ID env var

Setup

  1. Create a public OAuth app in Outline (Settings → Applications)
  2. Set redirect URI to http://localhost (any port)
  3. Run ol auth login and enter the client ID when prompted

Closes #7

Ubuntu added 3 commits January 26, 2026 00:09
Implements #7 - OAuth PKCE flow for browser-based authentication.

New files:
- src/lib/pkce.ts - PKCE utilities (code verifier, challenge, state)
- src/lib/oauth-server.ts - Local HTTP callback server
- src/lib/oauth.ts - OAuth URL builder and token exchange

Changes:
- ol auth login now opens browser for OAuth authorization
- ol auth login --token preserved for manual API token auth
- Client ID configurable via OUTLINE_OAUTH_CLIENT_ID env or prompt
- Client ID persisted in config for future logins

Flow:
1. Generate PKCE code_verifier + code_challenge + state
2. Start local callback server on localhost
3. Open browser to authorize endpoint
4. Receive callback with auth code
5. Exchange code for access token
6. Save token to config

Note: Requires user to register a public OAuth app in Outline settings.
Blocked by outline/outline#11254 (HTTPS redirect URI requirement).

Copilot AI left a comment

Copy link
Copy Markdown

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 implements OAuth PKCE browser-based authentication as an alternative to manual API token entry, addressing issue #7. The implementation follows the standard OAuth 2.0 authorization code flow with PKCE for public clients.

Changes:

  • Adds OAuth PKCE flow with three new library modules (pkce.ts, oauth-server.ts, oauth.ts) for cryptographic utilities, local callback server, and OAuth client operations
  • Integrates OAuth flow into the ol auth login command while preserving backwards compatibility with --token flag for manual authentication
  • Adds OAuth client ID configuration support with environment variable and config file storage

Reviewed changes

Copilot reviewed 8 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/lib/pkce.ts Implements PKCE utilities (code verifier, challenge, state generation) with proper cryptographic functions
src/lib/oauth-server.ts Local HTTP callback server that validates state and extracts authorization codes
src/lib/oauth.ts OAuth authorization URL builder and token exchange implementation
src/commands/auth.ts Integrates OAuth flow into login command with backwards-compatible manual token option
src/lib/auth.ts Adds OAuth client ID configuration support with env var and config file
src/tests/auth.test.ts Adds basic tests for OAuth client ID retrieval functions
package.json Adds open dependency for browser launching
pnpm-lock.yaml Lock file updates for new dependency
package-lock.json Lock file updates for new dependency
README.md Documents OAuth setup process and maintains manual token flow documentation
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

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

Comment thread src/lib/oauth-server.ts
Comment thread src/lib/pkce.ts
Comment thread src/lib/oauth-server.ts
Comment thread src/commands/auth.ts
- Handle OAuth error responses (e.g., access_denied) with descriptive messages
- Prevent race condition in server error handler by setting resolved flag
@gnapse

gnapse commented Jan 26, 2026

Copy link
Copy Markdown
Contributor Author

Addressed Copilot's feedback:

Fixed - OAuth error handling: Now properly checks for error param and shows descriptive messages (e.g., "OAuth authorization denied: access_denied")

Fixed - Server error race condition: Error handler now sets resolved = true to prevent timeout from double-firing

📋 Acknowledged - Missing tests for OAuth modules: Fair point, will add in a follow-up PR

ℹ️ Noted - Defense-in-depth cleanup: Current timeout fallback + built-in finally cleanup already handles this

@gnapse gnapse merged commit b7f6eec into main Jan 26, 2026
2 checks passed
@gnapse gnapse deleted the feat/oauth-pkce-login branch January 26, 2026 00:31
gnapse pushed a commit that referenced this pull request Jan 26, 2026
Adds comprehensive test coverage for:
- pkce.ts: code verifier/challenge generation, RFC 7636 compliance
- oauth.ts: authorization URL building, token exchange with error handling
- oauth-server.ts: HTTP server behavior, success path, routing

Addresses Copilot review feedback from PR #20.
github-actions Bot pushed a commit that referenced this pull request Mar 25, 2026
# 1.0.0 (2026-03-25)

### Bug Fixes

* broaden CI detection to handle all truthy values ([7dc2806](7dc2806))
* exclude dist from biome checks ([0dc49a3](0dc49a3))

### Features

* add API Spinner Proxy ([#17](#17)) ([a3bc75a](a3bc75a))
* add fuzzy reference resolution ([#19](#19)) ([6c1c6f9](6c1c6f9))
* add npm publishing, new agent skills, and skill auto-update ([#36](#36)) ([bcb2e75](bcb2e75)), closes [Doist/todoist-cli#176](Doist/todoist-cli#176) [Doist/bob-cli#17](Doist/bob-cli#17) [Doist/twist-cli#101](Doist/twist-cli#101)
* add structured error formatting with codes and hints ([#18](#18)) ([17658d2](17658d2))
* implement OAuth PKCE browser login ([#20](#20)) ([b7f6eec](b7f6eec)), closes [#7](#7) [outline/outline#11254](outline/outline#11254)
* improve oauth login inputs and callback UX ([#31](#31)) ([3011b28](3011b28))
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement OAuth PKCE browser login

2 participants