WebAuthn子域名无法登录问题:Angular+Kotlin项目中的跨域认证需求咨询
你的问题核心在于WebAuthn RP ID的匹配规则,其实规范里明确支持主域名注册的凭证在所有子域名使用,只是你在登录时漏掉了关键配置项。
关键原因分析
你注册时把rp.id设为my-company.com(主域名)是正确的——根据WebAuthn规范,RP ID必须是当前页面域名的**注册域名(Registered Domain)**或其父级注册域名(不能是.com这类公共后缀)。但登录时,在子域名other.my-company.com调用navigator.credentials.get()时,你没有显式指定rp.id,浏览器会默认将当前子域名作为RP ID,而你的凭证是绑定到my-company.com的,两者不匹配,所以认证器找不到对应的密钥,弹出“认证器未被识别”的提示。
反过来,当你在子域名注册时把rp.id设为other.my-company.com,主域名能正常登录,是因为my-company.com是other.my-company.com的父级注册域名,满足WebAuthn的RP ID后缀匹配规则——主域名页面可以调用指定子域名RP ID的get()接口,从而匹配到对应凭证。
具体解决方案
你只需要在登录时的get()调用中显式指定rp.id为主域名,不管当前是主域名还是任何子域名:
navigator.credentials.get({ publicKey: { challenge: challenge, allowCredentials: credIds, userVerification: 'preferred', rpId: 'my-company.com' // 关键:显式设置为主域名的RP ID } });
这样做的逻辑是:
- 浏览器会验证当前页面域名(比如
other.my-company.com)是否是rpId(my-company.com)的后缀,符合规则就允许调用 - 认证器会查找绑定到
my-company.com的凭证,和你传入的credIds匹配后,就能正常弹出验证窗口
额外注意事项
- 必须使用HTTPS:WebAuthn要求所有页面都在安全上下文(HTTPS)中运行,包括主域名和所有子域名
- 确认注册域名有效性:确保
my-company.com是你的注册域名,不能是.co.uk这类公共后缀(如果是二级公共后缀,RP ID需要设为yourcompany.co.uk) - 保持RP ID一致:注册和登录时的
rp.id必须完全相同(都是my-company.com),不能混用主域名和子域名
关于SSO方案的对比
你提到的将登录流程分离到sso.my-company.com的方案确实可行,但对于你的需求来说没必要——用上述方法,所有子域名都可以直接调用WebAuthn的get()接口,只要显式指定主域名的RP ID,就能共享主域名注册的凭证,无需额外跳转。
内容的提问来源于stack exchange,提问作者PrimuS

