我一遍又一遍地尝试让密钥身份验证显示 rp 名称而不是 rp id。最初,我将后端 url (rp id) 设置为子域 (api.project.ca),而我的前端是 projectname.project.ca。我在某处读到,子域不匹配可能会导致 chrome 对用户的保护过于热心,并显示 rp id 作为预防措施,但在重新设计我的基础设施后,将 CDN 放在它前面并路由它,以便所有流量都流向项目名称.project.ca,它仍然不会显示 rp 名称。边缘也一样。所以我不知道我在这里做错了什么,看起来这应该是一件简单的事情。我不是 100% 确定哪些代码在这里相关,但这里有一些我运行 navigator.create 的角度服务:
public register(
email: string,
attestOptions: AttestationOptions,
): Observable<FidoState> {
return new Observable((observer) => {
observer.next(FidoState.PendingBrowserPasskey);
const options = this.mapAttestOptions(attestOptions);
navigator.credentials
.create({
publicKey: options,
})
.then((cred) => {
const credential = cred as PublicKeyCredential;
observer.next(FidoState.PendingRegistration);
this.completeWebAuthnRegistration(email, credential, observer);
return credential;
})
.catch((error) => {
console.error('Error getting attestation options', error);
observer.next(FidoState.Error);
});
});
}
private mapAttestOptions(
options: AttestationOptions,
): PublicKeyCredentialCreationOptions {
const challengeArray = coerceToArrayBuffer(options.challenge);
const userId = coerceToArrayBuffer(options.user.id);
const publicKey: PublicKeyCredentialCreationOptions = {
...options,
attestation: 'direct',
challenge: challengeArray,
user: {
...options.user,
id: userId,
},
authenticatorSelection: {
requireResidentKey: false,
userVerification: 'discouraged',
},
excludeCredentials: options.excludeCredentials.map((cred) => ({
type: 'public-key',
id: coerceToArrayBuffer(cred.id),
})),
pubKeyCredParams: options.pubKeyCredParams.map((param) => ({
type: 'public-key',
alg: param.alg,
})),
};
return publicKey;
}
attestOptions 是我从下面的代码片段中的 C# 后端获取的 json 对象。我正在使用 Fido2 v3.0.1 nuget 包:
public async Task<AttestationOptionsResponse> GetAttestationOptions(string email)
{
Fido2User fidoUser = new()
{
Name = email,
DisplayName = email,
Id = Encoding.UTF8.GetBytes(email)
};
User? user = await db.Users.Include(u => u.Credentials).FirstOrDefaultAsync(u => u.Email == email);
List<PublicKeyCredentialDescriptor> storedCredentials =
[.. db
.Credentials
.Include(c => c.User)
.Where(c => c.User!.Email == email)
.Select(c => new PublicKeyCredentialDescriptor(c.CredentialId))];
CredentialCreateOptions options = fido.RequestNewCredential(fidoUser, storedCredentials, AuthenticatorSelection.Default, AttestationConveyancePreference.None);
return !await cache.StoreItemAsync(string.Format(CacheAttestStringFormat, email), options.ToJson())
? new AttestationOptionsResponse
{
Success = false,
ErrorCode = AttestationOptionsError.CacheError
}
: new AttestationOptionsResponse
{
Success = true,
Data = options.ToJson()
};
}
此时,注册在技术上是有效的,但我真的希望弹出窗口显示一个友好的名称,而不是 URL,并且根据 MDN 文档,这应该可行。谁能告诉我我在这里做错了什么?感谢您的帮助!
我最初尝试将 rp id 作为请求 URL 的子域,但将其更改为完全匹配。浏览器仍然显示 rp id,但我希望它显示 rp 名称。
没有大众市场客户端或验证器使用 RP 名称(主要是因为客户端不喜欢在受信任的 UI 内显示无法验证的不受信任的内容)。
建议仅使用 RP ID 作为名称。 WebAuthn 规范的未来版本将正式提出该建议。