Skip to content

Commit 88f3373

Browse files
authored
Merge pull request #895 from tkhq/moeO/authCallback
auth callback
2 parents 575d62b + 516f47c commit 88f3373

File tree

6 files changed

+148
-80
lines changed

6 files changed

+148
-80
lines changed

packages/core/src/__clients__/core.ts

Lines changed: 48 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ import {
1818
v1HashFunction,
1919
v1Curve,
2020
v1PrivateKey,
21+
OtpAuthResult,
22+
OAuthAuthResult,
23+
WalletAuthResult,
24+
BaseAuthResult,
2125
} from "@turnkey/sdk-types";
2226
import {
2327
DEFAULT_SESSION_EXPIRATION_IN_SECONDS,
@@ -67,6 +71,7 @@ import {
6771
getAuthenticatorAddresses,
6872
getCurveTypeFromProvider,
6973
isValidPasskeyName,
74+
addressFromPublicKey,
7075
} from "@utils";
7176
import { createStorageManager } from "../__storage__/base";
7277
import { CrossPlatformApiKeyStamper } from "../__stampers__/api/base";
@@ -311,7 +316,7 @@ export class TurnkeyClient {
311316
publicKey?: string;
312317
sessionKey?: string;
313318
expirationSeconds?: string;
314-
}): Promise<string> => {
319+
}): Promise<BaseAuthResult> => {
315320
let generatedPublicKey: string | undefined = undefined;
316321
return await withTurnkeyErrorHandling(
317322
async () => {
@@ -344,7 +349,7 @@ export class TurnkeyClient {
344349

345350
generatedPublicKey = undefined; // Key pair was successfully used, set to null to prevent cleanup
346351

347-
return sessionResponse.session;
352+
return { sessionToken: sessionResponse.session };
348353
},
349354
{
350355
errorMessage: "Unable to log in with the provided passkey",
@@ -397,7 +402,7 @@ export class TurnkeyClient {
397402
passkeyDisplayName?: string;
398403
expirationSeconds?: string;
399404
challenge?: string;
400-
}): Promise<string> => {
405+
}): Promise<BaseAuthResult> => {
401406
const {
402407
createSubOrgParams,
403408
passkeyDisplayName,
@@ -474,7 +479,7 @@ export class TurnkeyClient {
474479

475480
generatedPublicKey = undefined; // Key pair was successfully used, set to null to prevent cleanup
476481

477-
return sessionResponse.session;
482+
return { sessionToken: sessionResponse.session };
478483
},
479484
{
480485
errorCode: TurnkeyErrorCodes.PASSKEY_SIGNUP_AUTH_ERROR,
@@ -675,7 +680,7 @@ export class TurnkeyClient {
675680
publicKey?: string;
676681
sessionKey?: string;
677682
expirationSeconds?: string;
678-
}): Promise<string> => {
683+
}): Promise<WalletAuthResult> => {
679684
let publicKey =
680685
params.publicKey || (await this.apiKeyStamper?.createKeyPair());
681686
return withTurnkeyErrorHandling(
@@ -718,7 +723,15 @@ export class TurnkeyClient {
718723
sessionKey,
719724
});
720725

721-
return sessionResponse.session;
726+
// TODO (Moe): What happens if a user connects to MetaMask on Ethereum,
727+
// then switches to a Solana account within MetaMask? Will this flow break?
728+
return {
729+
sessionToken: sessionResponse.session,
730+
address: addressFromPublicKey(
731+
walletProvider.chainInfo.namespace,
732+
publicKey,
733+
),
734+
};
722735
},
723736
{
724737
errorMessage: "Unable to log in with the provided wallet",
@@ -765,7 +778,7 @@ export class TurnkeyClient {
765778
createSubOrgParams?: CreateSubOrgParams;
766779
sessionKey?: string;
767780
expirationSeconds?: string;
768-
}): Promise<string> => {
781+
}): Promise<WalletAuthResult> => {
769782
const {
770783
walletProvider,
771784
createSubOrgParams,
@@ -848,7 +861,15 @@ export class TurnkeyClient {
848861

849862
generatedPublicKey = undefined; // Key pair was successfully used, set to null to prevent cleanup
850863

851-
return sessionResponse.session;
864+
// TODO (Moe): What happens if a user connects to MetaMask on Ethereum,
865+
// then switches to a Solana account within MetaMask? Will this flow break?
866+
return {
867+
sessionToken: sessionResponse.session,
868+
address: addressFromPublicKey(
869+
walletProvider.chainInfo.namespace,
870+
publicKey,
871+
),
872+
};
852873
},
853874
{
854875
errorMessage: "Failed to sign up with wallet",
@@ -896,7 +917,7 @@ export class TurnkeyClient {
896917
createSubOrgParams?: CreateSubOrgParams;
897918
sessionKey?: string;
898919
expirationSeconds?: string;
899-
}): Promise<string> => {
920+
}): Promise<WalletAuthResult> => {
900921
const createSubOrgParams = params.createSubOrgParams;
901922
const sessionKey = params.sessionKey || SessionKey.DefaultSessionkey;
902923
const walletProvider = params.walletProvider;
@@ -1063,7 +1084,13 @@ export class TurnkeyClient {
10631084
sessionKey,
10641085
});
10651086

1066-
return sessionToken;
1087+
return {
1088+
sessionToken: sessionToken,
1089+
address: addressFromPublicKey(
1090+
walletProvider.chainInfo.namespace,
1091+
publicKey,
1092+
),
1093+
};
10671094
},
10681095
{
10691096
errorCode: TurnkeyErrorCodes.WALLET_LOGIN_OR_SIGNUP_ERROR,
@@ -1218,7 +1245,7 @@ export class TurnkeyClient {
12181245
publicKey?: string;
12191246
invalidateExisting?: boolean;
12201247
sessionKey?: string;
1221-
}): Promise<string> => {
1248+
}): Promise<OtpAuthResult> => {
12221249
const {
12231250
verificationToken,
12241251
invalidateExisting = false,
@@ -1254,7 +1281,10 @@ export class TurnkeyClient {
12541281
sessionKey,
12551282
});
12561283

1257-
return loginRes.session;
1284+
return {
1285+
sessionToken: loginRes.session,
1286+
verificationToken,
1287+
};
12581288
},
12591289
{
12601290
errorMessage: "Failed to log in with OTP",
@@ -1302,7 +1332,7 @@ export class TurnkeyClient {
13021332
createSubOrgParams?: CreateSubOrgParams;
13031333
invalidateExisting?: boolean;
13041334
sessionKey?: string;
1305-
}): Promise<string> => {
1335+
}): Promise<OtpAuthResult> => {
13061336
const {
13071337
verificationToken,
13081338
contact,
@@ -1377,7 +1407,7 @@ export class TurnkeyClient {
13771407
invalidateExisting?: boolean;
13781408
sessionKey?: string;
13791409
createSubOrgParams?: CreateSubOrgParams;
1380-
}): Promise<string> => {
1410+
}): Promise<OtpAuthResult> => {
13811411
const {
13821412
otpId,
13831413
otpCode,
@@ -1457,7 +1487,7 @@ export class TurnkeyClient {
14571487
sessionKey?: string;
14581488
invalidateExisting?: boolean;
14591489
createSubOrgParams?: CreateSubOrgParams;
1460-
}): Promise<string> => {
1490+
}): Promise<OAuthAuthResult> => {
14611491
const {
14621492
oidcToken,
14631493
publicKey,
@@ -1527,7 +1557,7 @@ export class TurnkeyClient {
15271557
publicKey: string;
15281558
invalidateExisting?: boolean;
15291559
sessionKey?: string;
1530-
}): Promise<string> => {
1560+
}): Promise<OAuthAuthResult> => {
15311561
const {
15321562
oidcToken,
15331563
invalidateExisting = false,
@@ -1569,7 +1599,7 @@ export class TurnkeyClient {
15691599
sessionKey,
15701600
});
15711601

1572-
return loginRes.session;
1602+
return { sessionToken: loginRes.session, oidcToken };
15731603
},
15741604
{
15751605
errorMessage: "Failed to complete OAuth login",
@@ -1621,7 +1651,7 @@ export class TurnkeyClient {
16211651
providerName: string;
16221652
createSubOrgParams?: CreateSubOrgParams;
16231653
sessionKey?: string;
1624-
}): Promise<string> => {
1654+
}): Promise<OAuthAuthResult> => {
16251655
const { oidcToken, publicKey, providerName, createSubOrgParams } = params;
16261656

16271657
return withTurnkeyErrorHandling(

packages/core/src/utils.ts

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -810,22 +810,36 @@ export function findWalletProviderFromAddress(
810810
return undefined;
811811
}
812812

813-
/**@internal */
814-
export function ethereumAddressFromCompressedPublicKey(publicKey: string) {
815-
const compressedBytes = uint8ArrayFromHexString(publicKey);
813+
/**
814+
* Derives a wallet address from a given public key and chain.
815+
*
816+
* @param chain - "ethereum" or "solana"
817+
* @param publicKey - The raw public key string
818+
* @returns The derived wallet address
819+
*/
820+
export function addressFromPublicKey(chain: Chain, publicKey: string): string {
821+
if (chain === Chain.Ethereum) {
822+
const compressedBytes = uint8ArrayFromHexString(publicKey);
816823

817-
const publicKeyUncompressed = uint8ArrayToHexString(
818-
uncompressRawPublicKey(compressedBytes, Curve.SECP256K1),
819-
);
824+
const publicKeyUncompressed = uint8ArrayToHexString(
825+
uncompressRawPublicKey(compressedBytes, Curve.SECP256K1),
826+
);
827+
828+
// drop 04 prefix
829+
const key = publicKeyUncompressed.startsWith("04")
830+
? publicKeyUncompressed.slice(2)
831+
: publicKeyUncompressed;
820832

821-
// drop 04 prefix
822-
const key = publicKeyUncompressed.startsWith("04")
823-
? publicKeyUncompressed.slice(2)
824-
: publicKeyUncompressed;
833+
// hash with Keccak256 and take last 20 bytes
834+
const hash = keccak256(uint8ArrayFromHexString(key));
835+
return "0x" + hash.slice(-40);
836+
}
837+
838+
if (chain === Chain.Solana) {
839+
return bs58.encode(uint8ArrayFromHexString(publicKey));
840+
}
825841

826-
// hash with Keccak256 and take last 20 bytes
827-
const hash = keccak256(uint8ArrayFromHexString(key));
828-
return "0x" + hash.slice(-40);
842+
throw new Error(`Unsupported chain: ${chain}`);
829843
}
830844

831845
/**@internal */
@@ -837,10 +851,10 @@ export function getAuthenticatorAddresses(user: v1User) {
837851
const { type, publicKey } = key.credential;
838852
switch (type) {
839853
case "CREDENTIAL_TYPE_API_KEY_SECP256K1":
840-
ethereum.push(ethereumAddressFromCompressedPublicKey(publicKey));
854+
ethereum.push(addressFromPublicKey(Chain.Ethereum, publicKey));
841855
break;
842856
case "CREDENTIAL_TYPE_API_KEY_ED25519":
843-
solana.push(bs58.encode(uint8ArrayFromHexString(publicKey)));
857+
solana.push(addressFromPublicKey(Chain.Solana, publicKey));
844858
break;
845859
}
846860
}

0 commit comments

Comments
 (0)