diff --git a/packages/interface/src/lib.ts b/packages/interface/src/lib.ts index cb3bbb6d..6addbcec 100644 --- a/packages/interface/src/lib.ts +++ b/packages/interface/src/lib.ts @@ -284,9 +284,9 @@ export type InvocationError = | InvalidAudience | Unauthorized -export interface InvocationContext extends CanIssue { +export interface InvocationContext extends ValidatorOptions { id: Verifier - my?: (issuer: DID) => Capability[] + resolve?: (proof: UCANLink) => Await> principal: PrincipalParser @@ -460,7 +460,6 @@ export interface ValidatorOptions { readonly principal?: PrincipalParser readonly canIssue?: CanIssue['canIssue'] - readonly my?: InvocationContext['my'] readonly resolve?: InvocationContext['resolve'] } diff --git a/packages/server/src/server.js b/packages/server/src/server.js index 6f5b3d6a..e16414b8 100644 --- a/packages/server/src/server.js +++ b/packages/server/src/server.js @@ -32,12 +32,10 @@ class Server { encoder, decoder, principal = Verifier, - canIssue = (capability, issuer) => - capability.with === issuer || issuer === id.did(), ...rest }) { const { catch: fail, ...context } = rest - this.context = { id, principal, canIssue, ...context } + this.context = { id, principal, ...context } this.service = service this.encoder = encoder this.decoder = decoder diff --git a/packages/server/test/handler.spec.js b/packages/server/test/handler.spec.js index 422608aa..14101c6d 100644 --- a/packages/server/test/handler.spec.js +++ b/packages/server/test/handler.spec.js @@ -153,7 +153,11 @@ test('checks service id', async () => { const result = await invocation.execute(client) - assert.deepEqual(result, null) + assert.equal(result?.error, true) + + assert.ok( + result?.message.includes(`can not be (self) issued by '${w3.did()}'`) + ) } }) diff --git a/packages/validator/test/session.spec.js b/packages/validator/test/session.spec.js index ec24be39..b5b1148e 100644 --- a/packages/validator/test/session.spec.js +++ b/packages/validator/test/session.spec.js @@ -310,3 +310,122 @@ test('resolve key', async () => { }, }) }) + +test('service can not delegate access to account', async () => { + const account = Absentee.from({ id: 'did:mailto:web.mail:alice' }) + // service should not be able to delegate access to account resource + const auth = await Delegation.delegate({ + issuer: w3, + audience: alice, + capabilities: [ + { + with: account.did(), + can: 'debug/echo', + }, + ], + }) + + const session = await Delegation.delegate({ + issuer: w3, + audience: alice, + capabilities: [ + { + with: w3.did(), + can: 'ucan/attest', + nb: { proof: auth.cid }, + }, + ], + proofs: [auth], + }) + + const request = echo.invoke({ + audience: w3, + issuer: alice, + with: account.did(), + nb: { message: 'hello world' }, + proofs: [auth, session], + }) + + const result = await access(await request.delegate(), { + authority: w3, + capability: echo, + principal: Verifier, + }) + + assert.equal(result.error, true) +}) + +test('attest with an account did', async () => { + const account = Absentee.from({ id: 'did:mailto:web.mail:alice' }) + + // service should not be able to delegate access to account resource + const auth = await Delegation.delegate({ + issuer: w3, + audience: alice, + capabilities: [ + { + with: account.did(), + can: 'debug/echo', + }, + ], + }) + + const session = await Delegation.delegate({ + issuer: w3, + audience: alice, + capabilities: [ + { + // this should be an service did instead + with: account.did(), + can: 'ucan/attest', + nb: { proof: auth.cid }, + }, + ], + }) + + const request = echo.invoke({ + audience: w3, + issuer: alice, + with: account.did(), + nb: { message: 'hello world' }, + proofs: [auth, session], + }) + + const result = await access(await request.delegate(), { + authority: w3, + capability: echo, + principal: Verifier, + }) + + assert.equal(result.error, true) +}) + +test('service can not delegate account resource', async () => { + const account = Absentee.from({ id: 'did:mailto:web.mail:alice' }) + const proof = await Delegation.delegate({ + issuer: service, + audience: alice, + capabilities: [ + { + can: 'debug/echo', + with: account.did(), + }, + ], + }) + + const request = await echo.invoke({ + issuer: alice, + audience: service, + with: account.did(), + nb: { message: 'hello world' }, + proofs: [proof], + }) + + const result = await access(await request.delegate(), { + authority: w3, + capability: echo, + principal: Verifier, + }) + + assert.equal(result.error, true) +})