@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 +9 -0
- package/README.md +1 -1
- package/index.js +1 -1
- package/lib/auth/authentication.js +38 -11
- package/package.json +1 -1
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.
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
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
|
-
|
|
758
|
-
|
|
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
|
|
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
|
|
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
|
|