emulate 0.4.1 → 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.
Files changed (50) hide show
  1. package/README.md +198 -27
  2. package/dist/api.d.ts +2 -1
  3. package/dist/api.js +675 -103
  4. package/dist/api.js.map +1 -1
  5. package/dist/chunk-WVQMFHQM.js +83 -0
  6. package/dist/chunk-WVQMFHQM.js.map +1 -0
  7. package/dist/{dist-B674PYKV.js → dist-2ZZGNPJI.js} +22 -43
  8. package/dist/dist-2ZZGNPJI.js.map +1 -0
  9. package/dist/{dist-RDFBZ5O6.js → dist-CXRPM6BK.js} +211 -48
  10. package/dist/dist-CXRPM6BK.js.map +1 -0
  11. package/dist/{dist-VVXVP5EZ.js → dist-DSJSF3GY.js} +551 -91
  12. package/dist/dist-DSJSF3GY.js.map +1 -0
  13. package/dist/{dist-RMK3BS5M.js → dist-IFULY5LE.js} +196 -33
  14. package/dist/dist-IFULY5LE.js.map +1 -0
  15. package/dist/dist-IRUBHCZU.js +1898 -0
  16. package/dist/dist-IRUBHCZU.js.map +1 -0
  17. package/dist/{dist-YOVM5HEY.js → dist-NJJLJT2N.js} +520 -61
  18. package/dist/dist-NJJLJT2N.js.map +1 -0
  19. package/dist/dist-OGSAVJ25.js +4874 -0
  20. package/dist/dist-OGSAVJ25.js.map +1 -0
  21. package/dist/{dist-H6JYGQM4.js → dist-PO4CL5SJ.js} +271 -158
  22. package/dist/dist-PO4CL5SJ.js.map +1 -0
  23. package/dist/{dist-QMOJM6DV.js → dist-R3TNKUIE.js} +238 -55
  24. package/dist/dist-R3TNKUIE.js.map +1 -0
  25. package/dist/{dist-6JFNJPUU.js → dist-WACHAAVU.js} +171 -22
  26. package/dist/dist-WACHAAVU.js.map +1 -0
  27. package/dist/{dist-OTJZRQ3Q.js → dist-XWWZVLQQ.js} +216 -75
  28. package/dist/dist-XWWZVLQQ.js.map +1 -0
  29. package/dist/{dist-6EW7SSOZ.js → dist-ZY5SZSJ2.js} +397 -223
  30. package/dist/dist-ZY5SZSJ2.js.map +1 -0
  31. package/dist/fonts/favicon.ico +0 -0
  32. package/dist/helpers-LXLP3DFE-LBOTATT5.js +17 -0
  33. package/dist/helpers-LXLP3DFE-LBOTATT5.js.map +1 -0
  34. package/dist/index.js +812 -117
  35. package/dist/index.js.map +1 -1
  36. package/package.json +17 -15
  37. package/dist/chunk-TEPNEZ63.js +0 -2143
  38. package/dist/chunk-TEPNEZ63.js.map +0 -1
  39. package/dist/dist-6EW7SSOZ.js.map +0 -1
  40. package/dist/dist-6JFNJPUU.js.map +0 -1
  41. package/dist/dist-B674PYKV.js.map +0 -1
  42. package/dist/dist-G7WQPZ3Y.js +0 -1287
  43. package/dist/dist-G7WQPZ3Y.js.map +0 -1
  44. package/dist/dist-H6JYGQM4.js.map +0 -1
  45. package/dist/dist-OTJZRQ3Q.js.map +0 -1
  46. package/dist/dist-QMOJM6DV.js.map +0 -1
  47. package/dist/dist-RDFBZ5O6.js.map +0 -1
  48. package/dist/dist-RMK3BS5M.js.map +0 -1
  49. package/dist/dist-VVXVP5EZ.js.map +0 -1
  50. package/dist/dist-YOVM5HEY.js.map +0 -1
@@ -3,7 +3,6 @@ import {
3
3
  exportJWK,
4
4
  generateKeyPair
5
5
  } from "./chunk-D6EKRYGP.js";
6
- import "./chunk-TEPNEZ63.js";
7
6
 
8
7
  // ../@emulators/okta/dist/index.js
9
8
  import { randomUUID } from "crypto";
@@ -129,6 +128,7 @@ var FONTS = {
129
128
  "geist-sans.woff2": readFileSync(join(__dirname, "fonts", "geist-sans.woff2")),
130
129
  "GeistPixel-Square.woff2": readFileSync(join(__dirname, "fonts", "GeistPixel-Square.woff2"))
131
130
  };
131
+ var FAVICON = readFileSync(join(__dirname, "fonts", "favicon.ico"));
132
132
  function parsePagination(c) {
133
133
  const page = Math.max(1, parseInt(c.req.query("page") ?? "1", 10) || 1);
134
134
  const per_page = Math.min(100, Math.max(1, parseInt(c.req.query("per_page") ?? "30", 10) || 30));
@@ -306,6 +306,132 @@ body{
306
306
  .app-link-name{font-weight:600;font-size:.875rem;color:#33ff00;}
307
307
  .app-link-scopes{font-size:.6875rem;color:#1a8c00;margin-top:1px;}
308
308
  .empty{color:#1a8c00;text-align:center;padding:28px 0;font-size:.875rem;}
309
+
310
+ .inspector-layout{max-width:960px;margin:0 auto;padding:28px 20px;}
311
+ .inspector-tabs{display:flex;gap:4px;margin-bottom:20px;}
312
+ .inspector-tabs a{
313
+ padding:7px 16px;border-radius:6px;text-decoration:none;
314
+ font-size:.8125rem;color:#1a8c00;border:1px solid transparent;
315
+ transition:color .15s,border-color .15s;
316
+ }
317
+ .inspector-tabs a:hover{color:#33ff00;}
318
+ .inspector-tabs a.active{color:#33ff00;font-weight:600;border-color:#0a3300;background:#0a3300;}
319
+ .inspector-section{margin-bottom:24px;}
320
+ .inspector-section h2{
321
+ font-family:'Geist Pixel',monospace;
322
+ font-size:1rem;font-weight:600;color:#33ff00;margin-bottom:10px;
323
+ }
324
+ .inspector-section h3{
325
+ font-family:'Geist Pixel',monospace;
326
+ font-size:.875rem;font-weight:600;color:#1a8c00;margin:16px 0 8px;
327
+ }
328
+ .inspector-table{width:100%;border-collapse:collapse;margin-bottom:12px;}
329
+ .inspector-table th,.inspector-table td{
330
+ text-align:left;padding:8px 12px;border-bottom:1px solid #0a3300;
331
+ font-size:.8125rem;
332
+ }
333
+ .inspector-table th{color:#1a8c00;font-weight:600;font-size:.75rem;text-transform:uppercase;letter-spacing:.04em;}
334
+ .inspector-table td{color:#33ff00;}
335
+ .inspector-table tbody tr{transition:background .1s;}
336
+ .inspector-table tbody tr:hover{background:#0a3300;}
337
+ .inspector-empty{color:#1a8c00;text-align:center;padding:20px 0;font-size:.8125rem;}
338
+
339
+ .checkout-layout{
340
+ display:flex;min-height:calc(100vh - 42px);
341
+ }
342
+ .checkout-summary{
343
+ flex:1;background:#020;padding:48px 40px 48px 10%;
344
+ display:flex;flex-direction:column;justify-content:center;
345
+ border-right:1px solid #0a3300;
346
+ }
347
+ .checkout-form-side{
348
+ flex:1;background:#000;padding:48px 10% 48px 40px;
349
+ display:flex;flex-direction:column;justify-content:center;
350
+ }
351
+ .checkout-merchant{
352
+ display:flex;align-items:center;gap:10px;margin-bottom:6px;
353
+ }
354
+ .checkout-merchant-name{
355
+ font-family:'Geist Pixel',monospace;
356
+ font-size:.9375rem;font-weight:600;color:#33ff00;
357
+ }
358
+ .checkout-test-badge{
359
+ font-size:.625rem;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
360
+ background:#0a3300;color:#1a8c00;padding:2px 8px;border-radius:4px;
361
+ }
362
+ .checkout-total{
363
+ font-family:'Geist Pixel',monospace;
364
+ font-size:2rem;font-weight:700;color:#33ff00;margin:8px 0 28px;
365
+ }
366
+ .checkout-line-item{
367
+ display:flex;align-items:center;gap:14px;padding:14px 0;
368
+ border-bottom:1px solid #0a3300;
369
+ }
370
+ .checkout-line-item:first-child{border-top:1px solid #0a3300;}
371
+ .checkout-item-icon{
372
+ width:42px;height:42px;border-radius:6px;background:#0a3300;
373
+ display:flex;align-items:center;justify-content:center;flex-shrink:0;
374
+ font-family:'Geist Pixel',monospace;font-size:.875rem;font-weight:700;color:#116600;
375
+ }
376
+ .checkout-item-details{flex:1;min-width:0;}
377
+ .checkout-item-name{font-size:.875rem;font-weight:600;color:#33ff00;}
378
+ .checkout-item-qty{font-size:.75rem;color:#1a8c00;margin-top:2px;}
379
+ .checkout-item-price{
380
+ font-size:.875rem;font-weight:600;color:#33ff00;text-align:right;white-space:nowrap;
381
+ }
382
+ .checkout-item-unit{font-size:.6875rem;color:#1a8c00;text-align:right;margin-top:2px;}
383
+ .checkout-totals{margin-top:20px;}
384
+ .checkout-totals-row{
385
+ display:flex;justify-content:space-between;padding:6px 0;
386
+ font-size:.8125rem;color:#1a8c00;
387
+ }
388
+ .checkout-totals-row.total{
389
+ border-top:1px solid #0a3300;margin-top:8px;padding-top:14px;
390
+ font-size:.9375rem;font-weight:600;color:#33ff00;
391
+ }
392
+ .checkout-form-section{margin-bottom:24px;}
393
+ .checkout-form-label{
394
+ font-size:.8125rem;font-weight:600;color:#33ff00;margin-bottom:8px;display:block;
395
+ }
396
+ .checkout-input{
397
+ width:100%;padding:10px 12px;border:1px solid #0a3300;border-radius:6px;
398
+ background:#020;color:#33ff00;font:inherit;font-size:.875rem;
399
+ transition:border-color .15s;outline:none;
400
+ }
401
+ .checkout-input:focus{border-color:#33ff00;}
402
+ .checkout-input::placeholder{color:#116600;}
403
+ .checkout-card-box{
404
+ border:1px solid #0a3300;border-radius:6px;padding:14px;
405
+ background:#020;
406
+ }
407
+ .checkout-card-row{
408
+ display:flex;gap:12px;margin-top:10px;
409
+ }
410
+ .checkout-card-row .checkout-input{flex:1;}
411
+ .checkout-sim-note{
412
+ font-size:.6875rem;color:#1a8c00;margin-top:10px;text-align:center;
413
+ font-style:italic;
414
+ }
415
+ .checkout-pay-btn{
416
+ width:100%;padding:14px;border:none;border-radius:8px;
417
+ background:#33ff00;color:#000;font:inherit;font-size:.9375rem;font-weight:700;
418
+ cursor:pointer;transition:background .15s;
419
+ font-family:'Geist Pixel',monospace;
420
+ }
421
+ .checkout-pay-btn:hover{background:#44ff22;}
422
+ .checkout-cancel{
423
+ text-align:center;margin-top:14px;
424
+ }
425
+ .checkout-cancel a{
426
+ color:#1a8c00;text-decoration:none;font-size:.8125rem;
427
+ transition:color .15s;
428
+ }
429
+ .checkout-cancel a:hover{color:#33ff00;}
430
+ @media(max-width:768px){
431
+ .checkout-layout{flex-direction:column;}
432
+ .checkout-summary{padding:32px 20px;border-right:none;border-bottom:1px solid #0a3300;}
433
+ .checkout-form-side{padding:32px 20px;}
434
+ }
309
435
  `;
310
436
  var POWERED_BY = `<div class="powered-by">Powered by <a href="https://emulate.dev" target="_blank" rel="noopener">emulate</a></div>`;
311
437
  function emuBar(service) {
@@ -325,6 +451,7 @@ function head(title) {
325
451
  <head>
326
452
  <meta charset="utf-8"/>
327
453
  <meta name="viewport" content="width=device-width,initial-scale=1"/>
454
+ <link rel="icon" href="/_emulate/favicon.ico"/>
328
455
  <title>${escapeHtml(title)} | emulate</title>
329
456
  <style>${CSS}</style>
330
457
  </head>`;
@@ -356,6 +483,25 @@ ${emuBar(service)}
356
483
  ${POWERED_BY}
357
484
  </body></html>`;
358
485
  }
486
+ function renderFormPostPage(action, fields, service) {
487
+ const hiddens = Object.entries(fields).filter(([, v]) => v != null).map(([k, v]) => `<input type="hidden" name="${escapeAttr(k)}" value="${escapeAttr(v)}"/>`).join("\n");
488
+ return `${head("Redirecting")}
489
+ <body onload="document.forms[0].submit()">
490
+ ${emuBar(service)}
491
+ <div class="content">
492
+ <div class="content-inner" style="text-align:center">
493
+ <div class="card-subtitle">Redirecting&hellip;</div>
494
+ <form method="POST" action="${escapeAttr(action)}">
495
+ ${hiddens}
496
+ <noscript><button type="submit" class="user-btn" style="margin-top:12px;justify-content:center">
497
+ <span class="user-login">Continue</span>
498
+ </button></noscript>
499
+ </form>
500
+ </div>
501
+ </div>
502
+ ${POWERED_BY}
503
+ </body></html>`;
504
+ }
359
505
  function renderUserButton(opts) {
360
506
  const hiddens = Object.entries(opts.hiddenFields).map(([k, v]) => `<input type="hidden" name="${escapeAttr(k)}" value="${escapeAttr(v)}"/>`).join("");
361
507
  const nameLine = opts.name ? `<div class="user-meta">${escapeHtml(opts.name)}</div>` : "";
@@ -538,7 +684,10 @@ function getOktaStore(store) {
538
684
  apps: store.collection("okta.apps", ["okta_id", "name"]),
539
685
  oauthClients: store.collection("okta.oauth_clients", ["client_id", "auth_server_id"]),
540
686
  authorizationServers: store.collection("okta.auth_servers", ["server_id"]),
541
- groupMemberships: store.collection("okta.group_memberships", ["group_okta_id", "user_okta_id"]),
687
+ groupMemberships: store.collection("okta.group_memberships", [
688
+ "group_okta_id",
689
+ "user_okta_id"
690
+ ]),
542
691
  appAssignments: store.collection("okta.app_assignments", ["app_okta_id", "user_okta_id"])
543
692
  };
544
693
  }
@@ -550,9 +699,7 @@ function appRoutes({ app, store, baseUrl, tokenMap }) {
550
699
  const q = (c.req.query("q") ?? "").toLowerCase();
551
700
  let apps = oktaStore.apps.all();
552
701
  if (q) {
553
- apps = apps.filter(
554
- (entry) => `${entry.name} ${entry.label}`.toLowerCase().includes(q)
555
- );
702
+ apps = apps.filter((entry) => `${entry.name} ${entry.label}`.toLowerCase().includes(q));
556
703
  }
557
704
  const { page, per_page } = parsePagination(c);
558
705
  const total = apps.length;
@@ -776,9 +923,7 @@ function groupRoutes({ app, store, baseUrl, tokenMap }) {
776
923
  const q = (c.req.query("q") ?? "").toLowerCase();
777
924
  let groups = oktaStore.groups.all();
778
925
  if (q) {
779
- groups = groups.filter(
780
- (group) => `${group.name} ${group.description ?? ""}`.toLowerCase().includes(q)
781
- );
926
+ groups = groups.filter((group) => `${group.name} ${group.description ?? ""}`.toLowerCase().includes(q));
782
927
  }
783
928
  const { page, per_page } = parsePagination(c);
784
929
  const total = groups.length;
@@ -1080,10 +1225,10 @@ async function createIdToken(oktaStore, user, clientId, nonce, issuer, scope) {
1080
1225
  return new SignJWT(claims).setProtectedHeader({ alg: "RS256", kid: KID, typ: "JWT" }).setIssuer(issuer).setAudience(clientId).setIssuedAt(now).setExpirationTime("1h").sign(privateKey);
1081
1226
  }
1082
1227
  function unauthorizedOAuthError() {
1083
- return new Response(
1084
- JSON.stringify({ error: "invalid_token", error_description: "The access token is invalid." }),
1085
- { status: 401, headers: { "Content-Type": "application/json" } }
1086
- );
1228
+ return new Response(JSON.stringify({ error: "invalid_token", error_description: "The access token is invalid." }), {
1229
+ status: 401,
1230
+ headers: { "Content-Type": "application/json" }
1231
+ });
1087
1232
  }
1088
1233
  function oauthRoutes({ app, store, baseUrl, tokenMap }) {
1089
1234
  const oktaStore = getOktaStore(store);
@@ -1152,7 +1297,11 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
1152
1297
  }
1153
1298
  if (!matchesRedirectUri(redirectUri, client.redirect_uris)) {
1154
1299
  return c.html(
1155
- renderErrorPage("Redirect URI mismatch", "The redirect_uri is not registered for this application.", SERVICE_LABEL),
1300
+ renderErrorPage(
1301
+ "Redirect URI mismatch",
1302
+ "The redirect_uri is not registered for this application.",
1303
+ SERVICE_LABEL
1304
+ ),
1156
1305
  400
1157
1306
  );
1158
1307
  }
@@ -1160,25 +1309,27 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
1160
1309
  }
1161
1310
  const users = oktaStore.users.all();
1162
1311
  const callbackPath = `${buildOAuthBasePath(authServerId)}/authorize/callback`;
1163
- const buttons = users.map((user) => renderUserButton({
1164
- letter: (user.login[0] ?? "?").toUpperCase(),
1165
- login: user.login,
1166
- name: userDisplayName(user),
1167
- email: user.email,
1168
- formAction: callbackPath,
1169
- hiddenFields: {
1170
- user_ref: user.okta_id,
1171
- redirect_uri: redirectUri,
1172
- scope,
1173
- state,
1174
- nonce,
1175
- client_id: clientId,
1176
- response_mode: responseMode,
1177
- code_challenge: codeChallenge,
1178
- code_challenge_method: codeChallengeMethod,
1179
- auth_server_id: authServerId
1180
- }
1181
- })).join("\n");
1312
+ const buttons = users.map(
1313
+ (user) => renderUserButton({
1314
+ letter: (user.login[0] ?? "?").toUpperCase(),
1315
+ login: user.login,
1316
+ name: userDisplayName(user),
1317
+ email: user.email,
1318
+ formAction: callbackPath,
1319
+ hiddenFields: {
1320
+ user_ref: user.okta_id,
1321
+ redirect_uri: redirectUri,
1322
+ scope,
1323
+ state,
1324
+ nonce,
1325
+ client_id: clientId,
1326
+ response_mode: responseMode,
1327
+ code_challenge: codeChallenge,
1328
+ code_challenge_method: codeChallengeMethod,
1329
+ auth_server_id: authServerId
1330
+ }
1331
+ })
1332
+ ).join("\n");
1182
1333
  const subtitle = clientName ? `Sign in to <strong>${escapeHtml(clientName)}</strong> with your Okta account.` : "Choose a seeded user to continue.";
1183
1334
  return c.html(
1184
1335
  renderCardPage(
@@ -1212,10 +1363,7 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
1212
1363
  }
1213
1364
  const user = findUserByRef(oktaStore, userRef);
1214
1365
  if (!user) {
1215
- return c.html(
1216
- renderErrorPage("Unknown user", "The selected user is not available.", SERVICE_LABEL),
1217
- 400
1218
- );
1366
+ return c.html(renderErrorPage("Unknown user", "The selected user is not available.", SERVICE_LABEL), 400);
1219
1367
  }
1220
1368
  const configuredClients = getClientsForServer(oktaStore.oauthClients.all(), authServerId);
1221
1369
  if (configuredClients.length > 0) {
@@ -1228,7 +1376,11 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
1228
1376
  }
1229
1377
  if (!matchesRedirectUri(redirectUri, client.redirect_uris)) {
1230
1378
  return c.html(
1231
- renderErrorPage("Redirect URI mismatch", "The redirect_uri is not registered for this application.", SERVICE_LABEL),
1379
+ renderErrorPage(
1380
+ "Redirect URI mismatch",
1381
+ "The redirect_uri is not registered for this application.",
1382
+ SERVICE_LABEL
1383
+ ),
1232
1384
  400
1233
1385
  );
1234
1386
  }
@@ -1247,17 +1399,7 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
1247
1399
  });
1248
1400
  debug("okta.oauth", `[callback] code=${code.slice(0, 8)}... user=${user.login} server=${authServerId}`);
1249
1401
  if (responseMode === "form_post") {
1250
- const html = `<!DOCTYPE html>
1251
- <html>
1252
- <head><title>Submit</title></head>
1253
- <body onload="document.forms[0].submit()">
1254
- <form method="POST" action="${escapeAttr(redirectUri)}">
1255
- <input type="hidden" name="code" value="${escapeAttr(code)}" />
1256
- <input type="hidden" name="state" value="${escapeAttr(state)}" />
1257
- </form>
1258
- </body>
1259
- </html>`;
1260
- return c.html(html);
1402
+ return c.html(renderFormPostPage(redirectUri, { code, state }, SERVICE_LABEL));
1261
1403
  }
1262
1404
  const url = new URL(redirectUri);
1263
1405
  url.searchParams.set("code", code);
@@ -1265,7 +1407,10 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
1265
1407
  return c.redirect(url.toString(), 302);
1266
1408
  };
1267
1409
  app.post("/oauth2/v1/authorize/callback", (c) => handleAuthorizeCallback(c, ORG_AUTH_SERVER_ID));
1268
- app.post("/oauth2/:authServerId/v1/authorize/callback", (c) => handleAuthorizeCallback(c, c.req.param("authServerId")));
1410
+ app.post(
1411
+ "/oauth2/:authServerId/v1/authorize/callback",
1412
+ (c) => handleAuthorizeCallback(c, c.req.param("authServerId"))
1413
+ );
1269
1414
  const handleToken = async (c, authServerId) => {
1270
1415
  const server = resolveServer(authServerId, baseUrl, oktaStore);
1271
1416
  if (!server) return oktaError(c, 404, "E0000007", `Not found: authorization server '${authServerId}'`);
@@ -1295,7 +1440,10 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
1295
1440
  return c.json({ error: "invalid_grant", error_description: "redirect_uri does not match." }, 400);
1296
1441
  }
1297
1442
  if (validatedClient && validatedClient.client_id !== pending.clientId) {
1298
- return c.json({ error: "invalid_grant", error_description: "Authorization code was not issued to this client." }, 400);
1443
+ return c.json(
1444
+ { error: "invalid_grant", error_description: "Authorization code was not issued to this client." },
1445
+ 400
1446
+ );
1299
1447
  }
1300
1448
  if (pending.codeChallenge !== null) {
1301
1449
  if (!codeVerifier) {
@@ -1345,14 +1493,7 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
1345
1493
  id: user.id,
1346
1494
  scopes: parseScope(scope)
1347
1495
  });
1348
- const idToken = await createIdToken(
1349
- oktaStore,
1350
- user,
1351
- audienceClient,
1352
- pending.nonce,
1353
- server.issuer,
1354
- scope
1355
- );
1496
+ const idToken = await createIdToken(oktaStore, user, audienceClient, pending.nonce, server.issuer, scope);
1356
1497
  return c.json({
1357
1498
  token_type: "Bearer",
1358
1499
  expires_in: 3600,
@@ -1371,7 +1512,10 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
1371
1512
  return c.json({ error: "invalid_grant", error_description: "Authorization server mismatch." }, 400);
1372
1513
  }
1373
1514
  if (validatedClient && validatedClient.client_id !== existing.clientId) {
1374
- return c.json({ error: "invalid_grant", error_description: "Refresh token was not issued to this client." }, 400);
1515
+ return c.json(
1516
+ { error: "invalid_grant", error_description: "Refresh token was not issued to this client." },
1517
+ 400
1518
+ );
1375
1519
  }
1376
1520
  const user = oktaStore.users.findOneBy("okta_id", existing.userOktaId);
1377
1521
  if (!user) return c.json({ error: "invalid_grant", error_description: "Unknown user." }, 400);
@@ -1541,9 +1685,7 @@ function oauthRoutes({ app, store, baseUrl, tokenMap }) {
1541
1685
  if (!postLogoutRedirectUri) return c.text("Logged out");
1542
1686
  const scopedClients = getClientsForServer(oktaStore.oauthClients.all(), authServerId);
1543
1687
  if (scopedClients.length > 0) {
1544
- const isAllowed = scopedClients.some(
1545
- (client) => matchesRedirectUri(postLogoutRedirectUri, client.redirect_uris)
1546
- );
1688
+ const isAllowed = scopedClients.some((client) => matchesRedirectUri(postLogoutRedirectUri, client.redirect_uris));
1547
1689
  if (!isAllowed) return c.text("Invalid post_logout_redirect_uri", 400);
1548
1690
  }
1549
1691
  return c.redirect(postLogoutRedirectUri, 302);
@@ -1665,14 +1807,16 @@ function userRoutes({ app, store, baseUrl, tokenMap }) {
1665
1807
  if (!user) return oktaError(c, 404, "E0000007", "Not found: user");
1666
1808
  const memberships = oktaStore.groupMemberships.findBy("user_okta_id", user.okta_id);
1667
1809
  const groups = memberships.map((membership) => oktaStore.groups.findOneBy("okta_id", membership.group_okta_id)).filter((group) => Boolean(group));
1668
- return c.json(groups.map((group) => ({
1669
- id: group.okta_id,
1670
- profile: {
1671
- name: group.name,
1672
- description: group.description
1673
- },
1674
- type: group.type
1675
- })));
1810
+ return c.json(
1811
+ groups.map((group) => ({
1812
+ id: group.okta_id,
1813
+ profile: {
1814
+ name: group.name,
1815
+ description: group.description
1816
+ },
1817
+ type: group.type
1818
+ }))
1819
+ );
1676
1820
  });
1677
1821
  app.post("/api/v1/users/:userId/lifecycle/activate", (c) => {
1678
1822
  const auth = requireManagementAuth(c, tokenMap);
@@ -1818,10 +1962,7 @@ function seedDefaults(store, _baseUrl) {
1818
1962
  client_id: "okta-test-app",
1819
1963
  client_secret: "",
1820
1964
  name: "Sample Public PKCE Client",
1821
- redirect_uris: [
1822
- "http://localhost:3000/official-sdk/callback",
1823
- "http://localhost:3000/official-sdk"
1824
- ],
1965
+ redirect_uris: ["http://localhost:3000/official-sdk/callback", "http://localhost:3000/official-sdk"],
1825
1966
  response_types: ["code"],
1826
1967
  grant_types: ["authorization_code", "refresh_token"],
1827
1968
  token_endpoint_auth_method: "none",
@@ -1953,4 +2094,4 @@ export {
1953
2094
  oktaPlugin,
1954
2095
  seedFromConfig
1955
2096
  };
1956
- //# sourceMappingURL=dist-OTJZRQ3Q.js.map
2097
+ //# sourceMappingURL=dist-XWWZVLQQ.js.map