feat!: drop the backend-side elevation windows; password and passkey sessions share capabilities, passkeys guard what nodes verify; the trust page lists added and removed passkeys [CI]
This commit is contained in:
1 parent
f704c66dd9
commit
4106f831dc
34 files changed
+191
-1364
No files matched your search
@@ -82,45 +82,6 @@ export async function signStatement(statement: string): Promise<SignedStatementD
|
||||
}
|
||||
}
|
||||
|
||||
/** 提权窗口的种类:加节点、吊销和删除、改凭证(用一次就没有)。 */
|
||||
export type ElevationClass = 'enroll' | 'revoke' | 'credential'
|
||||
|
||||
export const ELEVATED_EVENT = 'moshiro:elevated'
|
||||
|
||||
/**
|
||||
* 用已有的 passkey 触碰一次,给当前会话开一个提权窗口。用户取消返回 false;没有 passkey 等服务端拒绝的情况抛 ApiError。
|
||||
* 浏览器只会让用户选自己的 passkey(服务端给了 allow_credentials)。
|
||||
*/
|
||||
export async function elevate(elevation: ElevationClass): Promise<boolean> {
|
||||
const options = await api.post<PasskeyRequestOptionsDto>('/api/admin/auth/elevation/options', { class: elevation })
|
||||
let credential: PublicKeyCredential | null
|
||||
try {
|
||||
credential = (await navigator.credentials.get({
|
||||
publicKey: {
|
||||
challenge: toBytes(options.challenge),
|
||||
rpId: options.rp_id,
|
||||
timeout: options.timeout_ms,
|
||||
userVerification: 'required',
|
||||
allowCredentials: (options.allow_credentials ?? []).map((id) => ({ type: 'public-key' as const, id: toBytes(id) })),
|
||||
},
|
||||
})) as PublicKeyCredential | null
|
||||
} catch (e) {
|
||||
if (e instanceof DOMException && (e.name === 'NotAllowedError' || e.name === 'AbortError')) return false
|
||||
throw e
|
||||
}
|
||||
if (!credential) return false
|
||||
const response = credential.response as AuthenticatorAssertionResponse
|
||||
await api.post('/api/admin/auth/elevation', {
|
||||
class: elevation,
|
||||
credential_id: credential.id,
|
||||
authenticator_data: toText(response.authenticatorData),
|
||||
client_data_json: toText(response.clientDataJSON),
|
||||
signature: toText(response.signature),
|
||||
})
|
||||
window.dispatchEvent(new Event(ELEVATED_EVENT))
|
||||
return true
|
||||
}
|
||||
|
||||
/** 给当前登录的用户注册一个新 passkey(要求用户验证,ES256)。 */
|
||||
export async function registerPasskey(name: string, place: PasskeyPlace = 'device'): Promise<PasskeyDto> {
|
||||
const options = await api.post<PasskeyCreationOptionsDto>('/api/admin/auth/passkeys/options')
|
||||
|
||||
Reference in new issue
Block a user