react-native-passkey
Version:
Passkey implementation for React Native
137 lines (136 loc) • 4.79 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.stringifyPasskeyRequest = stringifyPasskeyRequest;
const base64UrlChars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
function stringifyPasskeyRequest(request, platformOS) {
if (platformOS !== 'android') {
return JSON.stringify(request);
}
return JSON.stringify(normalizeAndroidRequest(request));
}
function normalizeAndroidRequest(request) {
var _request$allowCredent;
const normalized = {
...request,
challenge: normalizeBase64UrlString(request.challenge)
};
if (isCreateRequest(request)) {
var _request$excludeCrede;
return {
...normalized,
user: {
...request.user,
id: normalizeBase64UrlString(request.user.id)
},
excludeCredentials: (_request$excludeCrede = request.excludeCredentials) === null || _request$excludeCrede === void 0 ? void 0 : _request$excludeCrede.map(normalizeCredentialDescriptor),
extensions: normalizeExtensions(request.extensions)
};
}
return {
...normalized,
allowCredentials: (_request$allowCredent = request.allowCredentials) === null || _request$allowCredent === void 0 ? void 0 : _request$allowCredent.map(normalizeCredentialDescriptor),
extensions: normalizeExtensions(request.extensions)
};
}
function isCreateRequest(request) {
return 'user' in request;
}
function normalizeCredentialDescriptor(credential) {
return {
...credential,
id: normalizeBase64UrlString(credential.id)
};
}
function normalizeExtensions(extensions) {
if (!extensions) {
return extensions;
}
return {
...extensions,
largeBlob: extensions.largeBlob ? {
...extensions.largeBlob,
write: extensions.largeBlob.write === undefined ? undefined : binaryInputToBase64Url(extensions.largeBlob.write)
} : undefined,
prf: extensions.prf ? {
...extensions.prf,
eval: normalizePrfValues(extensions.prf.eval),
evalByCredential: normalizeEvalByCredential(extensions.prf.evalByCredential)
} : undefined
};
}
function normalizePrfValues(values) {
if (!values) {
return values;
}
return {
...values,
first: binaryInputToBase64Url(values.first),
second: values.second === undefined ? undefined : binaryInputToBase64Url(values.second)
};
}
function normalizeEvalByCredential(evalByCredential) {
if (!evalByCredential) {
return evalByCredential;
}
if (Array.isArray(evalByCredential)) {
return evalByCredential.map(normalizeEvalByCredentialRecord);
}
return normalizeEvalByCredentialRecord(evalByCredential);
}
function normalizeEvalByCredentialRecord(evalByCredential) {
return Object.fromEntries(Object.entries(evalByCredential).map(([credentialId, values]) => [normalizeBase64UrlString(credentialId), normalizePrfValues(values)]));
}
function binaryInputToBase64Url(value) {
if (typeof value === 'string') {
return normalizeBase64UrlString(value);
}
if (isArrayBuffer(value)) {
return bytesToBase64Url(new Uint8Array(value));
}
if (isArrayBufferView(value)) {
return bytesToBase64Url(new Uint8Array(value.buffer, value.byteOffset, value.byteLength));
}
if (Array.isArray(value)) {
return bytesToBase64Url(value);
}
if (isNumberRecord(value)) {
return bytesToBase64Url(Object.entries(value).sort(([left], [right]) => Number(left) - Number(right)).map(([, byte]) => byte));
}
return bytesToBase64Url(Array.from(value));
}
function normalizeBase64UrlString(value) {
return value.replace(/\+/g, '-').replace(/\//g, '_').replace(/[=]+$/g, '');
}
function bytesToBase64Url(bytes) {
let encoded = '';
for (let index = 0; index < bytes.length; index += 3) {
const first = bytes[index] ?? 0;
const second = bytes[index + 1] ?? 0;
const third = bytes[index + 2] ?? 0;
encoded += base64UrlChars[first >> 2];
encoded += base64UrlChars[(first & 3) << 4 | second >> 4];
if (index + 1 < bytes.length) {
encoded += base64UrlChars[(second & 15) << 2 | third >> 6];
}
if (index + 2 < bytes.length) {
encoded += base64UrlChars[third & 63];
}
}
return encoded;
}
function isArrayBuffer(value) {
return typeof ArrayBuffer !== 'undefined' && value instanceof ArrayBuffer;
}
function isArrayBufferView(value) {
return typeof ArrayBuffer !== 'undefined' && ArrayBuffer.isView(value) && 'buffer' in value && value.buffer instanceof ArrayBuffer;
}
function isNumberRecord(value) {
if (typeof value !== 'object' || value === null || Array.isArray(value)) {
return false;
}
const entries = Object.entries(value);
return entries.length > 0 && entries.every(([key, entryValue]) => /^\d+$/.test(key) && typeof entryValue === 'number');
}
//# sourceMappingURL=PasskeyRequest.js.map