@supertokens-plugins/rownd-nodejs 0.5.0 → 0.6.0

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.
@@ -62,12 +62,15 @@ var ConfigSchema = import_zod.z.object({
62
62
  appKey: import_zod.z.string(),
63
63
  appSecret: import_zod.z.string(),
64
64
  bearerToken: import_zod.z.string().optional(),
65
- pageSize: import_zod.z.number().int().positive()
65
+ pageSize: import_zod.z.number().int().positive(),
66
+ oidcClientSecrets: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional(),
67
+ provisionOidcClientIdAliases: import_zod.z.boolean().default(true)
66
68
  }),
67
69
  supertokens: import_zod.z.object({
68
70
  connectionURI: import_zod.z.string(),
69
71
  apiKey: import_zod.z.string().optional(),
70
- batchSize: import_zod.z.number().int().positive()
72
+ batchSize: import_zod.z.number().int().positive(),
73
+ tenantId: import_zod.z.string().min(1).default("public")
71
74
  }),
72
75
  thirdPartyProviders: import_zod.z.array(
73
76
  import_zod.z.object({
@@ -187,55 +190,118 @@ async function provisionSuperTokensInfrastructure(config, oidcClients) {
187
190
  if (config.supertokens.apiKey) {
188
191
  headers["api-key"] = config.supertokens.apiKey;
189
192
  }
193
+ const provisionedClientIds = /* @__PURE__ */ new Set();
190
194
  for (const oidcClient of oidcClients) {
191
- for (const credential of oidcClient.credentials ?? []) {
192
- console.log(
193
- `Provisioning SuperTokens OAuth2 Client: ${credential.client_id}`
195
+ const credentials = oidcClient.credentials ?? [];
196
+ for (const credential of credentials) {
197
+ await createSuperTokensOAuthClient({
198
+ config,
199
+ headers,
200
+ oidcClient,
201
+ clientId: credential.client_id,
202
+ clientSecret: resolveOidcClientSecret(
203
+ config,
204
+ credential.client_id,
205
+ credential.secret
206
+ ),
207
+ appVariantId: credential.app_variant_id,
208
+ provisionedClientIds
209
+ });
210
+ }
211
+ if (config.rownd.provisionOidcClientIdAliases && credentials.length > 0) {
212
+ const firstCredential = credentials[0];
213
+ if (!firstCredential) {
214
+ continue;
215
+ }
216
+ const firstCredentialSecret = resolveOidcClientSecret(
217
+ config,
218
+ firstCredential.client_id,
219
+ firstCredential.secret
194
220
  );
195
- const oauthRes = await fetch(
196
- new URL(
197
- "/recipe/oauth/clients",
198
- config.supertokens.connectionURI
199
- ).toString(),
200
- {
201
- method: "POST",
202
- headers,
203
- body: JSON.stringify({
204
- clientName: oidcClient.name || credential.client_id || "Rownd Client",
205
- clientId: credential.client_id,
206
- clientSecret: credential.secret,
207
- redirectUris: oidcClient.config.redirect_uris || [],
208
- postLogoutRedirectUris: oidcClient.config.post_logout_uris || [],
209
- scope: oidcClient.config.allowed_scopes?.join(" "),
210
- responseTypes: ["code", "token", "id_token"],
211
- grantTypes: [
212
- "authorization_code",
213
- "refresh_token",
214
- "client_credentials",
215
- "implicit"
216
- ],
217
- tokenEndpointAuthMethod: oidcClient.config.token_endpoint_auth_method ?? "client_secret_basic",
218
- audience: [`app:${config.rownd.appId}`],
219
- metadata: {
220
- rowndOidcClientId: oidcClient.id,
221
- rowndAppVariantId: credential.app_variant_id || void 0,
222
- rowndAllowedScopes: oidcClient.config.allowed_scopes || [],
223
- rowndApplicationType: oidcClient.config.application_type,
224
- rowndIsPkceRequired: oidcClient.config.is_pkce_required,
225
- rowndIsPkceSupported: oidcClient.config.is_pkce_supported,
226
- rowndDeviceFlowEnabled: oidcClient.config.device_flow_enabled
227
- }
228
- })
229
- }
221
+ const aliasSecret = resolveOidcClientSecret(
222
+ config,
223
+ oidcClient.id,
224
+ firstCredentialSecret
230
225
  );
231
- if (!oauthRes.ok) {
232
- const errorText = await oauthRes.text();
233
- if (!errorText.includes("already exists") && !errorText.includes("Duplicate")) {
234
- throw new Error(
235
- `Failed to create OAuth2 Client ${credential.client_id}: ${oauthRes.status} ${errorText}`
236
- );
226
+ await createSuperTokensOAuthClient({
227
+ config,
228
+ headers,
229
+ oidcClient,
230
+ clientId: oidcClient.id,
231
+ clientSecret: aliasSecret,
232
+ isOidcClientIdAlias: true,
233
+ provisionedClientIds
234
+ });
235
+ }
236
+ }
237
+ }
238
+ function resolveOidcClientSecret(config, clientId, apiSecret) {
239
+ const secret = config.rownd.oidcClientSecrets?.[clientId] ?? apiSecret;
240
+ if (!secret) {
241
+ throw new Error(
242
+ `Missing plaintext secret for Rownd OIDC client ${clientId}. Add rownd.oidcClientSecrets.${clientId} to the config.`
243
+ );
244
+ }
245
+ if (secret.startsWith("$argon2")) {
246
+ throw new Error(
247
+ `Rownd returned a hashed secret for OIDC client ${clientId}. Add the plaintext secret under rownd.oidcClientSecrets.${clientId}.`
248
+ );
249
+ }
250
+ return secret;
251
+ }
252
+ async function createSuperTokensOAuthClient(input) {
253
+ if (input.provisionedClientIds.has(input.clientId)) {
254
+ return;
255
+ }
256
+ input.provisionedClientIds.add(input.clientId);
257
+ console.log(`Provisioning SuperTokens OAuth2 Client: ${input.clientId}`);
258
+ const grantTypes = [
259
+ "authorization_code",
260
+ "refresh_token",
261
+ "client_credentials",
262
+ "implicit"
263
+ ];
264
+ if (input.oidcClient.config.device_flow_enabled) {
265
+ grantTypes.push("urn:ietf:params:oauth:grant-type:device_code");
266
+ }
267
+ const oauthRes = await fetch(
268
+ new URL(
269
+ "/recipe/oauth/clients",
270
+ input.config.supertokens.connectionURI
271
+ ).toString(),
272
+ {
273
+ method: "POST",
274
+ headers: input.headers,
275
+ body: JSON.stringify({
276
+ clientName: input.oidcClient.name || input.clientId || "Rownd Client",
277
+ clientId: input.clientId,
278
+ clientSecret: input.clientSecret,
279
+ redirectUris: input.oidcClient.config.redirect_uris || [],
280
+ postLogoutRedirectUris: input.oidcClient.config.post_logout_uris || [],
281
+ scope: input.oidcClient.config.allowed_scopes?.join(" "),
282
+ responseTypes: ["code", "token", "id_token"],
283
+ grantTypes,
284
+ tokenEndpointAuthMethod: input.oidcClient.config.token_endpoint_auth_method ?? "client_secret_basic",
285
+ audience: [`app:${input.config.rownd.appId}`],
286
+ metadata: {
287
+ rowndOidcClientId: input.oidcClient.id,
288
+ rowndAppVariantId: input.appVariantId || void 0,
289
+ rowndAllowedScopes: input.oidcClient.config.allowed_scopes || [],
290
+ rowndApplicationType: input.oidcClient.config.application_type,
291
+ rowndIsPkceRequired: input.oidcClient.config.is_pkce_required,
292
+ rowndIsPkceSupported: input.oidcClient.config.is_pkce_supported,
293
+ rowndDeviceFlowEnabled: input.oidcClient.config.device_flow_enabled,
294
+ rowndIsOidcClientIdAlias: input.isOidcClientIdAlias || void 0
237
295
  }
238
- }
296
+ })
297
+ }
298
+ );
299
+ if (!oauthRes.ok) {
300
+ const errorText = await oauthRes.text();
301
+ if (!errorText.includes("already exists") && !errorText.includes("Duplicate")) {
302
+ throw new Error(
303
+ `Failed to create OAuth2 Client ${input.clientId}: ${oauthRes.status} ${errorText}`
304
+ );
239
305
  }
240
306
  }
241
307
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supertokens-plugins/rownd-nodejs",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Rownd User Migration Plugin for SuperTokens",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",