@phantom/embedded-provider-core 1.0.0-beta.10 → 1.0.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +8 -5
- package/dist/index.d.ts +8 -5
- package/dist/index.js +113 -62
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +113 -62
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -29,7 +29,7 @@ interface Session {
|
|
|
29
29
|
authenticatorCreatedAt: number;
|
|
30
30
|
authenticatorExpiresAt: number;
|
|
31
31
|
lastRenewalAttempt?: number;
|
|
32
|
-
username
|
|
32
|
+
username?: string;
|
|
33
33
|
accountDerivationIndex?: number;
|
|
34
34
|
}
|
|
35
35
|
interface EmbeddedStorage {
|
|
@@ -60,12 +60,14 @@ interface URLParamsAccessor {
|
|
|
60
60
|
|
|
61
61
|
interface AuthResult {
|
|
62
62
|
walletId: string;
|
|
63
|
+
organizationId: string;
|
|
63
64
|
provider?: string;
|
|
64
65
|
userInfo?: Record<string, any>;
|
|
65
|
-
accountDerivationIndex
|
|
66
|
+
accountDerivationIndex: number;
|
|
67
|
+
expiresInMs: number;
|
|
66
68
|
}
|
|
67
69
|
interface PhantomConnectOptions {
|
|
68
|
-
|
|
70
|
+
publicKey: string;
|
|
69
71
|
appId: string;
|
|
70
72
|
provider?: "google" | "apple";
|
|
71
73
|
redirectUrl?: string;
|
|
@@ -75,7 +77,7 @@ interface PhantomConnectOptions {
|
|
|
75
77
|
}
|
|
76
78
|
interface JWTAuthOptions {
|
|
77
79
|
appId: string;
|
|
78
|
-
|
|
80
|
+
publicKey: string;
|
|
79
81
|
jwtToken: string;
|
|
80
82
|
customAuthData?: Record<string, any>;
|
|
81
83
|
}
|
|
@@ -171,7 +173,8 @@ declare class EmbeddedProvider {
|
|
|
171
173
|
private validateAuthOptions;
|
|
172
174
|
private isSessionValid;
|
|
173
175
|
autoConnect(): Promise<void>;
|
|
174
|
-
private
|
|
176
|
+
private initializeStamper;
|
|
177
|
+
private createOrganizationForAppWallet;
|
|
175
178
|
connect(authOptions?: AuthOptions): Promise<ConnectResult>;
|
|
176
179
|
disconnect(): Promise<void>;
|
|
177
180
|
signMessage(params: SignMessageParams): Promise<ParsedSignatureResult>;
|
package/dist/index.d.ts
CHANGED
|
@@ -29,7 +29,7 @@ interface Session {
|
|
|
29
29
|
authenticatorCreatedAt: number;
|
|
30
30
|
authenticatorExpiresAt: number;
|
|
31
31
|
lastRenewalAttempt?: number;
|
|
32
|
-
username
|
|
32
|
+
username?: string;
|
|
33
33
|
accountDerivationIndex?: number;
|
|
34
34
|
}
|
|
35
35
|
interface EmbeddedStorage {
|
|
@@ -60,12 +60,14 @@ interface URLParamsAccessor {
|
|
|
60
60
|
|
|
61
61
|
interface AuthResult {
|
|
62
62
|
walletId: string;
|
|
63
|
+
organizationId: string;
|
|
63
64
|
provider?: string;
|
|
64
65
|
userInfo?: Record<string, any>;
|
|
65
|
-
accountDerivationIndex
|
|
66
|
+
accountDerivationIndex: number;
|
|
67
|
+
expiresInMs: number;
|
|
66
68
|
}
|
|
67
69
|
interface PhantomConnectOptions {
|
|
68
|
-
|
|
70
|
+
publicKey: string;
|
|
69
71
|
appId: string;
|
|
70
72
|
provider?: "google" | "apple";
|
|
71
73
|
redirectUrl?: string;
|
|
@@ -75,7 +77,7 @@ interface PhantomConnectOptions {
|
|
|
75
77
|
}
|
|
76
78
|
interface JWTAuthOptions {
|
|
77
79
|
appId: string;
|
|
78
|
-
|
|
80
|
+
publicKey: string;
|
|
79
81
|
jwtToken: string;
|
|
80
82
|
customAuthData?: Record<string, any>;
|
|
81
83
|
}
|
|
@@ -171,7 +173,8 @@ declare class EmbeddedProvider {
|
|
|
171
173
|
private validateAuthOptions;
|
|
172
174
|
private isSessionValid;
|
|
173
175
|
autoConnect(): Promise<void>;
|
|
174
|
-
private
|
|
176
|
+
private initializeStamper;
|
|
177
|
+
private createOrganizationForAppWallet;
|
|
175
178
|
connect(authOptions?: AuthOptions): Promise<ConnectResult>;
|
|
176
179
|
disconnect(): Promise<void>;
|
|
177
180
|
signMessage(params: SignMessageParams): Promise<ParsedSignatureResult>;
|
package/dist/index.js
CHANGED
|
@@ -72,6 +72,7 @@ var JWTAuth = class {
|
|
|
72
72
|
},
|
|
73
73
|
body: JSON.stringify({
|
|
74
74
|
appId: options.appId,
|
|
75
|
+
publicKey: options.publicKey,
|
|
75
76
|
customAuthData: options.customAuthData
|
|
76
77
|
})
|
|
77
78
|
});
|
|
@@ -112,10 +113,19 @@ var JWTAuth = class {
|
|
|
112
113
|
if (!result.walletId) {
|
|
113
114
|
throw new Error("Invalid JWT authentication response: missing walletId");
|
|
114
115
|
}
|
|
116
|
+
if (!result.organizationId) {
|
|
117
|
+
throw new Error("Invalid JWT authentication response: missing organizationId");
|
|
118
|
+
}
|
|
119
|
+
if (!result.expiresInMs) {
|
|
120
|
+
throw new Error("Invalid JWT authentication response: missing expiresInMs");
|
|
121
|
+
}
|
|
115
122
|
return {
|
|
116
123
|
walletId: result.walletId,
|
|
124
|
+
organizationId: result.organizationId,
|
|
117
125
|
provider: "jwt",
|
|
118
|
-
userInfo: result.userInfo || {}
|
|
126
|
+
userInfo: result.userInfo || {},
|
|
127
|
+
expiresInMs: result.expiresInMs,
|
|
128
|
+
accountDerivationIndex: result.accountDerivationIndex || 0
|
|
119
129
|
};
|
|
120
130
|
} catch (error) {
|
|
121
131
|
if (error instanceof TypeError && error.message.includes("fetch")) {
|
|
@@ -794,34 +804,39 @@ var EmbeddedProvider = class {
|
|
|
794
804
|
* We use this method to initialize the stamper and create an organization for new sessions.
|
|
795
805
|
* This is the first step when no existing session is found and we need to set up a new wallet.
|
|
796
806
|
*/
|
|
797
|
-
async
|
|
807
|
+
async initializeStamper() {
|
|
798
808
|
this.logger.log("EMBEDDED_PROVIDER", "Initializing stamper");
|
|
799
|
-
|
|
800
|
-
this.logger.log("EMBEDDED_PROVIDER", "
|
|
809
|
+
await this.stamper.init();
|
|
810
|
+
this.logger.log("EMBEDDED_PROVIDER", "Resetting keypair to avoid conflicts with existing keypairs");
|
|
811
|
+
const stamperInfo = await this.stamper.resetKeyPair();
|
|
812
|
+
this.logger.log("EMBEDDED_PROVIDER", "Stamper initialized with fresh keypair", {
|
|
801
813
|
publicKey: stamperInfo.publicKey,
|
|
802
814
|
keyId: stamperInfo.keyId,
|
|
803
815
|
algorithm: this.stamper.algorithm
|
|
804
816
|
});
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
817
|
+
const expiresInMs = AUTHENTICATOR_EXPIRATION_TIME_MS;
|
|
818
|
+
this.logger.info("EMBEDDED_PROVIDER", "Stamper ready for auth flow with fresh keypair", {
|
|
819
|
+
publicKey: stamperInfo.publicKey,
|
|
820
|
+
keyId: stamperInfo.keyId
|
|
821
|
+
});
|
|
822
|
+
return { stamperInfo, expiresInMs };
|
|
823
|
+
}
|
|
824
|
+
async createOrganizationForAppWallet(stamperInfo, expiresInMs) {
|
|
825
|
+
const tempClient = new import_client.PhantomClient({
|
|
826
|
+
apiBaseUrl: this.config.apiBaseUrl,
|
|
827
|
+
headers: {
|
|
828
|
+
...this.platform.analyticsHeaders || {}
|
|
829
|
+
}
|
|
830
|
+
});
|
|
815
831
|
const platformName = this.platform.name || "unknown";
|
|
816
832
|
const shortPubKey = stamperInfo.publicKey.slice(0, 8);
|
|
817
833
|
const organizationName = `${this.config.appId.substring(0, 8)}-${platformName}-${shortPubKey}`;
|
|
818
|
-
this.logger.log("EMBEDDED_PROVIDER", "Creating organization", {
|
|
834
|
+
this.logger.log("EMBEDDED_PROVIDER", "Creating organization for app-wallet", {
|
|
819
835
|
organizationName,
|
|
820
836
|
publicKey: stamperInfo.publicKey,
|
|
821
837
|
platform: platformName
|
|
822
838
|
});
|
|
823
839
|
const base64urlPublicKey = (0, import_base64url2.base64urlEncode)(import_bs582.default.decode(stamperInfo.publicKey));
|
|
824
|
-
const expiresInMs = AUTHENTICATOR_EXPIRATION_TIME_MS;
|
|
825
840
|
const username = `user-${(0, import_utils.randomUUID)()}`;
|
|
826
841
|
const { organizationId } = await tempClient.createOrganization(organizationName, [
|
|
827
842
|
{
|
|
@@ -832,15 +847,14 @@ var EmbeddedProvider = class {
|
|
|
832
847
|
authenticatorName: `auth-${shortPubKey}`,
|
|
833
848
|
authenticatorKind: "keypair",
|
|
834
849
|
publicKey: base64urlPublicKey,
|
|
835
|
-
algorithm: "Ed25519"
|
|
836
|
-
|
|
837
|
-
// expiresInMs: expiresInMs,
|
|
850
|
+
algorithm: "Ed25519",
|
|
851
|
+
expiresInMs
|
|
838
852
|
}
|
|
839
853
|
]
|
|
840
854
|
}
|
|
841
855
|
]);
|
|
842
|
-
this.logger.info("EMBEDDED_PROVIDER", "Organization created", { organizationId });
|
|
843
|
-
return
|
|
856
|
+
this.logger.info("EMBEDDED_PROVIDER", "Organization created for app-wallet", { organizationId });
|
|
857
|
+
return organizationId;
|
|
844
858
|
}
|
|
845
859
|
async connect(authOptions) {
|
|
846
860
|
try {
|
|
@@ -869,8 +883,8 @@ var EmbeddedProvider = class {
|
|
|
869
883
|
}
|
|
870
884
|
this.validateAuthOptions(authOptions);
|
|
871
885
|
this.logger.info("EMBEDDED_PROVIDER", "No existing connection, creating new auth flow");
|
|
872
|
-
const {
|
|
873
|
-
const session = await this.handleAuthFlow(
|
|
886
|
+
const { stamperInfo, expiresInMs } = await this.initializeStamper();
|
|
887
|
+
const session = await this.handleAuthFlow(stamperInfo.publicKey, stamperInfo, authOptions, expiresInMs);
|
|
874
888
|
if (!session) {
|
|
875
889
|
return {
|
|
876
890
|
addresses: [],
|
|
@@ -1042,24 +1056,25 @@ var EmbeddedProvider = class {
|
|
|
1042
1056
|
* It handles app-wallet creation directly or routes to JWT/redirect authentication for user-wallets.
|
|
1043
1057
|
* Returns null for redirect flows since they don't complete synchronously.
|
|
1044
1058
|
*/
|
|
1045
|
-
async handleAuthFlow(
|
|
1059
|
+
async handleAuthFlow(publicKey, stamperInfo, authOptions, expiresInMs) {
|
|
1046
1060
|
if (this.config.embeddedWalletType === "user-wallet") {
|
|
1047
1061
|
this.logger.info("EMBEDDED_PROVIDER", "Creating user-wallet, routing authentication", {
|
|
1048
1062
|
authProvider: authOptions?.provider || "phantom-connect"
|
|
1049
1063
|
});
|
|
1050
1064
|
if (authOptions?.provider === "jwt") {
|
|
1051
|
-
return await this.handleJWTAuth(
|
|
1065
|
+
return await this.handleJWTAuth(publicKey, stamperInfo, authOptions, expiresInMs);
|
|
1052
1066
|
} else {
|
|
1053
1067
|
this.logger.info("EMBEDDED_PROVIDER", "Starting redirect-based authentication flow", {
|
|
1054
|
-
|
|
1068
|
+
publicKey,
|
|
1055
1069
|
provider: authOptions?.provider
|
|
1056
1070
|
});
|
|
1057
|
-
return await this.handleRedirectAuth(
|
|
1071
|
+
return await this.handleRedirectAuth(publicKey, stamperInfo, authOptions);
|
|
1058
1072
|
}
|
|
1059
1073
|
} else {
|
|
1060
1074
|
this.logger.info("EMBEDDED_PROVIDER", "Creating app-wallet", {
|
|
1061
|
-
|
|
1075
|
+
publicKey
|
|
1062
1076
|
});
|
|
1077
|
+
const organizationId = await this.createOrganizationForAppWallet(stamperInfo, expiresInMs);
|
|
1063
1078
|
const tempClient = new import_client.PhantomClient(
|
|
1064
1079
|
{
|
|
1065
1080
|
apiBaseUrl: this.config.apiBaseUrl,
|
|
@@ -1088,8 +1103,7 @@ var EmbeddedProvider = class {
|
|
|
1088
1103
|
lastUsed: now,
|
|
1089
1104
|
authenticatorCreatedAt: now,
|
|
1090
1105
|
authenticatorExpiresAt: Date.now() + expiresInMs,
|
|
1091
|
-
lastRenewalAttempt: void 0
|
|
1092
|
-
username
|
|
1106
|
+
lastRenewalAttempt: void 0
|
|
1093
1107
|
};
|
|
1094
1108
|
await this.storage.saveSession(session);
|
|
1095
1109
|
this.logger.info("EMBEDDED_PROVIDER", "App-wallet created successfully", { walletId, organizationId });
|
|
@@ -1100,7 +1114,7 @@ var EmbeddedProvider = class {
|
|
|
1100
1114
|
* We use this method to handle JWT-based authentication for user-wallets.
|
|
1101
1115
|
* It authenticates using the provided JWT token and creates a completed session.
|
|
1102
1116
|
*/
|
|
1103
|
-
async handleJWTAuth(
|
|
1117
|
+
async handleJWTAuth(publicKey, stamperInfo, authOptions, localExpiresInMs) {
|
|
1104
1118
|
this.logger.info("EMBEDDED_PROVIDER", "Using JWT authentication flow");
|
|
1105
1119
|
if (!authOptions.jwtToken) {
|
|
1106
1120
|
this.logger.error("EMBEDDED_PROVIDER", "JWT token missing for JWT authentication");
|
|
@@ -1108,13 +1122,20 @@ var EmbeddedProvider = class {
|
|
|
1108
1122
|
}
|
|
1109
1123
|
this.logger.log("EMBEDDED_PROVIDER", "Starting JWT authentication");
|
|
1110
1124
|
const authResult = await this.jwtAuth.authenticate({
|
|
1111
|
-
|
|
1125
|
+
publicKey,
|
|
1112
1126
|
appId: this.config.appId,
|
|
1113
1127
|
jwtToken: authOptions.jwtToken,
|
|
1114
1128
|
customAuthData: authOptions.customAuthData
|
|
1115
1129
|
});
|
|
1116
1130
|
const walletId = authResult.walletId;
|
|
1117
|
-
|
|
1131
|
+
const organizationId = authResult.organizationId;
|
|
1132
|
+
const expiresInMs = authResult.expiresInMs > 0 ? authResult.expiresInMs : localExpiresInMs;
|
|
1133
|
+
this.logger.info("EMBEDDED_PROVIDER", "JWT authentication completed", {
|
|
1134
|
+
walletId,
|
|
1135
|
+
organizationId,
|
|
1136
|
+
expiresInMs,
|
|
1137
|
+
source: authResult.expiresInMs ? "server" : "local"
|
|
1138
|
+
});
|
|
1118
1139
|
const now = Date.now();
|
|
1119
1140
|
const session = {
|
|
1120
1141
|
sessionId: generateSessionId(),
|
|
@@ -1130,8 +1151,7 @@ var EmbeddedProvider = class {
|
|
|
1130
1151
|
lastUsed: now,
|
|
1131
1152
|
authenticatorCreatedAt: now,
|
|
1132
1153
|
authenticatorExpiresAt: Date.now() + expiresInMs,
|
|
1133
|
-
lastRenewalAttempt: void 0
|
|
1134
|
-
username
|
|
1154
|
+
lastRenewalAttempt: void 0
|
|
1135
1155
|
};
|
|
1136
1156
|
this.logger.log("EMBEDDED_PROVIDER", "Saving JWT session");
|
|
1137
1157
|
await this.storage.saveSession(session);
|
|
@@ -1142,7 +1162,7 @@ var EmbeddedProvider = class {
|
|
|
1142
1162
|
* It saves a temporary session before redirecting to prevent losing state during the redirect flow.
|
|
1143
1163
|
* Session timestamp is updated before redirect to prevent race conditions.
|
|
1144
1164
|
*/
|
|
1145
|
-
async handleRedirectAuth(
|
|
1165
|
+
async handleRedirectAuth(publicKey, stamperInfo, authOptions) {
|
|
1146
1166
|
this.logger.info("EMBEDDED_PROVIDER", "Using Phantom Connect authentication flow (redirect-based)", {
|
|
1147
1167
|
provider: authOptions?.provider,
|
|
1148
1168
|
hasRedirectUrl: !!this.config.authOptions.redirectUrl,
|
|
@@ -1152,9 +1172,10 @@ var EmbeddedProvider = class {
|
|
|
1152
1172
|
const sessionId = generateSessionId();
|
|
1153
1173
|
const tempSession = {
|
|
1154
1174
|
sessionId,
|
|
1155
|
-
walletId: `temp-${now}`,
|
|
1175
|
+
walletId: `temp-wallet-${now}`,
|
|
1176
|
+
// Temporary ID, will be updated after redirect
|
|
1177
|
+
organizationId: `temp-org-${now}`,
|
|
1156
1178
|
// Temporary ID, will be updated after redirect
|
|
1157
|
-
organizationId,
|
|
1158
1179
|
appId: this.config.appId,
|
|
1159
1180
|
stamperInfo,
|
|
1160
1181
|
authProvider: "phantom-connect",
|
|
@@ -1166,8 +1187,7 @@ var EmbeddedProvider = class {
|
|
|
1166
1187
|
lastUsed: now,
|
|
1167
1188
|
authenticatorCreatedAt: now,
|
|
1168
1189
|
authenticatorExpiresAt: now + AUTHENTICATOR_EXPIRATION_TIME_MS,
|
|
1169
|
-
lastRenewalAttempt: void 0
|
|
1170
|
-
username: username || `user-${(0, import_utils.randomUUID)()}`
|
|
1190
|
+
lastRenewalAttempt: void 0
|
|
1171
1191
|
};
|
|
1172
1192
|
this.logger.log("EMBEDDED_PROVIDER", "Saving temporary session before redirect", {
|
|
1173
1193
|
sessionId: tempSession.sessionId,
|
|
@@ -1176,13 +1196,13 @@ var EmbeddedProvider = class {
|
|
|
1176
1196
|
tempSession.lastUsed = Date.now();
|
|
1177
1197
|
await this.storage.saveSession(tempSession);
|
|
1178
1198
|
this.logger.info("EMBEDDED_PROVIDER", "Starting Phantom Connect redirect", {
|
|
1179
|
-
|
|
1199
|
+
publicKey,
|
|
1180
1200
|
appId: this.config.appId,
|
|
1181
1201
|
provider: authOptions?.provider,
|
|
1182
1202
|
authUrl: this.config.authOptions.authUrl
|
|
1183
1203
|
});
|
|
1184
1204
|
const authResult = await this.authProvider.authenticate({
|
|
1185
|
-
|
|
1205
|
+
publicKey,
|
|
1186
1206
|
appId: this.config.appId,
|
|
1187
1207
|
provider: authOptions?.provider,
|
|
1188
1208
|
redirectUrl: this.config.authOptions.redirectUrl,
|
|
@@ -1193,13 +1213,24 @@ var EmbeddedProvider = class {
|
|
|
1193
1213
|
if (authResult && "walletId" in authResult) {
|
|
1194
1214
|
this.logger.info("EMBEDDED_PROVIDER", "Authentication completed after redirect", {
|
|
1195
1215
|
walletId: authResult.walletId,
|
|
1216
|
+
organizationId: authResult.organizationId,
|
|
1196
1217
|
provider: authResult.provider
|
|
1197
1218
|
});
|
|
1198
1219
|
tempSession.walletId = authResult.walletId;
|
|
1220
|
+
tempSession.organizationId = authResult.organizationId;
|
|
1199
1221
|
tempSession.authProvider = authResult.provider || tempSession.authProvider;
|
|
1200
1222
|
tempSession.accountDerivationIndex = authResult.accountDerivationIndex;
|
|
1201
1223
|
tempSession.status = "completed";
|
|
1202
1224
|
tempSession.lastUsed = Date.now();
|
|
1225
|
+
if (authResult.expiresInMs > 0) {
|
|
1226
|
+
const now2 = Date.now();
|
|
1227
|
+
tempSession.authenticatorCreatedAt = now2;
|
|
1228
|
+
tempSession.authenticatorExpiresAt = now2 + authResult.expiresInMs;
|
|
1229
|
+
this.logger.log("EMBEDDED_PROVIDER", "Updated authenticator expiration from immediate auth response", {
|
|
1230
|
+
expiresInMs: authResult.expiresInMs,
|
|
1231
|
+
expiresAt: new Date(tempSession.authenticatorExpiresAt).toISOString()
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
1203
1234
|
await this.storage.saveSession(tempSession);
|
|
1204
1235
|
return tempSession;
|
|
1205
1236
|
}
|
|
@@ -1213,9 +1244,19 @@ var EmbeddedProvider = class {
|
|
|
1213
1244
|
}
|
|
1214
1245
|
session.walletId = authResult.walletId;
|
|
1215
1246
|
session.authProvider = authResult.provider || session.authProvider;
|
|
1247
|
+
session.organizationId = authResult.organizationId;
|
|
1216
1248
|
session.accountDerivationIndex = authResult.accountDerivationIndex;
|
|
1217
1249
|
session.status = "completed";
|
|
1218
1250
|
session.lastUsed = Date.now();
|
|
1251
|
+
if (authResult.expiresInMs > 0) {
|
|
1252
|
+
const now = Date.now();
|
|
1253
|
+
session.authenticatorCreatedAt = now;
|
|
1254
|
+
session.authenticatorExpiresAt = now + authResult.expiresInMs;
|
|
1255
|
+
this.logger.log("EMBEDDED_PROVIDER", "Updated authenticator expiration from auth response", {
|
|
1256
|
+
expiresInMs: authResult.expiresInMs,
|
|
1257
|
+
expiresAt: new Date(session.authenticatorExpiresAt).toISOString()
|
|
1258
|
+
});
|
|
1259
|
+
}
|
|
1219
1260
|
await this.storage.saveSession(session);
|
|
1220
1261
|
await this.initializeClientFromSession(session);
|
|
1221
1262
|
await this.ensureValidAuthenticator();
|
|
@@ -1269,13 +1310,13 @@ var EmbeddedProvider = class {
|
|
|
1269
1310
|
}
|
|
1270
1311
|
/*
|
|
1271
1312
|
* We use this method to perform silent authenticator renewal.
|
|
1272
|
-
* It generates a new keypair,
|
|
1313
|
+
* It generates a new keypair, adds a new user to the organization with the new keypair, and switches to it.
|
|
1273
1314
|
*/
|
|
1274
1315
|
async renewAuthenticator(session) {
|
|
1275
1316
|
if (!this.client) {
|
|
1276
1317
|
throw new Error("Client not initialized");
|
|
1277
1318
|
}
|
|
1278
|
-
this.logger.info("EMBEDDED_PROVIDER", "Starting authenticator renewal");
|
|
1319
|
+
this.logger.info("EMBEDDED_PROVIDER", "Starting authenticator renewal using addUserToOrganization");
|
|
1279
1320
|
try {
|
|
1280
1321
|
const newKeyInfo = await this.stamper.rotateKeyPair();
|
|
1281
1322
|
this.logger.log("EMBEDDED_PROVIDER", "Generated new keypair for renewal", {
|
|
@@ -1284,44 +1325,54 @@ var EmbeddedProvider = class {
|
|
|
1284
1325
|
});
|
|
1285
1326
|
const base64urlPublicKey = (0, import_base64url2.base64urlEncode)(import_bs582.default.decode(newKeyInfo.publicKey));
|
|
1286
1327
|
const expiresInMs = AUTHENTICATOR_EXPIRATION_TIME_MS;
|
|
1287
|
-
|
|
1328
|
+
const shortKeyId = newKeyInfo.keyId.substring(0, 8);
|
|
1329
|
+
const newUsername = `user-${shortKeyId}`;
|
|
1288
1330
|
try {
|
|
1289
|
-
|
|
1331
|
+
await this.client.addUserToOrganization({
|
|
1290
1332
|
organizationId: session.organizationId,
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1333
|
+
user: {
|
|
1334
|
+
username: newUsername,
|
|
1335
|
+
role: "ADMIN",
|
|
1336
|
+
// Use ADMIN role like original users
|
|
1337
|
+
authenticators: [
|
|
1338
|
+
{
|
|
1339
|
+
authenticatorName: `auth-${shortKeyId}`,
|
|
1340
|
+
authenticatorKind: "keypair",
|
|
1341
|
+
publicKey: base64urlPublicKey,
|
|
1342
|
+
algorithm: "Ed25519"
|
|
1343
|
+
}
|
|
1344
|
+
],
|
|
1345
|
+
traits: {
|
|
1346
|
+
appId: this.config.appId
|
|
1347
|
+
}
|
|
1300
1348
|
},
|
|
1349
|
+
expiresInMs,
|
|
1301
1350
|
replaceExpirable: true
|
|
1351
|
+
// Replace oldest expirable user if at limit
|
|
1302
1352
|
});
|
|
1303
1353
|
} catch (error) {
|
|
1304
|
-
this.logger.error("EMBEDDED_PROVIDER", "Failed to
|
|
1354
|
+
this.logger.error("EMBEDDED_PROVIDER", "Failed to add new user to organization", {
|
|
1305
1355
|
error: error instanceof Error ? error.message : String(error)
|
|
1306
1356
|
});
|
|
1307
1357
|
await this.stamper.rollbackRotation();
|
|
1308
1358
|
throw new Error(
|
|
1309
|
-
`Failed to
|
|
1359
|
+
`Failed to add new user to organization: ${error instanceof Error ? error.message : String(error)}`
|
|
1310
1360
|
);
|
|
1311
1361
|
}
|
|
1312
|
-
this.logger.info("EMBEDDED_PROVIDER", "
|
|
1313
|
-
|
|
1362
|
+
this.logger.info("EMBEDDED_PROVIDER", "Added new user to organization successfully", {
|
|
1363
|
+
username: newUsername
|
|
1314
1364
|
});
|
|
1315
|
-
await this.stamper.commitRotation(
|
|
1365
|
+
await this.stamper.commitRotation(newKeyInfo.keyId);
|
|
1316
1366
|
const now = Date.now();
|
|
1317
1367
|
session.stamperInfo = newKeyInfo;
|
|
1318
1368
|
session.authenticatorCreatedAt = now;
|
|
1319
|
-
session.authenticatorExpiresAt =
|
|
1369
|
+
session.authenticatorExpiresAt = now + expiresInMs;
|
|
1320
1370
|
session.lastRenewalAttempt = now;
|
|
1321
1371
|
await this.storage.saveSession(session);
|
|
1322
1372
|
this.logger.info("EMBEDDED_PROVIDER", "Authenticator renewal completed successfully", {
|
|
1323
1373
|
newKeyId: newKeyInfo.keyId,
|
|
1324
|
-
|
|
1374
|
+
newUsername,
|
|
1375
|
+
expiresAt: new Date(session.authenticatorExpiresAt).toISOString()
|
|
1325
1376
|
});
|
|
1326
1377
|
} catch (error) {
|
|
1327
1378
|
await this.stamper.rollbackRotation();
|