@rodit/rodit-auth-be 9.15.0 → 9.16.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/CHANGELOG.md +13 -0
- package/README.md +17 -5
- package/index.js +0 -6
- package/lib/auth/authentication.js +0 -140
- package/lib/auth/tokenservice.js +1 -45
- package/package.json +7 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to `@rodit/rodit-auth-be` are documented here.
|
|
4
4
|
|
|
5
|
+
## [9.16.0] — 2026-09-14
|
|
6
|
+
|
|
7
|
+
### Removed
|
|
8
|
+
|
|
9
|
+
- **`verify_rodit_isactive`** — DNS TXT revocation check
|
|
10
|
+
(`<token_id>.revoked.<domain>`). The function short-circuited with an
|
|
11
|
+
unconditional `return true` while debugging, so its body was unreachable and
|
|
12
|
+
no RODiT could be rejected as revoked. Removed along with its call sites in
|
|
13
|
+
`verify_peer_rodit` and `thorough_validate_jwt_token_be`, and the
|
|
14
|
+
`RODIT_REVOKED` / `SERVER_RODIT_REVOKED` failure codes they emitted.
|
|
15
|
+
No behavior change; the SDK now has no revocation check.
|
|
16
|
+
`verify_rodit_isactive_fe` in `@rodit/rodit-auth-fe` is unaffected.
|
|
17
|
+
|
|
5
18
|
## [9.15.0] — 2026-08-11
|
|
6
19
|
|
|
7
20
|
### Added
|
package/README.md
CHANGED
|
@@ -1,10 +1,22 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @rodit/rodit-auth-be
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Node.js / Express SDK for RODiT-based mutual authentication, authorization, session management, and webhooks.
|
|
4
4
|
|
|
5
|
-
**
|
|
6
|
-
**
|
|
7
|
-
**Author:** Discernible IO
|
|
5
|
+
**npm:** [https://www.npmjs.com/package/@rodit/rodit-auth-be](https://www.npmjs.com/package/@rodit/rodit-auth-be)
|
|
6
|
+
**Monorepo:** [discernible-io/rodit-sdk](https://github.com/discernible-io/rodit-sdk) (this directory)
|
|
7
|
+
**Version:** 9.15.0 · **License:** Proprietary · **Author:** Discernible IO
|
|
8
|
+
|
|
9
|
+
## Production deployments
|
|
10
|
+
|
|
11
|
+
This package is the server runtime behind RODiT-powered APIs, including:
|
|
12
|
+
|
|
13
|
+
| Deployment | Role |
|
|
14
|
+
|------------|------|
|
|
15
|
+
| [api.identyclaw.com](https://api.identyclaw.com) | IdentyClaw platform API ([source: api-idc](https://github.com/discernible-io/api-idc)) |
|
|
16
|
+
| [api.lastcradle.io](https://api.lastcradle.io) | Last Cradle family API |
|
|
17
|
+
| Custom / federated APIs | Same SDK; sibling APIs in one token family support [federated login](#federated-login-same-family-different-api-url) |
|
|
18
|
+
|
|
19
|
+
Browser and wallet clients for these APIs use the companion package [`@rodit/rodit-auth-fe`](https://www.npmjs.com/package/@rodit/rodit-auth-fe).
|
|
8
20
|
|
|
9
21
|
**Login `POST` /api/login:** Use **`accountid`** (or **`roditid`**), **`timestamp`**, and **`base64url_signature`**. Sign UTF-8 bytes of `identifier + timestamp_iso`, and reject deprecated keys such as **`signature`** and **`account_id`**. See [CHANGELOG.md](./CHANGELOG.md).
|
|
10
22
|
|
package/index.js
CHANGED
|
@@ -1145,9 +1145,6 @@ class RoditClient {
|
|
|
1145
1145
|
case 'RODIT_NOT_LIVE':
|
|
1146
1146
|
errorMessage += '\n→ [CLIENT REJECTED] Your RODiT is expired or not yet valid. Check the validity period.';
|
|
1147
1147
|
break;
|
|
1148
|
-
case 'RODIT_REVOKED':
|
|
1149
|
-
errorMessage += '\n→ [CLIENT REJECTED] Your RODiT has been revoked and is no longer valid.';
|
|
1150
|
-
break;
|
|
1151
1148
|
case 'SMART_CONTRACT_NOT_TRUSTED':
|
|
1152
1149
|
errorMessage += '\n→ [CLIENT REJECTED] The smart contract that issued your RODiT is not trusted by this server.';
|
|
1153
1150
|
break;
|
|
@@ -1160,9 +1157,6 @@ class RoditClient {
|
|
|
1160
1157
|
case 'SERVER_RODIT_NOT_LIVE':
|
|
1161
1158
|
errorMessage += '\n→ [SERVER REJECTED] The server\'s RODiT is expired or not yet valid. Contact the server administrator.';
|
|
1162
1159
|
break;
|
|
1163
|
-
case 'SERVER_RODIT_REVOKED':
|
|
1164
|
-
errorMessage += '\n→ [SERVER REJECTED] The server\'s RODiT has been revoked. Contact the server administrator.';
|
|
1165
|
-
break;
|
|
1166
1160
|
case 'SERVER_SMART_CONTRACT_NOT_TRUSTED':
|
|
1167
1161
|
errorMessage += '\n→ [SERVER REJECTED] The server\'s issuing smart contract is not trusted by your client. Update your trust configuration.';
|
|
1168
1162
|
break;
|
|
@@ -993,32 +993,6 @@ async function verify_rodit_ownership(
|
|
|
993
993
|
};
|
|
994
994
|
}
|
|
995
995
|
|
|
996
|
-
const activeStart = Date.now();
|
|
997
|
-
const isActive = await verify_rodit_isactive(
|
|
998
|
-
peer_rodit.token_id,
|
|
999
|
-
config_own_rodit.own_rodit.metadata.subjectuniqueidentifier_url
|
|
1000
|
-
);
|
|
1001
|
-
const activeDuration = Date.now() - activeStart;
|
|
1002
|
-
|
|
1003
|
-
logger.debug("Active verification completed", {
|
|
1004
|
-
requestId,
|
|
1005
|
-
activeDuration,
|
|
1006
|
-
isActive,
|
|
1007
|
-
});
|
|
1008
|
-
|
|
1009
|
-
if (!isActive) {
|
|
1010
|
-
logger.warn("RODiT active verification failed", {
|
|
1011
|
-
requestId,
|
|
1012
|
-
roditId: peerroditid,
|
|
1013
|
-
});
|
|
1014
|
-
return {
|
|
1015
|
-
peer_rodit,
|
|
1016
|
-
goodrodit: false,
|
|
1017
|
-
failureReason: "RODIT_REVOKED",
|
|
1018
|
-
failureMessage: "RODiT has been revoked"
|
|
1019
|
-
};
|
|
1020
|
-
}
|
|
1021
|
-
|
|
1022
996
|
const trustedStart = Date.now();
|
|
1023
997
|
const isTrusted = await verify_rodit_istrusted_issuingsmartcontract(
|
|
1024
998
|
config_own_rodit.own_rodit.metadata.subjectuniqueidentifier_url
|
|
@@ -1241,119 +1215,6 @@ async function verify_rodit_ownership(
|
|
|
1241
1215
|
}
|
|
1242
1216
|
}
|
|
1243
1217
|
|
|
1244
|
-
async function verify_rodit_isactive(tokenId, ownsubjectuniqueidentifier_url) {
|
|
1245
|
-
const requestId = ulid();
|
|
1246
|
-
const startTime = Date.now();
|
|
1247
|
-
|
|
1248
|
-
// WHILE DEBUGGING TEMPORARY FIX DO NOT REMOVE THIS LINE EVER WITHOUT PERMISSION
|
|
1249
|
-
return true;
|
|
1250
|
-
|
|
1251
|
-
logger.debug("Checking RODiT activity status", {
|
|
1252
|
-
component: "RoditAuth",
|
|
1253
|
-
method: "verify_rodit_isactive",
|
|
1254
|
-
requestId,
|
|
1255
|
-
tokenId,
|
|
1256
|
-
subjectUrl: ownsubjectuniqueidentifier_url,
|
|
1257
|
-
});
|
|
1258
|
-
|
|
1259
|
-
const domainandextensionRegex =
|
|
1260
|
-
/(?:https?:\/\/)?(?:www\.)?([a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+)/i;
|
|
1261
|
-
|
|
1262
|
-
const match = ownsubjectuniqueidentifier_url.match(domainandextensionRegex);
|
|
1263
|
-
|
|
1264
|
-
if (match) {
|
|
1265
|
-
const domainandextension = match[1];
|
|
1266
|
-
const revokingDnsEntry = `${tokenId}.revoked.${domainandextension}`;
|
|
1267
|
-
|
|
1268
|
-
logger.debug("Checking DNS revocation entry", {
|
|
1269
|
-
requestId,
|
|
1270
|
-
domain: domainandextension,
|
|
1271
|
-
revokingDnsEntry,
|
|
1272
|
-
});
|
|
1273
|
-
|
|
1274
|
-
try {
|
|
1275
|
-
const dnsStart = Date.now();
|
|
1276
|
-
const resolver = new Resolver();
|
|
1277
|
-
await resolver.resolveTxt(revokingDnsEntry);
|
|
1278
|
-
const dnsDuration = Date.now() - dnsStart;
|
|
1279
|
-
const totalDuration = Date.now() - startTime;
|
|
1280
|
-
|
|
1281
|
-
logger.info("RODiT revocation found", {
|
|
1282
|
-
component: "AuthServices",
|
|
1283
|
-
method: "verify_rodit_isactive",
|
|
1284
|
-
requestId,
|
|
1285
|
-
duration: totalDuration,
|
|
1286
|
-
dnsDuration,
|
|
1287
|
-
tokenId,
|
|
1288
|
-
domain: domainandextension,
|
|
1289
|
-
revokingDnsEntry,
|
|
1290
|
-
isActive: false,
|
|
1291
|
-
});
|
|
1292
|
-
|
|
1293
|
-
// Add metrics for revoked tokens
|
|
1294
|
-
logger.metric &&
|
|
1295
|
-
logger.metric("rodit_revocation_checks", totalDuration, {
|
|
1296
|
-
result: "revoked",
|
|
1297
|
-
token_id: tokenId,
|
|
1298
|
-
});
|
|
1299
|
-
|
|
1300
|
-
return false;
|
|
1301
|
-
} catch (error) {
|
|
1302
|
-
// DNS error usually means no revocation entry found, which is good
|
|
1303
|
-
const dnsDuration = Date.now() - dnsStart || 0;
|
|
1304
|
-
const totalDuration = Date.now() - startTime;
|
|
1305
|
-
|
|
1306
|
-
logger.debug("No revocation found for RODiT", {
|
|
1307
|
-
requestId,
|
|
1308
|
-
dnsDuration,
|
|
1309
|
-
tokenId,
|
|
1310
|
-
error: error.code,
|
|
1311
|
-
});
|
|
1312
|
-
|
|
1313
|
-
logger.info("RODiT is active", {
|
|
1314
|
-
component: "AuthServices",
|
|
1315
|
-
method: "verify_rodit_isactive",
|
|
1316
|
-
requestId,
|
|
1317
|
-
duration: totalDuration,
|
|
1318
|
-
dnsDuration,
|
|
1319
|
-
tokenId,
|
|
1320
|
-
domain: domainandextension,
|
|
1321
|
-
isActive: true,
|
|
1322
|
-
});
|
|
1323
|
-
|
|
1324
|
-
// Add metrics for active tokens
|
|
1325
|
-
logger.metric &&
|
|
1326
|
-
logger.metric("rodit_revocation_checks", totalDuration, {
|
|
1327
|
-
result: "active",
|
|
1328
|
-
token_id: tokenId,
|
|
1329
|
-
});
|
|
1330
|
-
|
|
1331
|
-
return true;
|
|
1332
|
-
}
|
|
1333
|
-
} else {
|
|
1334
|
-
const duration = Date.now() - startTime;
|
|
1335
|
-
|
|
1336
|
-
logger.warn("Unable to parse domain from URL", {
|
|
1337
|
-
component: "AuthServices",
|
|
1338
|
-
method: "verify_rodit_isactive",
|
|
1339
|
-
requestId,
|
|
1340
|
-
duration,
|
|
1341
|
-
tokenId,
|
|
1342
|
-
subjectUrl: ownsubjectuniqueidentifier_url,
|
|
1343
|
-
});
|
|
1344
|
-
|
|
1345
|
-
// Add metrics for parsing errors
|
|
1346
|
-
logger.metric &&
|
|
1347
|
-
logger.metric("rodit_revocation_checks", duration, {
|
|
1348
|
-
result: "parse_error",
|
|
1349
|
-
token_id: tokenId,
|
|
1350
|
-
});
|
|
1351
|
-
|
|
1352
|
-
// Default to allowing the token if domain parsing fails
|
|
1353
|
-
return true;
|
|
1354
|
-
}
|
|
1355
|
-
}
|
|
1356
|
-
|
|
1357
1218
|
async function verify_rodit_istrusted_issuingsmartcontract(
|
|
1358
1219
|
ownsubjectuniqueidentifier_url
|
|
1359
1220
|
) {
|
|
@@ -1963,7 +1824,6 @@ module.exports = {
|
|
|
1963
1824
|
resolve_peer_rodit_for_login,
|
|
1964
1825
|
verify_peer_rodit,
|
|
1965
1826
|
validateTimestamp,
|
|
1966
|
-
verify_rodit_isactive,
|
|
1967
1827
|
verify_rodit_isamatch,
|
|
1968
1828
|
verify_rodit_islive,
|
|
1969
1829
|
verify_rodit_istrusted_issuingsmartcontract,
|
package/lib/auth/tokenservice.js
CHANGED
|
@@ -2085,7 +2085,7 @@ async function thorough_validate_jwt_token_be(token, requestId = ulid()) {
|
|
|
2085
2085
|
// Starting verification with more detailed logging
|
|
2086
2086
|
logger.debug("Starting verification checks", {
|
|
2087
2087
|
requestId,
|
|
2088
|
-
checks: ["match", "live", "
|
|
2088
|
+
checks: ["match", "live", "trusted"],
|
|
2089
2089
|
serviceProviderId: config_own_rodit.own_rodit.metadata.serviceprovider_id,
|
|
2090
2090
|
});
|
|
2091
2091
|
|
|
@@ -2093,7 +2093,6 @@ async function thorough_validate_jwt_token_be(token, requestId = ulid()) {
|
|
|
2093
2093
|
const {
|
|
2094
2094
|
verify_rodit_isamatch,
|
|
2095
2095
|
verify_rodit_islive,
|
|
2096
|
-
verify_rodit_isactive,
|
|
2097
2096
|
verify_rodit_istrusted_issuingsmartcontract
|
|
2098
2097
|
} = require("./authentication");
|
|
2099
2098
|
|
|
@@ -2188,49 +2187,6 @@ async function thorough_validate_jwt_token_be(token, requestId = ulid()) {
|
|
|
2188
2187
|
};
|
|
2189
2188
|
}
|
|
2190
2189
|
|
|
2191
|
-
// Perform active verification
|
|
2192
|
-
const activeStart = performance.now();
|
|
2193
|
-
const isActive = await verify_rodit_isactive(
|
|
2194
|
-
peer_rodit.token_id,
|
|
2195
|
-
config_own_rodit.own_rodit.metadata.subjectuniqueidentifier_url
|
|
2196
|
-
);
|
|
2197
|
-
const activeDuration = performance.now() - activeStart;
|
|
2198
|
-
|
|
2199
|
-
logger.debug("Active verification completed", {
|
|
2200
|
-
requestId,
|
|
2201
|
-
activeDuration,
|
|
2202
|
-
isActive,
|
|
2203
|
-
tokenId: peer_rodit.token_id,
|
|
2204
|
-
url: config_own_rodit.own_rodit.metadata.subjectuniqueidentifier_url,
|
|
2205
|
-
});
|
|
2206
|
-
|
|
2207
|
-
if (!isActive) {
|
|
2208
|
-
logger.warn("RODiT active verification failed", {
|
|
2209
|
-
component: "JwtAuth",
|
|
2210
|
-
method: "thorough_validate_jwt_token_be",
|
|
2211
|
-
requestId,
|
|
2212
|
-
duration: performance.now() - startTime,
|
|
2213
|
-
tokenId: peer_rodit.token_id,
|
|
2214
|
-
url: config_own_rodit.own_rodit.metadata.subjectuniqueidentifier_url,
|
|
2215
|
-
});
|
|
2216
|
-
|
|
2217
|
-
// Add metrics for failed active verification
|
|
2218
|
-
logger.metric &&
|
|
2219
|
-
logger.metric("jwt_thorough_validation", performance.now() - startTime, {
|
|
2220
|
-
result: "active_failed",
|
|
2221
|
-
token_jti: token.jti || "unknown",
|
|
2222
|
-
peer_rodit_id: peer_rodit.token_id,
|
|
2223
|
-
});
|
|
2224
|
-
|
|
2225
|
-
return {
|
|
2226
|
-
isValid: false,
|
|
2227
|
-
notAfter: null,
|
|
2228
|
-
error: "RODiT active verification failed",
|
|
2229
|
-
errorCode: "SERVER_RODIT_REVOKED",
|
|
2230
|
-
errorMessage: "Server's RODiT has been revoked"
|
|
2231
|
-
};
|
|
2232
|
-
}
|
|
2233
|
-
|
|
2234
2190
|
// Perform trusted verification
|
|
2235
2191
|
const trustedStart = performance.now();
|
|
2236
2192
|
const isTrusted = await verify_rodit_istrusted_issuingsmartcontract(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rodit/rodit-auth-be",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.16.0",
|
|
4
4
|
"description": "RODiT-based authentication system for Express.js applications",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"exports": {
|
|
@@ -46,8 +46,13 @@
|
|
|
46
46
|
},
|
|
47
47
|
"repository": {
|
|
48
48
|
"type": "git",
|
|
49
|
-
"url": "https://github.com/discernible-io/rodit-
|
|
49
|
+
"url": "git+https://github.com/discernible-io/rodit-sdk.git",
|
|
50
|
+
"directory": "rodit-auth-be"
|
|
50
51
|
},
|
|
52
|
+
"bugs": {
|
|
53
|
+
"url": "https://github.com/discernible-io/rodit-sdk/issues"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://github.com/discernible-io/rodit-sdk/tree/main/rodit-auth-be#readme",
|
|
51
56
|
"publishConfig": {
|
|
52
57
|
"access": "public"
|
|
53
58
|
},
|