A lightweight local HTTP server for handling OAuth 2.0 authorization callbacks in Node.js, Deno, and Bun applications. Perfect for CLI tools, desktop applications, and development environments that need to capture OAuth authorization codes.
- 🚀 Multi-runtime support - Works with Node.js 18+, Deno, and Bun
- 🔒 Secure localhost-only server for OAuth callbacks
- ⚡ Minimal dependencies - Only requires
open
package - 🎯 TypeScript support out of the box
- 🛡️ Comprehensive OAuth error handling with detailed error classes
- 🔄 Automatic server cleanup after callback
- 🎪 Clean success pages with animated checkmark
- 🎨 Customizable HTML templates with placeholder support
- 🚦 AbortSignal support for programmatic cancellation
- 📝 Request logging and debugging callbacks
- 🌐 Modern Web Standards APIs (Request/Response/URL)
bun add oauth-callback
Or with npm:
npm install oauth-callback
import { getAuthCode, OAuthError } from "oauth-callback";
// Simple usage
const result = await getAuthCode(
"https://example.com/oauth/authorize?client_id=xxx&redirect_uri=http://localhost:3000/callback",
);
console.log("Authorization code:", result.code);
import { getAuthCode, OAuthError } from "oauth-callback";
async function authenticate() {
const authUrl =
"https://github.com/login/oauth/authorize?" +
new URLSearchParams({
client_id: "your_client_id",
redirect_uri: "http://localhost:3000/callback",
scope: "user:email",
state: "random_state_string",
});
try {
const result = await getAuthCode(authUrl);
console.log("Authorization code:", result.code);
console.log("State:", result.state);
// Exchange code for access token
// ... your token exchange logic here
} catch (error) {
if (error instanceof OAuthError) {
console.error("OAuth error:", error.error);
console.error("Description:", error.error_description);
} else {
console.error("Unexpected error:", error);
}
}
}
import { getAuthCode } from "oauth-callback";
const result = await getAuthCode({
authorizationUrl: authUrl,
port: 8080, // Use custom port (default: 3000)
timeout: 60000, // Custom timeout in ms (default: 30000)
});
// Google OAuth
const googleAuth = await getAuthCode(
"https://accounts.google.com/o/oauth2/v2/auth?" +
new URLSearchParams({
client_id: process.env.GOOGLE_CLIENT_ID,
redirect_uri: "http://localhost:3000/callback",
response_type: "code",
scope: "openid email profile",
access_type: "offline",
}),
);
// Microsoft OAuth
const microsoftAuth = await getAuthCode(
"https://login.microsoftonline.com/common/oauth2/v2.0/authorize?" +
new URLSearchParams({
client_id: process.env.MICROSOFT_CLIENT_ID,
redirect_uri: "http://localhost:3000/callback",
response_type: "code",
scope: "user.read",
response_mode: "query",
}),
);
// With custom HTML templates and logging
const result = await getAuthCode({
authorizationUrl: authUrl,
port: 3000,
hostname: "127.0.0.1", // Bind to specific IP
successHtml: "<h1>Success! You can close this window.</h1>",
errorHtml: "<h1>Error: {{error_description}}</h1>",
onRequest: (req) => {
console.log(`Received request: ${req.method} ${req.url}`);
},
});
// With cancellation support
const controller = new AbortController();
// Cancel after 10 seconds
setTimeout(() => controller.abort(), 10000);
try {
const result = await getAuthCode({
authorizationUrl: authUrl,
signal: controller.signal,
});
} catch (error) {
if (error.message === "Operation aborted") {
console.log("Authorization was cancelled");
}
}
Starts a local HTTP server and opens the authorization URL in the user's browser.
-
input
(string | GetAuthCodeOptions): Either a string containing the OAuth authorization URL, or an options object with:-
authorizationUrl
(string): The OAuth authorization URL -
port
(number): Port for the local server (default: 3000) -
hostname
(string): Hostname to bind the server to (default: "localhost") -
callbackPath
(string): URL path for the OAuth callback (default: "/callback") -
timeout
(number): Timeout in milliseconds (default: 30000) -
openBrowser
(boolean): Whether to open browser automatically (default: true) -
successHtml
(string): Custom HTML to display on successful authorization -
errorHtml
(string): Custom HTML to display on authorization error -
signal
(AbortSignal): AbortSignal for cancellation support -
onRequest
(function): Callback fired when a request is received (for logging/debugging)
-
Promise that resolves to:
{
code: string; // Authorization code
state?: string; // State parameter (if provided)
[key: string]: any; // Additional query parameters
}
-
OAuthError
: When the OAuth provider returns an error (always thrown for OAuth errors) -
Error
: For timeout or other unexpected errors
Custom error class for OAuth-specific errors.
class OAuthError extends Error {
error: string; // OAuth error code
error_description?: string; // Human-readable error description
error_uri?: string; // URI with error information
}
- Server Creation: Creates a temporary HTTP server on the specified port
- Browser Launch: Opens the authorization URL in the user's default browser
- Callback Handling: Waits for the OAuth provider to redirect back with the authorization code
- Cleanup: Automatically closes the server after receiving the callback
- Result: Returns the authorization code and any additional parameters
- The server only accepts connections from localhost
- Server is closed immediately after receiving the callback
- No data is stored persistently
- State parameter validation should be implemented by the application
Try the library instantly with the built-in demo that includes a mock OAuth server:
# Run the demo - no credentials needed!
bun run example:demo
# Run without opening browser (for CI/testing)
bun run examples/demo.ts --no-browser
The demo showcases:
- Dynamic client registration (simplified OAuth 2.0 DCR)
- Complete authorization flow with mock provider
- Multiple scenarios (success, access denied, invalid scope)
- Custom HTML templates for success/error pages
- Token exchange and API usage simulation
For testing with GitHub OAuth:
# Set up GitHub OAuth App credentials
export GITHUB_CLIENT_ID="your_client_id"
export GITHUB_CLIENT_SECRET="your_client_secret"
# Run the GitHub example
bun run example:github
This example demonstrates:
- Setting up OAuth with GitHub
- Handling the authorization callback
- Exchanging the code for an access token
- Using the token to fetch user information
For testing with Notion's Model Context Protocol server:
# No credentials needed - uses Dynamic Client Registration!
bun run example:notion
This example demonstrates:
- Dynamic Client Registration (OAuth 2.0 DCR) - no pre-configured client ID/secret needed
- Integration with Model Context Protocol (MCP) servers
- Automatic client registration with the authorization server
- Using the MCP SDK's OAuth capabilities
# Install dependencies
bun install
# Run tests
bun test
# Build
bun run build
# Run examples
bun run example:demo # Interactive demo
bun run example:github # GitHub OAuth example
bun run example:notion # Notion MCP example with Dynamic Client Registration
- Node.js 18+ (for native Request/Response support), Deno, or Bun 1.0+
- A registered OAuth application with a provider
- Redirect URI configured as
http://localhost:[port]/callback
If port 3000 is already in use, specify a different port:
const result = await getAuthCode({ authorizationUrl: authUrl, port: 8080 });
On first run, your OS may show a firewall warning. Allow the connection for localhost only.
If the browser doesn't open automatically, manually navigate to the authorization URL.
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add some amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
This project is released under the MIT License. Feel free to use it in your projects, modify it to suit your needs, and share it with others. We believe in open source and hope this tool makes OAuth integration easier for everyone!
- MCP Client Generator - Generate TypeScript clients from MCP server specifications. Perfect companion for building MCP-enabled applications with OAuth support (npm).
- React Starter Kit - Full-stack React application template with authentication, including OAuth integration examples.
Support this project by becoming a backer. Your logo will show up here with a link to your website.
Found a bug or have a question? Please open an issue on the GitHub issue tracker and we'll be happy to help. If this project saves you time and you'd like to support its continued development, consider becoming a sponsor. Every bit of support helps maintain and improve this tool for the community. Thank you!