$npx -y skills add vercel-labs/portless --skill oauthConfigure 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
| 1 | # OAuth with Portless |
| 2 | |
| 3 | 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. |
| 4 | |
| 5 | ## The Problem |
| 6 | |
| 7 | When portless uses the default `.localhost` TLD, OAuth providers reject redirect URIs like `http://myapp.localhost:1355/callback`: |
| 8 | |
| 9 | | Provider | `localhost` | `.localhost` subdomains | Reason | |
| 10 | | --------- | ----------- | ----------------------- | ------------------------------ | |
| 11 | | Google | Allowed | Rejected | Not in their bundled PSL | |
| 12 | | Apple | Rejected | Rejected | No localhost at all | |
| 13 | | Microsoft | Allowed | Allowed | Permissive localhost handling | |
| 14 | | Facebook | Allowed | Varies | Must register each URI exactly | |
| 15 | | GitHub | Allowed | Allowed | Permissive | |
| 16 | |
| 17 | Google and Apple are the strictest. Microsoft and GitHub are more lenient with localhost. |
| 18 | |
| 19 | ## The Fix |
| 20 | |
| 21 | Use a valid TLD so the redirect URI passes provider validation: |
| 22 | |
| 23 | ```bash |
| 24 | portless proxy start --tld dev |
| 25 | portless myapp next dev |
| 26 | # -> https://myapp.dev |
| 27 | ``` |
| 28 | |
| 29 | Any TLD in the Public Suffix List works: `.dev`, `.app`, `.com`, `.io`, etc. |
| 30 | |
| 31 | ### Use a domain you own |
| 32 | |
| 33 | Bare TLDs like `.dev` mean `myapp.dev` could collide with a real domain. Use a subdomain of a domain you control: |
| 34 | |
| 35 | ```bash |
| 36 | portless proxy start --tld dev |
| 37 | portless myapp.local.yourcompany next dev |
| 38 | # -> https://myapp.local.yourcompany.dev |
| 39 | ``` |
| 40 | |
| 41 | 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`. |
| 42 | |
| 43 | ## Provider Setup |
| 44 | |
| 45 | |
| 46 | |
| 47 | 1. Go to [Google Cloud Console > Credentials](https://console.cloud.google.com/apis/credentials) |
| 48 | 2. Create or edit an OAuth 2.0 Client ID (Web application) |
| 49 | 3. Add the portless domain to **Authorized JavaScript origins**: `https://myapp.dev` |
| 50 | 4. Add the callback to **Authorized redirect URIs**: `https://myapp.dev/api/auth/callback/google` |
| 51 | |
| 52 | 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. |
| 53 | |
| 54 | HTTPS is required for `.dev` and `.app` (HSTS-preloaded). Portless handles this automatically with `--https`. |
| 55 | |
| 56 | ### Apple |
| 57 | |
| 58 | Apple Sign In does not allow `localhost` or IP addresses at all. |
| 59 | |
| 60 | 1. Go to [Apple Developer > Certificates, Identifiers & Profiles](https://developer.apple.com/account/resources) |
| 61 | 2. Register a Services ID |
| 62 | 3. Configure Sign In with Apple, adding the portless domain as a **Return URL**: `https://myapp.dev/api/auth/callback/apple` |
| 63 | |
| 64 | 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. |
| 65 | |
| 66 | ### Microsoft (Entra / Azure AD) |
| 67 | |
| 68 | 1. Go to [Azure Portal > App registrations](https://portal.azure.com/#view/Microsoft_AAD_RegisteredApps) |
| 69 | 2. Create or edit an app registration |
| 70 | 3. Under **Authentication**, add a **Web** redirect URI: `https://myapp.dev/api/auth/callback/azure-ad` |
| 71 | |
| 72 | 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. |
| 73 | |
| 74 | ### Facebook (Meta) |
| 75 | |
| 76 | 1. Go to [Meta for Developers > App Dashboard](https://developers.facebook.com/apps/) |
| 77 | 2. Under **Facebook Login > Settings**, add the portless URL to **Valid OAuth Redirect URIs**: `https://myapp.dev/api/auth/callback/facebook` |
| 78 | |
| 79 | Facebook requires each redirect URI to be registered exactly (no wildcards). Strict Mode (enabled by default) enforces exact matching. |
| 80 | |
| 81 | ### GitHub |
| 82 | |
| 83 | 1. Go to [GitHub Developer Settings > OAuth Apps](https://github.com/settings/developers) |
| 84 | 2. Set **Authorization callback URL**: `https://myapp.dev/api/auth/callback/github` |
| 85 | |
| 86 | GitHub is permissive with localhost and subdomains. A custom TLD is not strictly required but keeps the setup consistent. |
| 87 | |
| 88 | ## Auth Library Configuration |
| 89 | |
| 90 | ### NextAuth / Auth.js |
| 91 | |
| 92 | Set `NEXTA |