@rodit/rodit-auth-be 9.17.0 → 9.17.1

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/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  All notable changes to `@rodit/rodit-auth-be` are documented here.
4
4
 
5
+ ## [9.17.1] — 2026-10-20
6
+
7
+ ### Fixed
8
+
9
+ - **Login challenge max-age:** `validateTimestamp` again rejects challenges older
10
+ than `API_DEFAULT_OPTIONS.TIMESTAMP_MAX_AGE` (default 300s). Stale captured
11
+ `POST /api/login` bodies can no longer mint session JWTs indefinitely.
12
+ `verify_peer_rodit` passes the configured max age into the check.
13
+
5
14
  ## [9.17.0] — 2026-10-06
6
15
 
7
16
  ### Fixed
package/README.md CHANGED
@@ -4,7 +4,7 @@ Node.js / Express SDK for RODiT-based mutual authentication, authorization, sess
4
4
 
5
5
  **npm:** [https://www.npmjs.com/package/@rodit/rodit-auth-be](https://www.npmjs.com/package/@rodit/rodit-auth-be)
6
6
  **Monorepo:** [discernible-io/rodit-sdk](https://github.com/discernible-io/rodit-sdk) (this directory)
7
- **Version:** 9.17.0 · **License:** Proprietary · **Author:** Discernible IO
7
+ **Version:** 9.17.1 · **License:** Proprietary · **Author:** Discernible IO
8
8
 
9
9
  ## Production deployments
10
10
 
package/index.js CHANGED
@@ -1162,7 +1162,7 @@ class RoditClient {
1162
1162
 
1163
1163
  switch (errorCode) {
1164
1164
  case 'LOGIN_CHALLENGE_TIMESTAMP_INVALID':
1165
- errorMessage += '\n→ [CLIENT REJECTED] The login challenge timestamp is invalid or too far in the future. Use timestamp and timestamp_iso from one GET /api/login/timestamp call and check your system clock.';
1165
+ errorMessage += '\n→ [CLIENT REJECTED] The login challenge timestamp is invalid, too far in the future, or older than the allowed max age. Fetch a fresh timestamp and timestamp_iso from GET /api/login/timestamp and check your system clock.';
1166
1166
  break;
1167
1167
  case 'RODIT_NOT_FOUND':
1168
1168
  errorMessage += '\n→ [CLIENT REJECTED] The RODiT was not found on the blockchain. Verify the RODiT ID is correct.';
@@ -27,6 +27,7 @@ const {
27
27
  buildLoginSigningMessageBytes,
28
28
  tryConsumeLoginNonce,
29
29
  } = require("./login-nonce");
30
+ const config = require("../../services/configsdk");
30
31
 
31
32
  async function verify_rodit_ownership(
32
33
  peerroditid,
@@ -730,17 +731,26 @@ async function verify_rodit_ownership(
730
731
  }
731
732
 
732
733
  /**
733
- * Validates that a timestamp is not in the future
734
- *
734
+ * Validates that a login challenge timestamp is within skew and max-age bounds.
735
+ *
735
736
  * @param {number} timestamp - Unix timestamp in seconds
736
- * @param {number} maxAgeSeconds - Maximum age in seconds (not used, kept for backward compatibility)
737
+ * @param {number} [maxAgeSeconds] - Maximum challenge age in seconds (defaults to API_DEFAULT_OPTIONS.TIMESTAMP_MAX_AGE)
737
738
  * @returns {Promise<boolean>} True if timestamp is valid, false otherwise
738
739
  */
739
- async function validateTimestamp(timestamp, maxAgeSeconds = 300) {
740
+ async function validateTimestamp(timestamp, maxAgeSeconds) {
740
741
  const requestId = ulid();
741
742
  const currentTime = Math.floor(Date.now() / 1000);
742
743
  const timeDifference = currentTime - timestamp;
743
-
744
+ const configuredMaxAge = Number(
745
+ config.get("API_DEFAULT_OPTIONS.TIMESTAMP_MAX_AGE", 300)
746
+ );
747
+ const resolvedMaxAge =
748
+ Number.isFinite(maxAgeSeconds) && maxAgeSeconds > 0
749
+ ? maxAgeSeconds
750
+ : Number.isFinite(configuredMaxAge) && configuredMaxAge > 0
751
+ ? configuredMaxAge
752
+ : 300;
753
+
744
754
  // Check if timestamp is in the future (with small buffer for clock skew)
745
755
  if (timestamp > currentTime + 30) {
746
756
  logger.warn("Authentication rejected: timestamp is in the future", {
@@ -753,10 +763,20 @@ async function verify_rodit_ownership(
753
763
  });
754
764
  return false;
755
765
  }
756
-
757
- // We've removed the timestamp age check as it's not needed with our comprehensive validation system
758
- // The system already validates tokens through other means
759
-
766
+
767
+ if (timeDifference > resolvedMaxAge) {
768
+ logger.warn("Authentication rejected: timestamp too old", {
769
+ component: "RoditAuth",
770
+ method: "validateTimestamp",
771
+ requestId,
772
+ timestamp,
773
+ currentTime,
774
+ maxAgeSeconds: resolvedMaxAge,
775
+ ageSeconds: timeDifference,
776
+ });
777
+ return false;
778
+ }
779
+
760
780
  return true;
761
781
  }
762
782
 
@@ -833,7 +853,13 @@ async function verify_rodit_ownership(
833
853
  });
834
854
 
835
855
  try {
836
- const timestampValid = await validateTimestamp(peertimestamp);
856
+ const timestampMaxAge = Number(
857
+ config.get("API_DEFAULT_OPTIONS.TIMESTAMP_MAX_AGE", 300)
858
+ );
859
+ const timestampValid = await validateTimestamp(
860
+ peertimestamp,
861
+ timestampMaxAge
862
+ );
837
863
 
838
864
  if (!timestampValid) {
839
865
  logger.warn("Invalid timestamp, aborting RODiT verification", {
@@ -843,13 +869,14 @@ async function verify_rodit_ownership(
843
869
  roditId: peerroditid,
844
870
  timestamp: peertimestamp,
845
871
  currentTime: Math.floor(Date.now() / 1000),
872
+ maxAgeSeconds: timestampMaxAge,
846
873
  });
847
874
  return {
848
875
  peer_rodit: null,
849
876
  goodrodit: false,
850
877
  failureReason: "LOGIN_CHALLENGE_TIMESTAMP_INVALID",
851
878
  failureMessage:
852
- "Login challenge timestamp invalid: the Unix `timestamp` from your POST body is too far in the future relative to server time (use the `timestamp` from the same GET /api/login/timestamp response as your login signing payload; check clock skew)."
879
+ "Login challenge timestamp invalid: the Unix `timestamp` from your POST body is too far in the future or older than the allowed max age relative to server time (use a fresh `timestamp` from GET /api/login/timestamp for the same login signing payload; check clock skew)."
853
880
  };
854
881
  }
855
882
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rodit/rodit-auth-be",
3
- "version": "9.17.0",
3
+ "version": "9.17.1",
4
4
  "description": "RODiT-based authentication system for Express.js applications",
5
5
  "main": "index.js",
6
6
  "exports": {