oauth
vercel-labs/portless
Configure OAuth providers to work with portless local dev URLs by using valid TLDs instead of .localhost.
What is oauth?
This skill helps you set up OAuth redirect URIs for local development with portless. Use it when OAuth providers reject .localhost subdomains, you encounter redirect_uri_mismatch errors, or need to configure sign-in providers (Google, Apple, Microsoft, Facebook, GitHub) for local testing.
- Use valid TLDs (.dev, .app, .com, .io) instead of .localhost to pass OAuth provider validation
- Configure redirect URIs for Google, Apple, Microsoft, Facebook, and GitHub OAuth providers
- Set environment variables (NEXTAUTH_URL, AUTH_URL, BASE_URL) to match portless domains
- Troubleshoot redirect_uri_mismatch and invalid redirect URI errors
- Enable HTTPS automatically for HSTS-preloaded TLDs like .dev and .app
How to install oauth
npx skills add https://github.com/vercel-labs/portless --skill oauth- Portless installed and proxy running with --tld flag
- OAuth credentials (Client ID/Secret) from your provider
- For Apple: a publicly-resolvable domain or DNS A record pointing to 127.0.0.1
How to use oauth
- 1.Start the portless proxy with a valid TLD: portless proxy start --tld dev
- 2.Register your portless domain with each OAuth provider (e.g., https://myapp.dev)
- 3.Add the callback URI to each provider (e.g., https://myapp.dev/api/auth/callback/google)
- 4.Set the appropriate environment variable (NEXTAUTH_URL, AUTH_URL, or BASE_URL) to your portless domain
- 5.Run your app with portless: portless myapp next dev (or equivalent)
- 6.Test OAuth sign-in; if it fails, verify the registered redirect URI matches exactly
Use cases
- Setting up Google OAuth with portless local dev URLs
- Configuring Apple Sign In which rejects localhost entirely
- Fixing redirect_uri_mismatch errors during local OAuth testing
- Using a team subdomain (e.g., myapp.local.yourcompany.dev) to avoid domain collisions
- Troubleshooting OAuth callback failures with NextAuth or Passport.js
- Full-stack developers building apps with OAuth authentication
- Teams setting up local development environments with shared subdomains
- Developers using NextAuth, Auth.js, Passport.js, or manual OAuth implementations
- Anyone testing social login (Google, Apple, Microsoft, Facebook, GitHub) locally
oauth FAQ
.localhost subdomains are not in the Public Suffix List or are explicitly blocked by most providers (Google, Apple). Valid TLDs like .dev, .app, .com, and .io pass validation.
Any TLD in the Public Suffix List works. For teams, use a subdomain of a domain you own (e.g., myapp.local.yourcompany.dev) to avoid collisions with real domains and ensure no outbound traffic to unknown hosts.
Yes. For HSTS-preloaded TLDs like .dev and .app, portless defaults to HTTPS on port 443. Run portless trust to add the local CA to your system trust store and eliminate browser warnings.
Apple requires publicly-resolvable domains. Add a DNS A record for your dev subdomain pointing to 127.0.0.1, or use a wildcard record (*.local.yourcompany.dev A 127.0.0.1).
Ensure the registered redirect URI matches exactly (protocol, host, path), set the correct environment variable (NEXTAUTH_URL, AUTH_URL, or BASE_URL) to your portless domain, and verify the proxy is running with the correct TLD.
Full instructions (SKILL.md)
Source of truth, from vercel-labs/portless.
name: oauth description: Configure OAuth providers (Google, Apple, Microsoft, Facebook, GitHub, etc.) to work with portless local dev URLs. Use when setting up OAuth redirect URIs, fixing "redirect_uri_mismatch" or "invalid redirect" errors, configuring sign-in providers for local development, or when a provider rejects .localhost subdomains. Triggers include "OAuth not working with portless", "redirect URI mismatch", "Google/Apple/Microsoft sign-in fails locally", "configure OAuth for local dev", or any task involving OAuth callback URLs with portless domains.
OAuth with Portless
OAuth providers validate redirect URIs against domain rules. .localhost subdomains fail on most providers because they are not in the Public Suffix List or are explicitly blocked. Portless fixes this with --tld to serve apps on real, valid domains.
The Problem
When portless uses the default .localhost TLD, OAuth providers reject redirect URIs like http://myapp.localhost:1355/callback:
| Provider | localhost | .localhost subdomains | Reason |
|---|---|---|---|
| Allowed | Rejected | Not in their bundled PSL | |
| Apple | Rejected | Rejected | No localhost at all |
| Microsoft | Allowed | Allowed | Permissive localhost handling |
| Allowed | Varies | Must register each URI exactly | |
| GitHub | Allowed | Allowed | Permissive |
Google and Apple are the strictest. Microsoft and GitHub are more lenient with localhost.
The Fix
Use a valid TLD so the redirect URI passes provider validation:
portless proxy start --tld dev
portless myapp next dev
# -> https://myapp.dev
Any TLD in the Public Suffix List works: .dev, .app, .com, .io, etc.
Use a domain you own
Bare TLDs like .dev mean myapp.dev could collide with a real domain. Use a subdomain of a domain you control:
portless proxy start --tld dev
portless myapp.local.yourcompany next dev
# -> https://myapp.local.yourcompany.dev
This ensures no outbound traffic reaches something you don't own. For teams, set a wildcard DNS record (*.local.yourcompany.dev -> 127.0.0.1) so every developer gets resolution without /etc/hosts.
Provider Setup
- Go to Google Cloud Console > Credentials
- Create or edit an OAuth 2.0 Client ID (Web application)
- Add the portless domain to Authorized JavaScript origins:
https://myapp.dev - Add the callback to Authorized redirect URIs:
https://myapp.dev/api/auth/callback/google
Google validates domains against the Public Suffix List. The domain must end with a recognized TLD. .localhost subdomains fail this check; .dev, .app, .com, etc. all pass.
HTTPS is required for .dev and .app (HSTS-preloaded). Portless handles this automatically with --https.
Apple
Apple Sign In does not allow localhost or IP addresses at all.
- Go to Apple Developer > Certificates, Identifiers & Profiles
- Register a Services ID
- Configure Sign In with Apple, adding the portless domain as a Return URL:
https://myapp.dev/api/auth/callback/apple
The domain must be a real, publicly-resolvable domain name. Since portless maps the domain to 127.0.0.1 locally, the browser resolves it but Apple's server-side validation may require the domain to resolve publicly too. If Apple rejects the domain, add a public DNS A record pointing to 127.0.0.1 for your dev subdomain.
Microsoft (Entra / Azure AD)
- Go to Azure Portal > App registrations
- Create or edit an app registration
- Under Authentication, add a Web redirect URI:
https://myapp.dev/api/auth/callback/azure-ad
Microsoft allows http://localhost with any port for development. It also accepts .localhost subdomains in most cases. Using a custom TLD with portless is still recommended for consistency across providers.
Facebook (Meta)
- Go to Meta for Developers > App Dashboard
- Under Facebook Login > Settings, add the portless URL to Valid OAuth Redirect URIs:
https://myapp.dev/api/auth/callback/facebook
Facebook requires each redirect URI to be registered exactly (no wildcards). Strict Mode (enabled by default) enforces exact matching.
GitHub
- Go to GitHub Developer Settings > OAuth Apps
- Set Authorization callback URL:
https://myapp.dev/api/auth/callback/github
GitHub is permissive with localhost and subdomains. A custom TLD is not strictly required but keeps the setup consistent.
Auth Library Configuration
NextAuth / Auth.js
Set NEXTAUTH_URL to match the portless domain:
NEXTAUTH_URL=https://myapp.dev
NextAuth uses this to construct callback URLs. Without it, callbacks may use localhost and cause a mismatch.
Passport.js
Set the callbackURL in each strategy to use the portless domain:
new GoogleStrategy({
clientID: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
callbackURL: process.env.BASE_URL + "/auth/google/callback",
});
Set BASE_URL=https://myapp.dev in your environment.
Generic / Manual
Read the PORTLESS_URL environment variable that portless injects into the child process:
const baseUrl = process.env.PORTLESS_URL || "http://localhost:3000";
const callbackUrl = `${baseUrl}/auth/callback`;
Troubleshooting
"redirect_uri_mismatch" or "invalid redirect URI"
The redirect URI sent during the OAuth flow doesn't match what's registered with the provider. Check:
- The provider's registered redirect URI matches the portless domain exactly (protocol, host, path)
NEXTAUTH_URLor equivalent is set to the portless URL (notlocalhost)- The proxy is running with the correct TLD (
portless listto verify)
Provider requires HTTPS
.dev and .app TLDs are HSTS-preloaded, so browsers force HTTPS. Start the proxy:
portless proxy start --tld dev
Portless defaults to HTTPS on port 443 (auto-elevates with sudo). Run portless trust to add the local CA to your system trust store and eliminate browser warnings.
Apple rejects the domain
Apple may require the domain to resolve publicly. Add a DNS A record for your dev subdomain pointing to 127.0.0.1:
myapp.local.yourcompany.dev A 127.0.0.1
Or use a wildcard: *.local.yourcompany.dev A 127.0.0.1.
Callback goes to wrong URL after sign-in
The auth library is constructing the callback URL from localhost instead of the portless domain. Set the appropriate environment variable:
- NextAuth:
NEXTAUTH_URL=https://myapp.dev - Auth.js v5:
AUTH_URL=https://myapp.dev - Manual:
PORTLESS_URLis injected automatically; use it as the base URL
Example
See examples/google-oauth for a complete working example with Next.js + NextAuth + Google OAuth using --tld dev.
Related skills
More from vercel-labs/portless and the wider catalog.

portless
Replace port numbers with stable, named .localhost URLs for local development.

find-skills
Discover and install agent skills to extend your coding agent's capabilities on demand

nextjs
Expert guidance for building, debugging, and architecting Next.js applications with App Router.

react-best-practices
React best-practices reviewer for TSX files. Triggers after editing multiple TSX components to run a condensed quality checklist covering component structure, hooks usage, accessibility, performance, and TypeScript patterns.

shadcn
shadcn/ui expert guidance — CLI, component installation, composition patterns, custom registries, theming, Tailwind CSS integration, and high-quality interface design. Use when initializing shadcn, adding components, composing product UI, building custom registries, configuring themes, or troubleshooting component issues.

ai-elements
Pre-built React components for AI chat interfaces, built on shadcn/ui.