@rodit/rodit-auth-be 9.11.14 → 9.11.16

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.
@@ -25,9 +25,8 @@ logger.infoWithContext("TokenService using SessionManager instance", {
25
25
  timestamp: new Date().toISOString()
26
26
  });
27
27
  const stateManager = require('../blockchain/statemanager');
28
- const {
29
- nearorg_rpc_tokenfromroditid,
30
- nearorg_rpc_tokensfromaccountid,
28
+ const {
29
+ nearorg_rpc_tokenfromroditid,
31
30
  nearorg_rpc_fetchpublickeybytes,
32
31
  } = require("../blockchain/blockchainservice");
33
32
 
@@ -62,6 +61,15 @@ function isCanonicalBase64Url(value) {
62
61
  }
63
62
  }
64
63
 
64
+ /** Login peer RODiT token id embedded in JWT sub (`{sp};sub={peerTokenId}`). */
65
+ function extractLoginPeerRoditIdFromSub(sub) {
66
+ if (!sub || typeof sub !== "string") {
67
+ return "";
68
+ }
69
+ const subParts = sub.split(";sub=");
70
+ return subParts.length > 1 ? subParts[1] : "";
71
+ }
72
+
65
73
  function parseRoditJwtDurationSeconds(metadata) {
66
74
  const parsed = parseInt(metadata?.jwt_duration, 10);
67
75
  if (Number.isFinite(parsed) && parsed > 0) {
@@ -1727,20 +1735,30 @@ function resolveCredentialExpirationUnix(now, sessionExpiration, own_rodit) {
1727
1735
  const startTime = Date.now();
1728
1736
 
1729
1737
  try {
1738
+ const extractedSub = extractLoginPeerRoditIdFromSub(token.sub);
1739
+ if (!extractedSub) {
1740
+ const duration = Date.now() - startTime;
1741
+ logger.warn("Brief token validation failed - missing login peer in sub", {
1742
+ component: "JwtAuth",
1743
+ method: "brief_validate_jwt_token_be",
1744
+ requestId,
1745
+ duration,
1746
+ tokenJti: token.jti,
1747
+ tokenSub: token.sub,
1748
+ });
1749
+ logger.metric("jwt_brief_validation", duration, {
1750
+ result: "failure",
1751
+ token_jti: token.jti || "unknown",
1752
+ id_match: "false",
1753
+ });
1754
+ return { isValid: false, notAfter: null };
1755
+ }
1756
+
1730
1757
  const tokenFetchStart = Date.now();
1731
- const peer_rodit =
1732
- await nearorg_rpc_tokensfromaccountid(
1733
-
1734
- token.aud
1735
- );
1758
+ const peer_rodit = await nearorg_rpc_tokenfromroditid(extractedSub);
1736
1759
  const tokenFetchDuration = Date.now() - tokenFetchStart;
1737
1760
 
1738
- const subParts = token.sub.split(";sub=");
1739
- const extractedSub = subParts.length > 1 ? subParts[1] : "";
1740
-
1741
- const isValid =
1742
- peer_rodit.token_id === extractedSub &&
1743
- peer_rodit.owner_id === token.aud;
1761
+ const isValid = !!peer_rodit?.token_id && peer_rodit.token_id === extractedSub;
1744
1762
 
1745
1763
  const totalDuration = Date.now() - startTime;
1746
1764
 
@@ -1753,6 +1771,7 @@ function resolveCredentialExpirationUnix(now, sessionExpiration, own_rodit) {
1753
1771
  tokenFetchDuration,
1754
1772
  tokenJti: token.jti,
1755
1773
  peerRoditId: peer_rodit.token_id,
1774
+ extractedSub,
1756
1775
  notAfter: peer_rodit.metadata.not_after,
1757
1776
  });
1758
1777
 
@@ -1769,26 +1788,23 @@ function resolveCredentialExpirationUnix(now, sessionExpiration, own_rodit) {
1769
1788
  duration: totalDuration,
1770
1789
  tokenFetchDuration,
1771
1790
  tokenJti: token.jti,
1772
- peerRoditId: peer_rodit.token_id,
1791
+ peerRoditId: peer_rodit?.token_id || null,
1773
1792
  extractedSub,
1774
1793
  tokenAud: token.aud,
1775
- peerRoditOwnerId: peer_rodit.owner_id,
1776
- idMatch: peer_rodit.token_id === extractedSub,
1777
- ownerMatch: peer_rodit.owner_id === token.aud,
1794
+ idMatch: peer_rodit?.token_id === extractedSub,
1778
1795
  });
1779
1796
 
1780
1797
  // Add metrics for failed brief validations
1781
1798
  logger.metric("jwt_brief_validation", totalDuration, {
1782
1799
  result: "failure",
1783
1800
  token_jti: token.jti || "unknown",
1784
- id_match: peer_rodit.token_id === extractedSub ? "true" : "false",
1785
- owner_match: peer_rodit.owner_id === token.aud ? "true" : "false",
1801
+ id_match: peer_rodit?.token_id === extractedSub ? "true" : "false",
1786
1802
  });
1787
1803
  }
1788
1804
 
1789
1805
  return {
1790
1806
  isValid,
1791
- notAfter: peer_rodit.metadata.not_after,
1807
+ notAfter: peer_rodit?.metadata?.not_after ?? null,
1792
1808
  };
1793
1809
  } catch (error) {
1794
1810
  const duration = Date.now() - startTime;
@@ -1831,14 +1847,32 @@ async function thorough_validate_jwt_token_be(token, requestId = ulid()) {
1831
1847
  const startTime = performance.now(); // More precise timing measurement
1832
1848
 
1833
1849
  try {
1850
+ const extractedSub = extractLoginPeerRoditIdFromSub(token.sub);
1851
+ if (!extractedSub) {
1852
+ logger.warn("Thorough token validation failed - missing login peer in sub", {
1853
+ component: "JwtAuth",
1854
+ method: "thorough_validate_jwt_token_be",
1855
+ requestId,
1856
+ duration: performance.now() - startTime,
1857
+ tokenJti: token?.jti,
1858
+ tokenSub: token?.sub,
1859
+ });
1860
+ logger.metric &&
1861
+ logger.metric("jwt_thorough_validation", performance.now() - startTime, {
1862
+ result: "missing_login_peer_sub",
1863
+ token_jti: token.jti || "unknown",
1864
+ });
1865
+ return { isValid: false, notAfter: null };
1866
+ }
1867
+
1834
1868
  // Fetch configuration with better timing measurements
1835
1869
  const configStart = performance.now();
1836
1870
  const config_own_rodit = await stateManager.getConfigOwnRodit();
1837
1871
  const configDuration = performance.now() - configStart;
1838
1872
 
1839
- // Fetch peer RODiT with clearer logging
1873
+ // Fetch login peer RODiT (client identity from sub), not server passport (rodit_id claim)
1840
1874
  const tokenFetchStart = performance.now();
1841
- const peer_rodit = await nearorg_rpc_tokenfromroditid(token.rodit_id);
1875
+ const peer_rodit = await nearorg_rpc_tokenfromroditid(extractedSub);
1842
1876
  const tokenFetchDuration = performance.now() - tokenFetchStart;
1843
1877
 
1844
1878
  if (!peer_rodit) {
@@ -1846,7 +1880,7 @@ async function thorough_validate_jwt_token_be(token, requestId = ulid()) {
1846
1880
  component: "JwtAuth",
1847
1881
  requestId,
1848
1882
  duration: performance.now() - startTime,
1849
- tokenRoditId: token?.rodit_id,
1883
+ loginPeerRoditId: extractedSub,
1850
1884
  });
1851
1885
 
1852
1886
  // Add metrics for failed token fetch
@@ -2075,11 +2109,7 @@ async function thorough_validate_jwt_token_be(token, requestId = ulid()) {
2075
2109
  };
2076
2110
  }
2077
2111
 
2078
- // Extract subject and perform final validation
2079
- const subParts = token.sub.split(";sub=");
2080
- const extractedSub = subParts.length > 1 ? subParts[1] : "";
2081
-
2082
- logger.debug("Extracted subject from token", {
2112
+ logger.debug("Login peer identity check", {
2083
2113
  requestId,
2084
2114
  extractedSub,
2085
2115
  tokenSub: token.sub,
@@ -2088,10 +2118,8 @@ async function thorough_validate_jwt_token_be(token, requestId = ulid()) {
2088
2118
  tokenAud: token.aud,
2089
2119
  });
2090
2120
 
2091
- // Additional identity checks
2092
2121
  const idMatch = peer_rodit.token_id === extractedSub;
2093
- const ownerMatch = peer_rodit.owner_id === token.aud;
2094
- const isValid = idMatch && ownerMatch;
2122
+ const isValid = idMatch;
2095
2123
 
2096
2124
  const totalDuration = performance.now() - startTime;
2097
2125
 
@@ -2114,10 +2142,6 @@ async function thorough_validate_jwt_token_be(token, requestId = ulid()) {
2114
2142
  peer_rodit_id: peer_rodit.token_id,
2115
2143
  });
2116
2144
  } else {
2117
- const failedIdentityChecks = [];
2118
- if (!idMatch) failedIdentityChecks.push("token_id_mismatch");
2119
- if (!ownerMatch) failedIdentityChecks.push("owner_id_mismatch");
2120
-
2121
2145
  logger.warn("Token identity verification failed", {
2122
2146
  component: "JwtAuth",
2123
2147
  method: "thorough_validate_jwt_token_be",
@@ -2129,8 +2153,7 @@ async function thorough_validate_jwt_token_be(token, requestId = ulid()) {
2129
2153
  tokenAud: token.aud,
2130
2154
  peerRoditOwnerId: peer_rodit.owner_id,
2131
2155
  idMatch,
2132
- ownerMatch,
2133
- failedIdentityChecks,
2156
+ failedIdentityChecks: ["token_id_mismatch"],
2134
2157
  });
2135
2158
 
2136
2159
  // Add metrics for identity mismatch with more details
@@ -2138,19 +2161,22 @@ async function thorough_validate_jwt_token_be(token, requestId = ulid()) {
2138
2161
  logger.metric("jwt_thorough_validation", totalDuration, {
2139
2162
  result: "identity_mismatch",
2140
2163
  token_jti: token.jti || "unknown",
2141
- id_match: idMatch ? "true" : "false",
2142
- owner_match: ownerMatch ? "true" : "false",
2143
- failed_checks: failedIdentityChecks.join(","),
2164
+ id_match: "false",
2165
+ failed_checks: "token_id_mismatch",
2144
2166
  peer_rodit_id: peer_rodit.token_id,
2145
2167
  });
2146
2168
  }
2147
2169
 
2170
+ const failedIdentityChecks = !isValid ? ["token_id_mismatch"] : [];
2171
+
2148
2172
  return {
2149
2173
  isValid,
2150
2174
  notAfter: peer_rodit.metadata.not_after,
2151
2175
  error: !isValid ? "Token identity verification failed" : undefined,
2152
2176
  errorCode: !isValid ? "SERVER_TOKEN_IDENTITY_MISMATCH" : undefined,
2153
- errorMessage: !isValid ? `Server token identity mismatch: ${failedIdentityChecks.join(", ")}` : undefined
2177
+ errorMessage: !isValid
2178
+ ? `Server token identity mismatch: ${failedIdentityChecks.join(", ")}`
2179
+ : undefined
2154
2180
  };
2155
2181
  } catch (error) {
2156
2182
  const duration = performance.now() - startTime;
@@ -2409,10 +2435,17 @@ async function thorough_validate_jwt_token_be(token, requestId = ulid()) {
2409
2435
 
2410
2436
 
2411
2437
  // Export the class directly (will be instantiated in rodit.js)
2412
- module.exports = {generate_jwt_token,base64url2jwk_public_key,
2438
+ module.exports = {
2439
+ generate_jwt_token,
2440
+ base64url2jwk_public_key,
2413
2441
  checkandrenew_jwt_token,
2414
2442
  thorough_validate_jwt_token_be,
2415
2443
  brief_validate_jwt_token_be,
2416
2444
  generate_jwt_token_fromtoken,
2417
- verify_jwt_token,validate_jwt_token_be, generate_session_termination_token
2445
+ verify_jwt_token,
2446
+ validate_jwt_token_be,
2447
+ generate_session_termination_token,
2448
+ parseRoditJwtDurationSeconds,
2449
+ resolveSessionExpirationUnix,
2450
+ resolveCredentialExpirationUnix,
2418
2451
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rodit/rodit-auth-be",
3
- "version": "9.11.14",
3
+ "version": "9.11.16",
4
4
  "description": "RODiT-based authentication system for Express.js applications",
5
5
  "main": "index.js",
6
6
  "exports": {