diff --git a/src/verifiers/documentStatus/didSigned/didSignedDocumentStatus.test.ts b/src/verifiers/documentStatus/didSigned/didSignedDocumentStatus.test.ts index 047b5f1..5ba8f42 100644 --- a/src/verifiers/documentStatus/didSigned/didSignedDocumentStatus.test.ts +++ b/src/verifiers/documentStatus/didSigned/didSignedDocumentStatus.test.ts @@ -595,6 +595,127 @@ describe("verify", () => { server.close(); }); + + it("should fail when DID document is signed but is found by an OCSP with reasoncode for suspended", async () => { + whenPublicKeyResolvesSuccessfully(); + + const handlers = [ + rest.get( + "https://ocsp.example.com/0x28b221f6287d8e4f8da09a835bcb750537cc8385e2535ff63591fdf0162be824", + (_, res, ctx) => { + return res( + ctx.json({ + revoked: true, + documentHash: "0x28b221f6287d8e4f8da09a835bcb750537cc8385e2535ff63591fdf0162be824", + reasonCode: 1001, + }) + ); + } + ), + rest.get( + "https://ocsp.example.com/0x56961854a82feafe9a56eb57acfe3b97f17eda5d497b622c9acc9f03c412618c", + (_, res, ctx) => { + return res( + ctx.json({ + revoked: false, + documentHash: "0x56961854a82feafe9a56eb57acfe3b97f17eda5d497b622c9acc9f03c412618c", + }) + ); + } + ), + ]; + + const server: SetupServerApi = setupServer(...handlers); + server.listen(); + + const res = await openAttestationDidSignedDocumentStatus.verify(didSignedOcspResponderV2, options); + expect(res).toMatchInlineSnapshot(` + Object { + "data": Object { + "details": Object { + "issuance": Array [ + Object { + "did": "did:ethr:0xB26B4941941C51a4885E5B7D3A1B861E54405f90", + "issued": true, + }, + ], + "revocation": Array [ + Object { + "address": "https://ocsp.example.com", + "reason": Object { + "code": 1001, + "codeString": "SUSPENDED", + "message": "Document 0x56961854a82feafe9a56eb57acfe3b97f17eda5d497b622c9acc9f03c412618c has been revoked under OCSP Responder: https://ocsp.example.com", + }, + "revoked": true, + }, + ], + }, + "issuedOnAll": true, + "revokedOnAny": true, + }, + "name": "OpenAttestationDidSignedDocumentStatus", + "reason": Object { + "code": 1001, + "codeString": "SUSPENDED", + "message": "Document 0x56961854a82feafe9a56eb57acfe3b97f17eda5d497b622c9acc9f03c412618c has been revoked under OCSP Responder: https://ocsp.example.com", + }, + "status": "INVALID", + "type": "DOCUMENT_STATUS", + } + `); + + server.close(); + }); + it("should thwow an invalid ocsp response error when DID document is signed but is found by an OCSP with an invalid reasoncode", async () => { + whenPublicKeyResolvesSuccessfully(); + + const handlers = [ + rest.get( + "https://ocsp.example.com/0x28b221f6287d8e4f8da09a835bcb750537cc8385e2535ff63591fdf0162be824", + (_, res, ctx) => { + return res( + ctx.json({ + revoked: true, + documentHash: "0x28b221f6287d8e4f8da09a835bcb750537cc8385e2535ff63591fdf0162be824", + reasonCode: 7, + }) + ); + } + ), + rest.get( + "https://ocsp.example.com/0x56961854a82feafe9a56eb57acfe3b97f17eda5d497b622c9acc9f03c412618c", + (_, res, ctx) => { + return res( + ctx.json({ + revoked: false, + documentHash: "0x56961854a82feafe9a56eb57acfe3b97f17eda5d497b622c9acc9f03c412618c", + }) + ); + } + ), + ]; + + const server: SetupServerApi = setupServer(...handlers); + server.listen(); + + const res = await openAttestationDidSignedDocumentStatus.verify(didSignedOcspResponderV2, options); + expect(res).toMatchInlineSnapshot(` + Object { + "data": [Error: Invalid or unexpected response from OCSP Responder], + "name": "OpenAttestationDidSignedDocumentStatus", + "reason": Object { + "code": 11, + "codeString": "OCSP_RESPONSE_INVALID", + "message": "Invalid or unexpected response from OCSP Responder", + }, + "status": "ERROR", + "type": "DOCUMENT_STATUS", + } + `); + + server.close(); + }); }); describe("v3", () => { @@ -990,6 +1111,44 @@ describe("verify", () => { } `); + server.close(); + }); + it("should throw an invalid ocsp response error when DID document is signed but is found by an OCSP with an invalid reasoncode", async () => { + whenPublicKeyResolvesSuccessfully("0x1245e5B64D785b25057f7438F715f4aA5D965733"); + + const handlers = [ + rest.get( + "https://ocsp.example.com/0x69e1a174ea67e1c3119639f713f8a7348bbda54fdce60903621398cc2fea4d40", + (_, res, ctx) => { + return res( + ctx.json({ + revoked: true, + documentHash: "0x69e1a174ea67e1c3119639f713f8a7348bbda54fdce60903621398cc2fea4d40", + reasonCode: 7, + }) + ); + } + ), + ]; + + const server: SetupServerApi = setupServer(...handlers); + server.listen(); + + const res = await openAttestationDidSignedDocumentStatus.verify(didSignedOcspResponderV3, options); + expect(res).toMatchInlineSnapshot(` + Object { + "data": [Error: Invalid or unexpected response from OCSP Responder], + "name": "OpenAttestationDidSignedDocumentStatus", + "reason": Object { + "code": 11, + "codeString": "OCSP_RESPONSE_INVALID", + "message": "Invalid or unexpected response from OCSP Responder", + }, + "status": "ERROR", + "type": "DOCUMENT_STATUS", + } + `); + server.close(); }); }); diff --git a/src/verifiers/documentStatus/didSigned/didSignedDocumentStatus.type.ts b/src/verifiers/documentStatus/didSigned/didSignedDocumentStatus.type.ts index 0b4ba08..d843a61 100644 --- a/src/verifiers/documentStatus/didSigned/didSignedDocumentStatus.type.ts +++ b/src/verifiers/documentStatus/didSigned/didSignedDocumentStatus.type.ts @@ -7,6 +7,7 @@ import { } from "../../../types/core"; import { Reason } from "../../../types/error"; import { + OcspResponderRevocationReason, RevocationStatus, RevocationStatusArray, ValidRevocationStatus, @@ -40,7 +41,9 @@ export type DidSignedIssuanceStatusArray = Static n >= 0 && n <= 10 && n != 7); +export const ValidOcspReasonCode = Number.withConstraint((n) => + Object.values(OcspResponderRevocationReason).includes(n) +); export const ValidOcspResponse = Record({ revoked: Literal(false), diff --git a/src/verifiers/documentStatus/revocation.types.ts b/src/verifiers/documentStatus/revocation.types.ts index 940608b..8fa1a17 100644 --- a/src/verifiers/documentStatus/revocation.types.ts +++ b/src/verifiers/documentStatus/revocation.types.ts @@ -32,4 +32,5 @@ export enum OcspResponderRevocationReason { REMOVE_FROM_CRL = 8, PRIVILEGE_WITHDRAWN = 9, A_A_COMPROMISE = 10, + SUSPENDED = 1001, }