Skip to content

Commit 128e54e

Browse files
committed
fix: remove redundant SUBJECT_NOT_IN_CHAIN validation check
The check is already guaranteed by the combination of DIFFERENT_SUBJECTS, ROOT_KEY_SIGNATURE_MISSING, and ISSUER_AUDIENCE_MISMATCH + signature verification. Removing it simplifies the validation rules and unblocks delegated auth chains where the subject never appears as an issuer.
1 parent efd6332 commit 128e54e

File tree

3 files changed

+22
-12
lines changed

3 files changed

+22
-12
lines changed

src/validator/chain.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export const MISSING_PROOF = "proof is missing";
1717
export const NOT_BEFORE_BACKWARDS = "`not before` cannot move backwards";
1818
export const PROOFS_MUST_BE_DELEGATIONS = "proofs must be delegations";
1919
export const ROOT_KEY_SIGNATURE_MISSING = "root NUC is not signed by a root issuer";
20-
export const SUBJECT_NOT_IN_CHAIN = "subject not in chain";
2120
export const TOO_MANY_PROOFS = "up to one `prf` in a token is allowed";
2221
export const UNCHAINED_PROOFS = "extra proofs not part of chain provided";
2322

@@ -63,15 +62,6 @@ export function validatePayloadChain(
6362
validatePolicyProperties(payload.pol, config);
6463
}
6564
}
66-
67-
if (payloads.length >= 2) {
68-
const subject = payloads[0].sub;
69-
const isSubjectAnIssuer = payloads.some((p) => Did.areEqual(p.iss, subject));
70-
if (!isSubjectAnIssuer) {
71-
Log.debug({ subject, issuers: payloads.map((p) => p.iss) }, SUBJECT_NOT_IN_CHAIN);
72-
throw new Error(SUBJECT_NOT_IN_CHAIN);
73-
}
74-
}
7565
}
7666

7767
/**

src/validator/validator.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ export namespace Validator {
2828
export const NOT_BEFORE_BACKWARDS = "`not before` cannot move backwards";
2929
export const PROOFS_MUST_BE_DELEGATIONS = "proofs must be delegations";
3030
export const ROOT_KEY_SIGNATURE_MISSING = "root NUC is not signed by a root issuer";
31-
export const SUBJECT_NOT_IN_CHAIN = "subject not in chain";
3231
export const TOO_MANY_PROOFS = "up to one `prf` in a token is allowed";
3332
export const UNCHAINED_PROOFS = "extra proofs not part of chain provided";
3433
// Policy validation errors
@@ -92,7 +91,6 @@ export namespace Validator {
9291
* @throws {Error} MISSING_PROOF - Required proof is missing
9392
* @throws {Error} NOT_BEFORE_BACKWARDS - notBefore times go backwards in chain
9493
* @throws {Error} ROOT_KEY_SIGNATURE_MISSING - Root signature is missing
95-
* @throws {Error} SUBJECT_NOT_IN_CHAIN - Subject is not found in chain
9694
* @throws {Error} UNCHAINED_PROOFS - Proofs are not properly chained
9795
* @throws {Error} INVALID_SIGNATURES - Any signature in the chain is invalid
9896
* @throws {Error} POLICY_NOT_MET - Policy evaluation fails

tests/integration/validator.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,28 @@ describe("Validator", () => {
269269
});
270270
});
271271

272+
it("should pass when subject is not an issuer in the chain (delegated auth)", async () => {
273+
// Root (nilauth) delegates to a session key, with sub=builder
274+
// The builder never appears as an issuer — trust flows from root
275+
const sessionSigner = Signer.generate();
276+
const sessionDid = await sessionSigner.getDid();
277+
const builderDid = await Signer.generate().getDid(); // builder never signs
278+
279+
const rootDelegation = await Builder.delegation()
280+
.audience(sessionDid)
281+
.subject(builderDid)
282+
.command("/nil")
283+
.expiresIn(ONE_HOUR_MS)
284+
.sign(rootSigner);
285+
286+
const invocation = await Builder.invocationFrom(rootDelegation)
287+
.audience(await Signer.generate().getDid())
288+
.expiresIn(ONE_HOUR_MS / 2)
289+
.sign(sessionSigner);
290+
291+
assertSuccess(invocation, { rootDids: ROOT_DIDS });
292+
});
293+
272294
it("should permit a namespace jump to the REVOKE_COMMAND", async () => {
273295
const testRootSigner = Signer.generate();
274296
const userSigner = Signer.generate();

0 commit comments

Comments
 (0)