oauth
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 .lo
By vercel-labs · 2,872 installs
npx skills add vercel-labs/portless --skill oauth
Source repository · Upstream listing
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
Google Allowed Rejected Not in their bundled PSL
Apple Rejected Rejected No localhost at all
Microsoft Allowed Allowed Permissive localhost handling
Facebook 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:
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 multi segment TLD under a domain you control, so the app name stays clean and the domain structure lives in the TLD:
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 , and every developer shares the same redirect URIs in the provider console.
Provider Setup
Google
1. Go to [Google Cloud Console Credentials](https://console.cloud.google.com/apis/credentials)
2. Create or edit an OAuth 2.0 Client ID (Web application)
3. Add the portless domain to Authorized JavaScript origins : https://myapp.dev
4. 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.
1. Go to [Apple Developer Certificates, Identifiers & Profiles](https://developer.apple.com/account/resources)
2. Register a Services ID
3. 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)
1. Go to [Azure Portal App registrations](https://portal.azure.com/ view/Microsoft AAD RegisteredApps)
2. Create or edit an app registration
3. 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)
1. Go to [Meta for Developers App Dashboard](https://developers.facebook.com/apps/)
2. 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
1. Go to [GitHub Developer Settings OAuth Apps](https://github.com/settings/developers)
2. 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 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:
Set BASE URL=https://myapp.dev in your environment.
Generic / Manual
Read the PORTLESS URL environment variable that portless injects into the child process:
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:
1. The provider's registered redirect URI matches the portless domain exactly (protocol, host, path)
2. NEXTAUTH URL or equivalent is set to the portless URL (not localhost )
3. The proxy is running with the correct TLD ( portless list to verify)
Provider requires HTTPS
.dev and .app TLDs are HSTS preloaded, so browsers force HTTPS. Start the proxy:
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 :
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 URL is injected automatically; use it as the base URL
Example
See [ examples/google oauth ](../../examples/google oauth) for a complete working example with Next.js + NextAuth + Google OAuth using tld dev .