news 2026/9/15 14:14:25

Portless 本地开发 OAuth 实战指南:用自定义 TLD 解决 redirect_uri_mismatch

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Portless 本地开发 OAuth 实战指南:用自定义 TLD 解决 redirect_uri_mismatch

Portless 本地开发 OAuth 实战指南:用自定义 TLD 解决 redirect_uri_mismatch

【免费下载链接】portlessReplace port numbers with stable, named local URLs. For humans and agents.项目地址: https://gitcode.com/GitHub_Trending/por/portless

导读

本文讲解如何在 portless 本地开发环境中配置 OAuth 登录(Google、Apple、Microsoft、Facebook、GitHub 等),核心解决 "redirect_uri_mismatch"、"invalid redirect URI" 等常见报错。你会掌握:为什么.localhost子域名会被多数 OAuth 提供商拒绝、如何用portless proxy start --tld让本地应用跑在真实合法域名上、各提供商控制台的精确配置步骤,以及 NextAuth/Auth.js、Passport.js 等常见认证库的对接方式。读完即可在本地完整跑通 Google OAuth 登录。

问题根源:.localhost子域名无法通过 OAuth 校验

OAuth 提供商在登记回调地址时,会按照各自规则校验重定向 URI 的域名。portless 默认使用.localhost作为 TLD,生成的本地 URL 形如http://myapp.localhost:1355/callback。这类地址在多数提供商处会被直接拒绝:

Providerlocalhost.localhost子域名原因
Google允许拒绝不在其内置的 Public Suffix List(PSL)中
Apple拒绝拒绝完全不支持 localhost
Microsoft允许允许对 localhost 处理宽松
Facebook允许视情况而定必须精确注册每一个 URI
GitHub允许允许宽松

其中 Google 与 Apple 最严格。Google 的 OAuth 凭据页面会用它内置的一份 Public Suffix List 校验回调域名,.localhost不在其中,因此myapp.localhost:3000会被报错:"must end with a public top-level domain (such as .com or .org)";纯localhost之所以可以,是因为 Google 把它硬编码进了白名单,但子域名不行。Apple Sign In 则干脆连localhost和 IP 地址都不允许。

解决方案:用--tld让应用跑在真实域名上

portless 支持用--tld指定任意合法 TLD 启动代理,让本地应用获得一个能通过提供商校验的域名:

portless proxy start --tld dev portless myapp next dev # -> https://myapp.dev

Public Suffix List 中的任何 TLD 都可以:.dev.app.com.io等。.dev是 Google 拥有的真实 gTLD,且被 HSTS 预加载(HSTS-preloaded),浏览器会强制 HTTPS——portless 默认开启 HTTPS 并自动处理证书,无需额外配置。

推荐:使用你拥有的多段域名

裸 TLD 意味着myapp.dev可能与别人拥有的真实域名撞车。更稳妥的做法是把域名结构放到 TLD 里,使用你控制下的多段 TLD:

portless proxy start --tld local.yourcompany.dev portless myapp next dev # -> https://myapp.local.yourcompany.dev

这样能保证没有出站流量到达你不拥有的资源。对团队而言,设置一条通配 DNS 记录(*.local.yourcompany.dev -> 127.0.0.1),每个开发者在没有/etc/hosts的情况下也能解析,且所有开发者在提供商控制台共享同一组回调 URI。

portless 本身对多段 TLD 有原生支持:TLD 可以是dev.example.com这样的多段 DNS 名称,让本地 URL 镜像生产结构(myapp.dev.example.com),每个标签遵循 DNS 规则(小写字母、数字、内部连字符,每段最长 63 字符,总计 253 字符)。当配置了多个重叠 TLD(如example.comdev.example.com)时,主机名会先匹配最长的 TLD,与配置顺序无关。

各提供商控制台配置

Google

  1. 打开 Google Cloud Console > Credentials
  2. 创建或编辑一个 OAuth 2.0 Client ID(Web application)
  3. Authorized JavaScript origins中加入 portless 域名:https://myapp.dev
  4. Authorized redirect URIs中加入回调地址:https://myapp.dev/api/auth/callback/google

Google 按 Public Suffix List 校验域名,域名必须以可识别的 TLD 结尾,.localhost子域名无法通过;.dev.app.com等都可以。注意.dev.app因 HSTS 预加载强制要求 HTTPS,portless 用--https自动处理。

Apple

Apple Sign In 完全不允许localhost和 IP 地址。

  1. 打开 Apple Developer > Certificates, Identifiers & Profiles
  2. 注册一个 Services ID
  3. 配置 Sign In with Apple,把 portless 域名加入Return URLhttps://myapp.dev/api/auth/callback/apple

域名必须是真实、可公网解析的域名。由于 portless 在本地把域名映射到 127.0.0.1,浏览器可以解析,但 Apple 的服务端校验可能要求域名也能公开解析。如果 Apple 拒绝该域名,为开发子域名添加一条指向127.0.0.1的公网 DNS A 记录。

Microsoft(Entra / Azure AD)

  1. 打开 Azure Portal > App registrations
  2. 创建或编辑应用注册
  3. Authentication下添加Web重定向 URI:https://myapp.dev/api/auth/callback/azure-ad

Microsoft 允许开发场景下的http://localhost(任意端口),多数情况下也接受.localhost子域名。但为了一致性,仍建议用 portless 的自定义 TLD 统一各提供商的配置。

Facebook(Meta)

  1. 打开 Meta for Developers > App Dashboard
  2. Facebook Login > Settings中,把 portless URL 加入Valid OAuth Redirect URIshttps://myapp.dev/api/auth/callback/facebook

Facebook 要求每个重定向 URI 必须精确注册(不支持通配符),默认开启的 Strict Mode 强制精确匹配。

GitHub

  1. 打开 GitHub Developer Settings > OAuth Apps
  2. 设置Authorization callback URLhttps://myapp.dev/api/auth/callback/github

GitHub 对 localhost 和子域名都很宽松,自定义 TLD 并非必需,但可以让整套配置保持一致。

认证库配置

NextAuth / Auth.js

设置NEXTAUTH_URL与 portless 域名保持一致:

NEXTAUTH_URL=https://myapp.dev

NextAuth 用它来构造回调 URL;不设置的话回调可能落到localhost上导致不匹配。Auth.js v5 对应的环境变量是AUTH_URL=https://myapp.dev

Passport.js

在每个策略里把callbackURL指向 portless 域名:

new GoogleStrategy({ clientID: process.env.GOOGLE_CLIENT_ID, clientSecret: process.env.GOOGLE_CLIENT_SECRET, callbackURL: process.env.BASE_URL + "/auth/google/callback", });

然后在环境中设置BASE_URL=https://myapp.dev

通用 / 手动方案

读取 portless 注入到子进程的PORTLESS_URL环境变量(其实现位于 cli.ts,代码把PORTLESS_URL作为环境变量传给被代理的子进程,并使用配置的第一个 TLD):

const baseUrl = process.env.PORTLESS_URL || "http://localhost:3000"; const callbackUrl = `${baseUrl}/auth/callback`;

疑难排查

"redirect_uri_mismatch" 或 "invalid redirect URI"

OAuth 流程中发出的重定向 URI 与提供商登记的不一致。逐项检查:

  1. 提供商登记的 URI 与 portless 域名完全一致(协议、主机、路径)
  2. NEXTAUTH_URL或等价变量已设置为 portless URL(而不是localhost
  3. 代理以正确的 TLD 运行,用portless list验证当前路由

提供商强制 HTTPS

.dev.app是 HSTS 预加载域名,浏览器强制 HTTPS。启动代理:

portless proxy start --tld dev

portless 默认在 443 端口启用 HTTPS(必要时自动用 sudo 提权)。运行portless trust把本地 CA 加入系统信任库,消除浏览器证书警告。

Apple 拒绝域名

Apple 可能要求域名可公开解析。为开发子域名添加指向127.0.0.1的 DNS A 记录:

myapp.local.yourcompany.dev A 127.0.0.1

或使用通配符:*.local.yourcompany.dev A 127.0.0.1

登录后回调跳到错误 URL

认证库用localhost而不是 portless 域名构造回调 URL。设置对应环境变量:

  • NextAuthNEXTAUTH_URL=https://myapp.dev
  • Auth.js v5AUTH_URL=https://myapp.dev
  • 手动方案PORTLESS_URL会被自动注入,直接用作 base URL

完整可运行示例

仓库中的 examples/google-oauth 是一个 Next.js + NextAuth + Google OAuth 的完整可运行示例,使用--tld dev。其package.json通过"portless": "google-oauth-example.portless"指定应用名,认证路由 只使用GOOGLE_CLIENT_IDGOOGLE_CLIENT_SECRET两个环境变量注册 GoogleProvider,首页 提供 "Continue with Google" 登录按钮并实时展示当前域名、协议与 TLD。

按以下步骤运行:

npm install -g portless portless proxy start --tld dev

创建 Google OAuth 客户端(Web application),填入 Authorized JavaScript originshttps://oauth-test.dev与 Authorized redirect URIshttps://oauth-test.dev/api/auth/callback/google,然后:

cd examples/google-oauth cp .env.example .env

编辑.env

GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com GOOGLE_CLIENT_SECRET=your-client-secret NEXTAUTH_SECRET=generate-with-openssl-rand-base64-32 NEXTAUTH_URL=https://oauth-test.dev

openssl rand -base64 32生成NEXTAUTH_SECRET,最后安装依赖并启动:

pnpm install pnpm dev

这会执行portless oauth-test next dev,把应用发布到https://oauth-test.dev。浏览器打开该地址点击 "Continue with Google" 即可验证完整登录流程。

如果只想用 Google OAuth 且不愿更换 TLD,也可以额外注册http://localhost:3000/api/auth/callback/google作为回调 URI(Google 允许带任意端口的纯localhost),并设置NEXTAUTH_URL=http://localhost:3000——代价是 OAuth 回调流程失去 portless 的命名 URL、无端口冲突等收益。

小结

OAuth 提供商对.localhost子域名的拒绝是本地开发对接第三方登录时最常见的拦路虎。portless 通过--tld把本地应用映射到真实合法域名,既绕过了 PSL 校验,又保留了命名 URL 的全部开发体验。对团队场景,配合自持域名与通配 DNS,还能实现所有开发者共享同一组回调 URI 与配置。结合本仓库的 OAuth 技能文档 与 google-oauth 示例,即可在几分钟内让本地 OAuth 登录跑通。

【免费下载链接】portlessReplace port numbers with stable, named local URLs. For humans and agents.项目地址: https://gitcode.com/GitHub_Trending/por/portless

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/15 14:14:14

量化实盘分时数据流水线搭建指南

1. 为什么“全市场日内分时扫描”不是个简单需求,而是量化实盘的分水岭你有没有试过在早盘9:25刚集合竞价结束,就想知道沪深两市3000多只股票里,哪些票在前5分钟出现了异常放量?或者想回测一个“分时突破布林带上轨成交量放大2倍”…

作者头像 李华
网站建设 2026/9/15 14:13:47

uniapp+uniCloud博客社区源码拆解:一套代码跑三端

简介:博客社区项目完整前后端源码,基于uniapp开发,可直接打包生成H5、Android App及微信小程序,适合具备Vue基础的移动端开发者、全栈学习者及需要快速搭建社区类应用的团队参考。压缩包共1588个文件,约31.34MB&#x…

作者头像 李华
网站建设 2026/9/15 14:13:46

WorkBuddy智能体工作台:从安装配置到自动化任务编排指南

1. WorkBuddy是什么,为什么它和CodeBuddy不是一回事先说一个我观察到的现象:很多人第一次听到CloudQ WorkBuddy,第一反应是“这不就是又一个ChatGPT壳子吗”,然后装完打开一看,发现界面里全是任务流、Skill、知识库、定…

作者头像 李华