Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: verify issuer id matches #5

Merged
merged 1 commit into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions src/anoncreds/DidWebAnonCredsRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry {
}
}
try {
const { response, resourceId } = await this.parseIdAndFetchResource(agentContext, schemaId)
const { response, resourceId, did } = await this.parseIdAndFetchResource(agentContext, schemaId)

if (response.status === 200) {
const result = (await response.json()) as AnonCredsResourceResolutionResult
Expand All @@ -69,6 +69,10 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry {
throw new Error('Wrong resource Id')
}

if (did !== schema.issuerId) {
throw new Error(`issuerId in schema (${schema.issuerId}) does not match the did (${did})`)
}

if (this.cacheSettings.allowCaching) {
const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache
await cache.set(
Expand Down Expand Up @@ -147,7 +151,7 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry {
}

try {
const { response, resourceId } = await this.parseIdAndFetchResource(agentContext, credentialDefinitionId)
const { response, resourceId, did } = await this.parseIdAndFetchResource(agentContext, credentialDefinitionId)
if (response.status === 200) {
const result = (await response.json()) as AnonCredsResourceResolutionResult
const credentialDefinition = result.resource as unknown as AnonCredsCredentialDefinition
Expand All @@ -157,6 +161,12 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry {
throw new Error('Wrong resource Id')
}

if (did !== credentialDefinition.issuerId) {
throw new Error(
`issuerId in credential definition (${credentialDefinition.issuerId}) does not match the did (${did})`
)
}

if (this.cacheSettings.allowCaching) {
const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache
await cache.set(
Expand Down Expand Up @@ -242,7 +252,10 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry {
}

try {
const { response, resourceId } = await this.parseIdAndFetchResource(agentContext, revocationRegistryDefinitionId)
const { response, resourceId, did } = await this.parseIdAndFetchResource(
agentContext,
revocationRegistryDefinitionId
)
if (response.status === 200) {
const result = (await response.json()) as AnonCredsResourceResolutionResult
const revocationRegistryDefinition = result.resource as unknown as AnonCredsRevocationRegistryDefinition
Expand All @@ -252,6 +265,12 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry {
throw new Error('Wrong resource Id')
}

if (did !== revocationRegistryDefinition.issuerId) {
throw new Error(
`issuerId in revocation registry definition (${revocationRegistryDefinition.issuerId}) does not match the did (${did})`
)
}

if (this.cacheSettings.allowCaching) {
const cache = agentContext.dependencyManager.resolve(CacheModuleConfig).cache
await cache.set(
Expand Down Expand Up @@ -320,6 +339,11 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry {
try {
// TODO: use cache to get Revocation Registry Definition data without fetching it again
const revRegDefResult = await this.getRevocationRegistryDefinition(agentContext, revocationRegistryId)
if (!revRegDefResult.revocationRegistryDefinition) {
throw new Error(
`Error resolving revocation registry definition with id ${revocationRegistryId}. ${revRegDefResult.resolutionMetadata.error} ${revRegDefResult.resolutionMetadata.message}`
)
}

const baseEndpoint = revRegDefResult.revocationRegistryDefinitionMetadata.statusListEndpoint

Expand All @@ -336,6 +360,12 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry {
const revocationStatusList = result.resource as unknown as AnonCredsRevocationStatusList
const revocationStatusListMetadata = result.resourceMetadata

if (revocationStatusList.issuerId !== revRegDefResult.revocationRegistryDefinition.issuerId) {
throw new Error(
`issuerId in revocation status list (${revocationStatusList.issuerId}) does not match the issuer in the revocation registry definition (${revRegDefResult.revocationRegistryDefinition.issuerId})`
)
}

return {
revocationStatusList,
revocationStatusListMetadata,
Expand Down Expand Up @@ -427,6 +457,7 @@ export class DidWebAnonCredsRegistry implements AnonCredsRegistry {
return {
response: await agentContext.config.agentDependencies.fetch(fetchResourceUrl, { method: 'GET' }),
resourceId,
did: parsedDid.did,
}
}
}
2 changes: 1 addition & 1 deletion test/__fixtures__/schema1.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"issuerId": "did:web:api.anoncreds.idlab.app:acme",
"issuerId": "did:web:ca.dev.2060.io",
"name": "idlab_demo",
"version": "0.0.1",
"attrNames": ["id", "name"]
Expand Down
37 changes: 35 additions & 2 deletions test/credentialDefinition.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ describe('Credential Definition', () => {

const registry = new DidWebAnonCredsRegistry()

const schemaResponse = await registry.getCredentialDefinition(
const credentialDefinitionResponse = await registry.getCredentialDefinition(
agent.context,
`did:web:ca.dev.2060.io?service=anoncreds&relativeRef=/credential-definition/${resourceId}`
)

expect(schemaResponse).toEqual({
expect(credentialDefinitionResponse).toEqual({
resolutionMetadata: {},
credentialDefinition: credentialDefinition1,
credentialDefinitionId: `did:web:ca.dev.2060.io?service=anoncreds&relativeRef=/credential-definition/${resourceId}`,
Expand Down Expand Up @@ -68,4 +68,37 @@ describe('Credential Definition', () => {
credentialDefinitionMetadata: {},
})
})

test('throws error when issuerId does not match with did', async () => {
const credentialDefinition = {
...credentialDefinition1,
issuerId: 'random',
}
const resourceId = calculateResourceId(credentialDefinition)

// did document
nock('https://ca.dev.2060.io').get('/.well-known/did.json').reply(200, didDocument1)

// Get schema
nock('https://anoncreds.ca.dev.2060.io').get(`/v1/credential-definition/${resourceId}`).reply(200, {
resource: credentialDefinition,
resourceMetadata: {},
})

const registry = new DidWebAnonCredsRegistry()

const credentialDefinitionResponse = await registry.getCredentialDefinition(
agent.context,
`did:web:ca.dev.2060.io?service=anoncreds&relativeRef=/credential-definition/${resourceId}`
)

expect(credentialDefinitionResponse).toEqual({
resolutionMetadata: {
error: 'invalid',
message: 'issuerId in credential definition (random) does not match the did (did:web:ca.dev.2060.io)',
},
credentialDefinitionId: `did:web:ca.dev.2060.io?service=anoncreds&relativeRef=/credential-definition/${resourceId}`,
credentialDefinitionMetadata: {},
})
})
})
33 changes: 33 additions & 0 deletions test/revocationRegistryDefinition.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,37 @@ describe('Revocation Registry Definition', () => {
revocationRegistryDefinitionMetadata: {},
})
})

test('throws error when revocation registry definition resourceId does not match', async () => {
const revocationRegistryDefinition = {
...revocationRegistryDefinition1,
issuerId: 'random2',
}

const resourceId = calculateResourceId(revocationRegistryDefinition)
// did document
nock('https://ca.dev.2060.io').get('/.well-known/did.json').reply(200, didDocument1)

// Get schema
nock('https://anoncreds.ca.dev.2060.io').get(`/v1/revocation-registry/${resourceId}`).reply(200, {
resource: revocationRegistryDefinition,
resourceMetadata: {},
})

const registry = new DidWebAnonCredsRegistry()

const revocationRegistryDefinitionResponse = await registry.getRevocationRegistryDefinition(
agent.context,
`did:web:ca.dev.2060.io?service=anoncreds&relativeRef=/revocation-registry/${resourceId}`
)

expect(revocationRegistryDefinitionResponse).toEqual({
resolutionMetadata: {
error: 'invalid',
message: 'issuerId in revocation registry definition (random2) does not match the did (did:web:ca.dev.2060.io)',
},
revocationRegistryDefinitionId: `did:web:ca.dev.2060.io?service=anoncreds&relativeRef=/revocation-registry/${resourceId}`,
revocationRegistryDefinitionMetadata: {},
})
})
})
35 changes: 34 additions & 1 deletion test/schema.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,40 @@ describe('Schema', () => {
})
})

test('register and resole did document with nested path', async () => {
test('throws error when issuerId does not match with did', async () => {
const schema = {
...schema1,
issuerId: 'random',
}
const resourceId = calculateResourceId(schema)

// did document
nock('https://ca.dev.2060.io').get('/.well-known/did.json').reply(200, didDocument1)

// Get schema
nock('https://anoncreds.ca.dev.2060.io').get(`/v1/schema/${resourceId}`).reply(200, {
resource: schema,
resourceMetadata: {},
})

const registry = new DidWebAnonCredsRegistry()

const schemaResponse = await registry.getSchema(
agent.context,
`did:web:ca.dev.2060.io?service=anoncreds&relativeRef=/schema/${resourceId}`
)

expect(schemaResponse).toEqual({
resolutionMetadata: {
error: 'invalid',
message: 'issuerId in schema (random) does not match the did (did:web:ca.dev.2060.io)',
},
schemaId: `did:web:ca.dev.2060.io?service=anoncreds&relativeRef=/schema/${resourceId}`,
schemaMetadata: {},
})
})

test('register and resolve did document with nested path', async () => {
const registry = new DidWebAnonCredsRegistry()

const result = await registry.registerSchema(agent.context, {
Expand Down
Loading