UNPKG

rn-passkeys

Version:

A library for using (webauthn) passkeys on iOS, Android & web with a single api

100 lines 4.51 kB
import { NotSupportedError } from './errors'; import { base64URLStringToBuffer, bufferToBase64URLString } from './utils/base64'; export default { get name() { return 'ReactNativePasskeys'; }, isAutoFillAvalilable() { const globalPublicKeyCredential = window.PublicKeyCredential; if (globalPublicKeyCredential.isConditionalMediationAvailable === undefined) return new Promise((resolve) => resolve(false)); return globalPublicKeyCredential.isConditionalMediationAvailable(); }, isSupported() { return (window?.PublicKeyCredential !== undefined && typeof window.PublicKeyCredential === 'function'); }, async create({ signal, ...request }) { if (!this.isSupported) throw new NotSupportedError(); const credential = (await navigator.credentials.create({ signal, publicKey: { ...request, challenge: base64URLStringToBuffer(request.challenge), user: { ...request.user, id: base64URLStringToBuffer(request.user.id) }, excludeCredentials: request.excludeCredentials?.map((credential) => ({ ...credential, id: base64URLStringToBuffer(credential.id), // TODO: remove the override when typescript has updated webauthn types transports: (credential.transports ?? undefined), })), }, })); // TODO: remove the override when typescript has updated webauthn types const clientExtensionResults = credential?.getClientExtensionResults(); warnUserOfMissingWebauthnExtensions(request.extensions, clientExtensionResults); if (!credential) return null; return { id: credential?.id, rawId: credential.id, response: { clientDataJSON: bufferToBase64URLString(credential.response.clientDataJSON), attestationObject: bufferToBase64URLString(credential.response.attestationObject), }, authenticatorAttachment: undefined, type: 'public-key', clientExtensionResults, }; }, async get({ mediation, signal, ...request }) { const credential = (await navigator.credentials.get({ mediation, signal, publicKey: { ...request, challenge: base64URLStringToBuffer(request.challenge), allowCredentials: request.allowCredentials?.map((credential) => ({ ...credential, id: base64URLStringToBuffer(credential.id), // TODO: remove the override when typescript has updated webauthn types transports: (credential.transports ?? undefined), })), }, })); // TODO: remove the override when typescript has updated webauthn types const clientExtensionResults = credential?.getClientExtensionResults(); warnUserOfMissingWebauthnExtensions(request.extensions, clientExtensionResults); if (!credential) return null; return { id: credential.id, rawId: credential.id, response: { clientDataJSON: bufferToBase64URLString(credential.response.clientDataJSON), authenticatorData: bufferToBase64URLString(credential.response.authenticatorData), signature: bufferToBase64URLString(credential.response.signature), userHandle: credential.response.userHandle ? bufferToBase64URLString(credential.response.userHandle) : undefined, }, authenticatorAttachment: undefined, clientExtensionResults, type: 'public-key', }; }, }; /** * warn the user about extensions that they tried to use that are not supported */ const warnUserOfMissingWebauthnExtensions = (requestedExtensions, clientExtensionResults) => { if (clientExtensionResults) { for (const key in requestedExtensions) { console.log(key, clientExtensionResults[key]); if (typeof clientExtensionResults[key] === 'undefined') { alert(`Webauthn extension ${key} is undefined -- your browser probably doesn't know about it`); } } } }; //# sourceMappingURL=ReactNativePasskeysModule.web.js.map