@absolutejs/auth 0.45.8 → 0.46.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.
package/dist/index.js CHANGED
@@ -10005,7 +10005,8 @@ var samlSsoRoutes = ({
10005
10005
  }
10006
10006
  const metadata = await samlAdapter.getServiceProviderMetadata({
10007
10007
  acsUrl: acsUrlFor(request.url, organizationId),
10008
- connection
10008
+ connection,
10009
+ sloUrl: sloUrlFor(request.url, organizationId)
10009
10010
  });
10010
10011
  return new Response(metadata, {
10011
10012
  headers: { "content-type": "application/xml" }
@@ -10045,7 +10046,13 @@ var samlSsoRoutes = ({
10045
10046
  }).get(sloRoute, async ({
10046
10047
  cookie: { user_session_id },
10047
10048
  params: { organizationId },
10048
- query: { RelayState, SAMLRequest, SAMLResponse },
10049
+ query: {
10050
+ RelayState,
10051
+ SAMLRequest,
10052
+ SAMLResponse,
10053
+ SigAlg,
10054
+ Signature
10055
+ },
10049
10056
  redirect,
10050
10057
  request,
10051
10058
  status,
@@ -10056,11 +10063,15 @@ var samlSsoRoutes = ({
10056
10063
  return status("Not Found", "No SAML connection is configured for this organization");
10057
10064
  }
10058
10065
  const sloUrl = sloUrlFor(request.url, organizationId);
10066
+ const signedQueryString = new URL(request.url).search.replace(/^\?/, "");
10059
10067
  if (isNonEmptyString(SAMLResponse)) {
10060
10068
  const responseSettled = await settle(samlAdapter.validateLogoutResponse?.({
10061
10069
  connection,
10062
10070
  relayState: RelayState,
10063
10071
  samlResponse: SAMLResponse,
10072
+ signature: Signature,
10073
+ signatureAlgorithm: SigAlg,
10074
+ signedQueryString,
10064
10075
  sloUrl
10065
10076
  }) ?? Promise.resolve());
10066
10077
  if (!("error" in responseSettled)) {
@@ -10083,6 +10094,9 @@ var samlSsoRoutes = ({
10083
10094
  connection,
10084
10095
  relayState: RelayState,
10085
10096
  samlRequest: SAMLRequest,
10097
+ signature: Signature,
10098
+ signatureAlgorithm: SigAlg,
10099
+ signedQueryString,
10086
10100
  sloUrl
10087
10101
  }));
10088
10102
  if ("error" in requestSettled) {
@@ -10118,7 +10132,9 @@ var samlSsoRoutes = ({
10118
10132
  query: t29.Object({
10119
10133
  RelayState: t29.Optional(t29.String()),
10120
10134
  SAMLRequest: t29.Optional(t29.String()),
10121
- SAMLResponse: t29.Optional(t29.String())
10135
+ SAMLResponse: t29.Optional(t29.String()),
10136
+ SigAlg: t29.Optional(t29.String()),
10137
+ Signature: t29.Optional(t29.String())
10122
10138
  })
10123
10139
  });
10124
10140
  };
@@ -25475,25 +25491,52 @@ var STANDARD_PROFILE_KEYS = new Set([
25475
25491
  "sessionIndex",
25476
25492
  "spNameQualifier"
25477
25493
  ]);
25478
- var createNodeSamlAdapter = async () => {
25494
+ var DEFAULT_NAMEID_FORMAT = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress";
25495
+ var siblingEndpoints = (urls) => {
25496
+ const acsUrl = urls.acsUrl ?? urls.sloUrl?.replace(/\/slo(\?|$)/, "/acs$1");
25497
+ const sloUrl = urls.sloUrl ?? urls.acsUrl?.replace(/\/acs(\?|$)/, "/slo$1");
25498
+ return { acsUrl, sloUrl };
25499
+ };
25500
+ var createNodeSamlAdapter = async (options = {}) => {
25479
25501
  const { SAML } = await import("@node-saml/node-saml");
25480
- const build = (acsUrl, connection) => {
25481
- const spEntityId = new URL(acsUrl).origin;
25502
+ const {
25503
+ signatureAlgorithm = "sha256",
25504
+ spCertificate,
25505
+ spPrivateKey
25506
+ } = options;
25507
+ const canSign = spPrivateKey !== undefined;
25508
+ const build = (connection, urls) => {
25509
+ const { acsUrl, sloUrl } = siblingEndpoints(urls);
25510
+ const baseUrl = acsUrl ?? sloUrl;
25511
+ if (baseUrl === undefined) {
25512
+ throw new Error("node-saml adapter requires an acsUrl or sloUrl to build a SAML client");
25513
+ }
25514
+ const spEntityId = new URL(baseUrl).origin;
25482
25515
  return new SAML({
25483
25516
  audience: spEntityId,
25484
- callbackUrl: acsUrl,
25517
+ callbackUrl: acsUrl ?? baseUrl,
25485
25518
  entryPoint: connection.config.idpSsoUrl,
25486
25519
  idpCert: connection.config.idpX509Cert,
25487
25520
  issuer: spEntityId,
25488
25521
  logoutUrl: connection.config.idpSloUrl,
25489
- wantAssertionsSigned: true
25522
+ wantAssertionsSigned: true,
25523
+ ...canSign ? {
25524
+ logoutCallbackUrl: sloUrl ?? baseUrl,
25525
+ privateKey: spPrivateKey,
25526
+ signatureAlgorithm
25527
+ } : {}
25490
25528
  });
25491
25529
  };
25492
- return {
25493
- createAuthorizationUrl: ({ acsUrl, connection, relayState }) => build(acsUrl, connection).getAuthorizeUrlAsync(relayState ?? "", undefined, {}),
25494
- getServiceProviderMetadata: ({ acsUrl, connection }) => build(acsUrl, connection).generateServiceProviderMetadata(null),
25530
+ const adapter = {
25531
+ createAuthorizationUrl: ({ acsUrl, connection, relayState }) => build(connection, { acsUrl }).getAuthorizeUrlAsync(relayState ?? "", undefined, {}),
25532
+ getServiceProviderMetadata: ({ acsUrl, connection, sloUrl }) => build(connection, {
25533
+ acsUrl,
25534
+ sloUrl
25535
+ }).generateServiceProviderMetadata(null, spCertificate ?? null),
25495
25536
  validateAssertion: async ({ acsUrl, connection, samlResponse }) => {
25496
- const { profile: profile2 } = await build(acsUrl, connection).validatePostResponseAsync({ SAMLResponse: samlResponse });
25537
+ const { profile: profile2 } = await build(connection, {
25538
+ acsUrl
25539
+ }).validatePostResponseAsync({ SAMLResponse: samlResponse });
25497
25540
  if (!profile2) {
25498
25541
  throw new Error("SAML response contained no assertion profile");
25499
25542
  }
@@ -25512,6 +25555,81 @@ var createNodeSamlAdapter = async () => {
25512
25555
  return result;
25513
25556
  }
25514
25557
  };
25558
+ if (!canSign)
25559
+ return adapter;
25560
+ return {
25561
+ ...adapter,
25562
+ createLogoutRequestUrl: ({
25563
+ connection,
25564
+ nameId,
25565
+ relayState,
25566
+ sessionIndex,
25567
+ sloUrl
25568
+ }) => {
25569
+ const saml = build(connection, { sloUrl });
25570
+ return saml.getLogoutUrlAsync({
25571
+ issuer: new URL(sloUrl).origin,
25572
+ nameID: nameId,
25573
+ nameIDFormat: DEFAULT_NAMEID_FORMAT,
25574
+ sessionIndex
25575
+ }, relayState ?? "", {});
25576
+ },
25577
+ createLogoutResponseUrl: ({
25578
+ connection,
25579
+ inResponseTo,
25580
+ nameId,
25581
+ relayState,
25582
+ sloUrl
25583
+ }) => {
25584
+ const saml = build(connection, { sloUrl });
25585
+ return saml.getLogoutResponseUrlAsync({
25586
+ ID: inResponseTo,
25587
+ issuer: new URL(sloUrl).origin,
25588
+ nameID: nameId ?? "",
25589
+ nameIDFormat: DEFAULT_NAMEID_FORMAT
25590
+ }, relayState ?? "", {}, true);
25591
+ },
25592
+ validateLogoutRequest: async ({
25593
+ connection,
25594
+ relayState,
25595
+ samlRequest,
25596
+ signature,
25597
+ signatureAlgorithm: sigAlg,
25598
+ signedQueryString,
25599
+ sloUrl
25600
+ }) => {
25601
+ const saml = build(connection, { sloUrl });
25602
+ const { profile: profile2 } = await saml.validateRedirectAsync({
25603
+ RelayState: relayState,
25604
+ SAMLRequest: samlRequest,
25605
+ SigAlg: sigAlg,
25606
+ Signature: signature
25607
+ }, signedQueryString ?? "");
25608
+ return {
25609
+ nameId: profile2?.nameID,
25610
+ relayState,
25611
+ requestId: profile2?.ID,
25612
+ sessionIndex: profile2?.sessionIndex
25613
+ };
25614
+ },
25615
+ validateLogoutResponse: async ({
25616
+ connection,
25617
+ relayState,
25618
+ samlResponse,
25619
+ signature,
25620
+ signatureAlgorithm: sigAlg,
25621
+ signedQueryString,
25622
+ sloUrl
25623
+ }) => {
25624
+ const saml = build(connection, { sloUrl });
25625
+ await saml.validateRedirectAsync({
25626
+ RelayState: relayState,
25627
+ SAMLResponse: samlResponse,
25628
+ SigAlg: sigAlg,
25629
+ Signature: signature
25630
+ }, signedQueryString ?? "");
25631
+ }
25632
+ };
25515
25633
  };
25516
25634
  // src/sso/inMemorySamlServiceProviderStore.ts
25517
25635
  var createInMemorySamlServiceProviderStore = () => {
@@ -25905,7 +26023,7 @@ var auth = async ({
25905
26023
  const auditedOnCallbackSuccess = auditEmit ? composeCallbackAudit(onCallbackSuccess, auditEmit) : onCallbackSuccess;
25906
26024
  const auditedOnRevocationSuccess = auditEmit ? composeRevocationAudit(onRevocationSuccess, auditEmit) : onRevocationSuccess;
25907
26025
  const auditedOnSignOut = auditEmit ? composeSignOutAudit(onSignOut, auditEmit) : onSignOut;
25908
- return new Elysia39().use(sessionCleanup({
26026
+ const composedAuth = new Elysia39().use(sessionCleanup({
25909
26027
  authSessionStore,
25910
26028
  cleanupIntervalMs,
25911
26029
  maxSessions,
@@ -26000,6 +26118,7 @@ var auth = async ({
26000
26118
  ...htmx,
26001
26119
  authSessionStore
26002
26120
  }) : new Elysia39);
26121
+ return composedAuth;
26003
26122
  };
26004
26123
  export {
26005
26124
  writeWarrant,
@@ -26434,5 +26553,5 @@ export {
26434
26553
  AuthIdentityConflictError
26435
26554
  };
26436
26555
 
26437
- //# debugId=CF175090287D988A64756E2164756E21
26556
+ //# debugId=85B7840BC5CF820764756E2164756E21
26438
26557
  //# sourceMappingURL=index.js.map