我有一个 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.com
和 other.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 并重定向回到原来的应用程序。但这真的是我唯一的选择吗?对于我想做的事情,即“注册一个域并允许所有子域”来说,这似乎太过分了。
任何提示(甚至只指向我链接的其他规格)