WebAuthn:无法在子域

时间:2021-02-09 14:23:41

标签: java angular webauthn

我有一个 Angular 11(前端)和 Kotlin(后端)项目,我在其中实现了 WebAuthn 登录。

作品的注册很简单,我从(WebAuthn4J)后端收到了一个挑战,并用这个创建了凭据:

...

const credentialOptions: CredentialCreationOptions = {
   publicKey: {
     attestation: 'direct',
     user: {
       name: 'UsernameXYZ',
       displayName: 'UsernameXYZ',
       id: decodeUrlSafeB64(btoa('<uuid-from-db>'))
     },
     rp: {
       id: 'my-company.com',
       name: 'My Company'
     },
     challenge: challenge, // Challenge from Backend as B64
     pubKeyCredParams: [
       {
         type: 'public-key',
         alg: -257 // RS256
       },
       {
         type: 'public-key',
         alg: -7 // ES256
       }
     ],
     authenticatorSelection: undefined // All options possible
   }
 };
 const credentials: Credential = await navigator.credentials.create(credentialOptions);

 ...

现在,我可以毫无问题地登录 my-company.com。但是我不能登录other.my-company.com,我不明白为什么。 WebAuthn 对话框(来自 Win10)显示“无法识别身份验证器”(不完全是,因为消息是德语)。

我所做的就是将有效的 credentialIds(我从后端收到)交给导航器。

...

const credIds: Array<PublicKeyCredentialDescriptor> = [];
credentialIds.forEach((credentialId) => {
  credIds.push({
    type: 'public-key',
    id: decodeUrlSafeB64(credentialId)
  });
});

// my-company.com --> WebAuthn Dialog as expected
// other.my-company.com --> WebAuthnDialog does not recognize key
navigator.credentials.get({
  publicKey: {
    challenge: challenge, // Challenge for Login from Backend
    allowCredentials: credIds,
    userVerification: 'preferred'
  }
});

...

但是,当我从 other.my-company.com 注册时:

rp: {
  id: 'other.my-company.com',
  name: 'My Company'
},

我现在可以从 my-company.comother.my-company.com 登录。这适用于我现在的设置,但是当我计划扩展我的项目并在 another.my-company.com 登录时,这将不起作用。

我阅读了规范,它对这个设置非常不具体,尽管我认为它很常见:https://www.w3.org/TR/webauthn/#relying-party-identifier

在一个类似的 SO 问题中,它说我在这里的设置应该可以工作(尽管没有任何来源):WebAuthn across multiple subdomain

我在实现逻辑时也遵循了这一点:https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API

我不知道去哪里研究。我使用的 WebAuthn4J 实现 (https://github.com/webauthn4j/webauthn4j) 工作得很好,事实证明我可以从上面的两个设置中登录。

我想出的唯一其他选择是将整个登录/注册过程与应用程序的其余部分分开,以便每次登录都重定向到 sso.my-company.com,使用 WebAuthn 登录,获取 JWT 并重定向回到原来的应用程序。但这真的是我唯一的选择吗?对于我想做的事情,即“注册一个域并允许所有子域”来说,这似乎太过分了。

任何提示(甚至只指向我链接的其他规格)

1 个答案:

答案 0 :(得分:1)

您需要在断言期间将 RP ID 设置为创建期间使用的相同 RP ID。如果您不设置它,它将默认为当前来源并包含子域,因此它将不再匹配。