mirror of
https://github.com/we-promise/sure.git
synced 2026-05-08 05:04:59 +00:00
* feat(auth): add WebAuthn MFA credentials * fix(auth): harden WebAuthn MFA review paths * fix(auth): polish WebAuthn error handling * fix(auth): handle duplicate WebAuthn credential races * fix(auth): permit WebAuthn credential params * fix(auth): trim WebAuthn registration controller cleanup * fix(auth): tighten WebAuthn MFA handling * fix(auth): pin WebAuthn relying party config
86 lines
2.4 KiB
JavaScript
86 lines
2.4 KiB
JavaScript
function bufferToBase64url(buffer) {
|
|
const bytes = new Uint8Array(buffer);
|
|
const binary = String.fromCharCode(...bytes);
|
|
|
|
return btoa(binary)
|
|
.replace(/\+/g, "-")
|
|
.replace(/\//g, "_")
|
|
.replace(/=+$/g, "");
|
|
}
|
|
|
|
function base64urlToBuffer(value) {
|
|
const base64 = value.replace(/-/g, "+").replace(/_/g, "/");
|
|
const padded = base64.padEnd(
|
|
base64.length + ((4 - (base64.length % 4)) % 4),
|
|
"=",
|
|
);
|
|
const binary = atob(padded);
|
|
const bytes = new Uint8Array(binary.length);
|
|
|
|
for (let i = 0; i < binary.length; i += 1) {
|
|
bytes[i] = binary.charCodeAt(i);
|
|
}
|
|
|
|
return bytes.buffer;
|
|
}
|
|
|
|
export function prepareCredentialCreationOptions(options) {
|
|
options.challenge = base64urlToBuffer(options.challenge);
|
|
options.user.id = base64urlToBuffer(options.user.id);
|
|
options.excludeCredentials = (options.excludeCredentials || []).map(
|
|
(credential) => ({
|
|
...credential,
|
|
id: base64urlToBuffer(credential.id),
|
|
}),
|
|
);
|
|
|
|
return options;
|
|
}
|
|
|
|
export function prepareCredentialRequestOptions(options) {
|
|
options.challenge = base64urlToBuffer(options.challenge);
|
|
options.allowCredentials = (options.allowCredentials || []).map(
|
|
(credential) => ({
|
|
...credential,
|
|
id: base64urlToBuffer(credential.id),
|
|
}),
|
|
);
|
|
|
|
return options;
|
|
}
|
|
|
|
export function serializePublicKeyCredential(credential) {
|
|
const serialized = {
|
|
id: credential.id,
|
|
rawId: bufferToBase64url(credential.rawId),
|
|
type: credential.type,
|
|
authenticatorAttachment: credential.authenticatorAttachment,
|
|
clientExtensionResults: credential.getClientExtensionResults(),
|
|
};
|
|
|
|
if (credential.response.attestationObject) {
|
|
serialized.response = {
|
|
attestationObject: bufferToBase64url(
|
|
credential.response.attestationObject,
|
|
),
|
|
clientDataJSON: bufferToBase64url(credential.response.clientDataJSON),
|
|
transports: credential.response.getTransports
|
|
? credential.response.getTransports()
|
|
: [],
|
|
};
|
|
} else {
|
|
serialized.response = {
|
|
authenticatorData: bufferToBase64url(
|
|
credential.response.authenticatorData,
|
|
),
|
|
clientDataJSON: bufferToBase64url(credential.response.clientDataJSON),
|
|
signature: bufferToBase64url(credential.response.signature),
|
|
userHandle: credential.response.userHandle
|
|
? bufferToBase64url(credential.response.userHandle)
|
|
: null,
|
|
};
|
|
}
|
|
|
|
return serialized;
|
|
}
|