@turnkey/core
Version:
A core JavaScript web and React Native package for interfacing with Turnkey's infrastructure.
101 lines (98 loc) • 4.47 kB
JavaScript
import { isWeb, isReactNative } from '../../utils.mjs';
import { IndexedDbStamper } from './web/stamper.mjs';
import { TurnkeyError, TurnkeyErrorCodes } from '@turnkey/sdk-types';
import { SignatureFormat } from '@turnkey/api-key-stamper';
/**
* Cross-platform API key stamper.
*
* - This stamper uses indexedDB on web and keychain on react-native to securely stamp Turnkey requests.
* - ***Only supports P-256 ECDSA key pairs.***
*/
class CrossPlatformApiKeyStamper {
constructor(storageManager) {
this.storageManager = storageManager;
// Use init method to set up the stamper based on the platform. It's async, so can't be done in the constructor.
}
async init() {
if (isWeb()) {
this.stamper = new IndexedDbStamper();
}
else if (isReactNative()) {
try {
// Dynamic import to prevent bundling the native module in web environments.
const { ReactNativeKeychainStamper } = await import('./mobile/stamper.mjs');
this.stamper = new ReactNativeKeychainStamper();
}
catch (error) {
throw new TurnkeyError(`Failed to load keychain stamper for react-native`, TurnkeyErrorCodes.INITIALIZE_CLIENT_ERROR, error);
}
}
else {
throw new TurnkeyError("Unsupported platform for API key stamper", TurnkeyErrorCodes.UNSUPPORTED_PLATFORM);
}
}
listKeyPairs() {
if (!this.stamper) {
throw new TurnkeyError("Stamper is not initialized. Please call .init() before calling this method.", TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
}
return this.stamper.listKeyPairs();
}
createKeyPair(externalKeyPair) {
if (!this.stamper) {
throw new TurnkeyError("Stamper is not initialized. Please call .init() before calling this method.", TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
}
return this.stamper.createKeyPair(externalKeyPair);
}
deleteKeyPair(publicKeyHex) {
if (!this.stamper) {
throw new TurnkeyError("Stamper is not initialized. Please call .init() before calling this method.", TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
}
// If the deleted key pair is the temporary one, clear it.
if (this.temporaryPublicKey === publicKeyHex) {
this.temporaryPublicKey = undefined;
}
return this.stamper.deleteKeyPair(publicKeyHex);
}
// This allows forcing a specific public key to find the key pair for stamping. The key pair must already exist in indexedDB / Keychain.
// This is useful if you need to stamp with a specific key pair without having an active session.
// See "signUpWithPasskey" function in core.ts for usage
setTemporaryPublicKey(publicKeyHex) {
this.temporaryPublicKey = publicKeyHex;
}
getTemporaryPublicKey() {
return this.temporaryPublicKey;
}
clearTemporaryPublicKey() {
this.temporaryPublicKey = undefined;
}
async stamp(payload) {
if (!this.stamper) {
throw new TurnkeyError("Stamper is not initialized. Please call .init() before calling this method.", TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
}
let publicKeyHex = this.temporaryPublicKey;
if (!publicKeyHex) {
const session = await this.storageManager.getActiveSession();
if (!session) {
throw new TurnkeyError("No active session or token available.", TurnkeyErrorCodes.NO_SESSION_FOUND);
}
publicKeyHex = session.publicKey;
}
return this.stamper.stamp(payload, publicKeyHex);
}
async sign(payload, format = SignatureFormat.Der) {
if (!this.stamper) {
throw new TurnkeyError("Stamper is not initialized. Please call .init() before calling this method.", TurnkeyErrorCodes.CLIENT_NOT_INITIALIZED);
}
let publicKeyHex = this.temporaryPublicKey;
if (!publicKeyHex) {
const session = await this.storageManager.getActiveSession();
if (!session) {
throw new TurnkeyError("No active session or token available.", TurnkeyErrorCodes.NO_SESSION_FOUND);
}
publicKeyHex = session.publicKey;
}
return this.stamper.sign(payload, publicKeyHex, format);
}
}
export { CrossPlatformApiKeyStamper };
//# sourceMappingURL=base.mjs.map