feat(auth): add webauthn authentication support

This commit is contained in:
BiFangKNT
2026-09-12 12:17:26 +08:00
parent 45d77c3926
commit b594cf23e4
18 changed files with 1370 additions and 2 deletions
+80
View File
@@ -1304,12 +1304,92 @@ export class BackendClient extends BaseHttpClient {
invitation_registration_enabled?: boolean;
password_login_enabled?: boolean;
space_login_enabled?: boolean;
passkey_login_enabled?: boolean;
passkey_supported?: boolean;
}> {
return this.get('/api/v1/user/account-info', undefined, {
skipWorkspace: true,
});
}
// ============ Passkey (WebAuthn) API ============
public getPasskeyAuthOptions(
email?: string,
origin?: string,
): Promise<{ options: any; challenge_token: string }> {
return this.post(
'/api/v1/user/passkey/auth/options',
{ email, origin },
{ skipWorkspace: true },
);
}
public verifyPasskeyAuth(
challenge_token: string,
credential: any,
): Promise<{ token: string; user: string }> {
return this.post(
'/api/v1/user/passkey/auth/verify',
{ challenge_token, credential },
{ skipWorkspace: true },
);
}
public getPasskeyRegisterOptions(
origin?: string,
): Promise<{ options: any; challenge_token: string }> {
return this.post(
'/api/v1/user/passkey/register/options',
{ origin },
{ skipWorkspace: true },
);
}
public verifyPasskeyRegister(
challenge_token: string,
credential: any,
name?: string,
): Promise<{ uuid: string; name: string; created_at?: string }> {
return this.post(
'/api/v1/user/passkey/register/verify',
{ challenge_token, credential, name },
{ skipWorkspace: true },
);
}
public getPasskeys(): Promise<
Array<{
uuid: string;
name: string;
aaguid?: string;
transports?: string;
backed_up?: boolean;
created_at?: string;
last_used_at?: string;
}>
> {
return this.get('/api/v1/user/passkeys', undefined, {
skipWorkspace: true,
});
}
public renamePasskey(
uuid: string,
name: string,
): Promise<{ uuid: string; name: string }> {
return this.patch(
`/api/v1/user/passkey/${encodeURIComponent(uuid)}`,
{ name },
{ skipWorkspace: true },
);
}
public deletePasskey(uuid: string): Promise<void> {
return this.delete(`/api/v1/user/passkey/${encodeURIComponent(uuid)}`, {
skipWorkspace: true,
});
}
// ============ Workspace API ============
public getWorkspaceBootstrap(): Promise<WorkspaceBootstrapResponse> {
return this.get('/api/v1/workspaces/bootstrap', undefined, {