@@ -106,6 +106,9 @@ import {
106106 type BuildWalletLoginRequestParams ,
107107 type VerifyAppProofsParams ,
108108 type PollTransactionStatusParams ,
109+ type OverrideApiKeyStamperParams ,
110+ type OverridePasskeyStamperParams ,
111+ type OverrideWalletManagerParams ,
109112} from "../__types__" ;
110113import {
111114 buildSignUpBody ,
@@ -280,6 +283,104 @@ export class TurnkeyClient {
280283 } ) ;
281284 } ;
282285
286+ /**
287+ * Overrides the API key stamper with a new temporary public key.
288+ *
289+ * - This function sets a temporary public key on the API key stamper or clears it if not provided.
290+ * - Useful for dynamically changing the API key used for signing requests.
291+ *
292+ * @param params.temporaryPublicKey - temporary public key to use for the API key stamper.
293+ * @returns A promise that resolves when the stamper and HTTP client have been updated.
294+ * @throws {TurnkeyError } If there is an error initializing the new stamper.
295+ */
296+ overrideApiKeyStamper = async (
297+ params ?: OverrideApiKeyStamperParams ,
298+ ) : Promise < void > => {
299+ const { temporaryPublicKey } = params || { } ;
300+ // Note: we can expand on this function in the future if we want
301+ return withTurnkeyErrorHandling (
302+ async ( ) => {
303+ if ( temporaryPublicKey ) {
304+ this . apiKeyStamper ?. setTemporaryPublicKey ( temporaryPublicKey ) ;
305+ } else {
306+ this . apiKeyStamper ?. clearTemporaryPublicKey ( ) ;
307+ }
308+ } ,
309+ {
310+ errorMessage : "Failed to override API key stamper" ,
311+ errorCode : TurnkeyErrorCodes . INITIALIZE_API_KEY_STAMPER_ERROR ,
312+ } ,
313+ ) ;
314+ } ;
315+
316+ /**
317+ * Overrides the passkey stamper with a new configuration.
318+ *
319+ * - This function creates a new passkey stamper instance with the provided configuration.
320+ * - Reinitializes the stamper and recreates the HTTP client with the new stamper.
321+ * - Useful for dynamically changing passkey configuration (e.g., allowCredentials, rpId, timeout).
322+ *
323+ * @param params.newConfig - new passkey stamper configuration to use.
324+ * @returns A promise that resolves when the stamper and HTTP client have been updated.
325+ * @throws {TurnkeyError } If there is an error initializing the new stamper.
326+ */
327+ overridePasskeyStamper = async (
328+ params : OverridePasskeyStamperParams ,
329+ ) : Promise < void > => {
330+ const { newConfig } = params ;
331+
332+ return withTurnkeyErrorHandling (
333+ async ( ) => {
334+ // Create a new passkey stamper with the new configuration
335+ const passkeyStamper = new CrossPlatformPasskeyStamper ( newConfig ) ;
336+
337+ // Initialize the new stamper
338+ await passkeyStamper . init ( ) ;
339+
340+ // Set the new stamper
341+ this . passkeyStamper = passkeyStamper ;
342+
343+ // Recreate the HTTP client with the new stamper
344+ this . httpClient = this . createHttpClient ( ) ;
345+ } ,
346+ {
347+ errorMessage : "Failed to override passkey stamper" ,
348+ errorCode : TurnkeyErrorCodes . INITIALIZE_PASSKEY_STAMPER_ERROR ,
349+ } ,
350+ ) ;
351+ } ;
352+
353+ /**
354+ * Overrides the wallet manager with a new configuration.
355+ *
356+ * - This function creates a new wallet manager instance with the provided configuration.
357+ * - Recreates the HTTP client with the new wallet manager's stamper.
358+ * - Useful for dynamically changing wallet configuration (e.g., chains, features, WalletConnect settings).
359+ *
360+ * @param params.newConfig - new wallet manager configuration to use.
361+ * @returns A promise that resolves when the wallet manager and HTTP client have been updated.
362+ * @throws {TurnkeyError } If there is an error creating the new wallet manager.
363+ */
364+ overrideWalletManager = async (
365+ params : OverrideWalletManagerParams ,
366+ ) : Promise < void > => {
367+ const { newConfig } = params ;
368+
369+ return withTurnkeyErrorHandling (
370+ async ( ) => {
371+ // Create a new wallet manager with the new configuration
372+ this . walletManager = await createWalletManager ( newConfig ) ;
373+
374+ // Recreate the HTTP client with the new wallet manager
375+ this . httpClient = this . createHttpClient ( ) ;
376+ } ,
377+ {
378+ errorMessage : "Failed to override wallet manager" ,
379+ errorCode : TurnkeyErrorCodes . INITIALIZE_WALLET_MANAGER_ERROR ,
380+ } ,
381+ ) ;
382+ } ;
383+
283384 /**
284385 * Creates a new passkey authenticator for the user.
285386 *
@@ -421,6 +522,7 @@ export class TurnkeyClient {
421522 * @param params.sessionKey - session key to use for session creation (defaults to the default session key).
422523 * @param params.expirationSeconds - session expiration time in seconds (defaults to the configured default).
423524 * @param params.organizationId - organization ID to target (defaults to the session's organization ID or the parent organization ID).
525+ * @param params.allowCredentials - optional list of allowed credentials for passkey authentication. This allows you to restrict which passkeys can be used for login.
424526 * @returns A promise that resolves to a {@link PasskeyAuthResult}, which includes:
425527 * - `sessionToken`: the signed JWT session token.
426528 * - `credentialId`: an empty string.
@@ -430,6 +532,12 @@ export class TurnkeyClient {
430532 params ?: LoginWithPasskeyParams ,
431533 ) : Promise < PasskeyAuthResult > => {
432534 let generatedPublicKey : string | undefined = undefined ;
535+
536+ const shouldOverrideConfig =
537+ params ?. allowCredentials && this . passkeyStamper ;
538+
539+ const currentConfig = this . config . passkeyConfig ;
540+
433541 return await withTurnkeyErrorHandling (
434542 async ( ) => {
435543 generatedPublicKey =
@@ -445,6 +553,16 @@ export class TurnkeyClient {
445553 TurnkeyErrorCodes . INTERNAL_ERROR ,
446554 ) ;
447555 }
556+
557+ if ( shouldOverrideConfig ) {
558+ // Override passkey stamper config to include allowCredentials
559+ const mergedConfig = {
560+ ...currentConfig ,
561+ allowCredentials : params ?. allowCredentials ! , // Can safely assert non-null due to check above
562+ } ;
563+ await this . overridePasskeyStamper ( { newConfig : mergedConfig } ) ;
564+ }
565+
448566 const sessionResponse = await this . httpClient . stampLogin (
449567 {
450568 publicKey : generatedPublicKey ,
@@ -494,6 +612,13 @@ export class TurnkeyClient {
494612 ) ;
495613 }
496614 }
615+
616+ if ( shouldOverrideConfig ) {
617+ // Restore previous stamper after login attempt
618+ await this . overridePasskeyStamper ( {
619+ newConfig : currentConfig ! , // can safely assert non-null since passkeyStamper exists
620+ } ) ;
621+ }
497622 } ,
498623 } ,
499624 ) ;
0 commit comments