Skip to content

Commit

Permalink
fix: JWT verification with multiple audiences
Browse files Browse the repository at this point in the history
  • Loading branch information
simonas-notcat committed May 5, 2020
1 parent c341dbc commit dbbb85f
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 7 deletions.
6 changes: 0 additions & 6 deletions packages/daf-did-jwt/src/__tests__/default.test.ts

This file was deleted.

155 changes: 155 additions & 0 deletions packages/daf-did-jwt/src/__tests__/message-handler.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
import { Message, Agent } from 'daf-core'
import { JwtMessageHandler } from '../index'
import { blake2bHex } from 'blakejs'

describe('daf-did-jwt', () => {
const vcJwt =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NkstUiJ9.eyJpYXQiOjE1ODI2MTk2NzYsInN1YiI6ImRpZDpldGhyOnJpbmtlYnk6MHgzYzM1N2JhNDU4OTMzYTE5YzFkZjFjN2Y2YjQ3M2IzMzAyYmJiZTYxIiwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJuYW1lIjoiQWxpY2UifX0sImlzcyI6ImRpZDpldGhyOnJpbmtlYnk6MHgzYzM1N2JhNDU4OTMzYTE5YzFkZjFjN2Y2YjQ3M2IzMzAyYmJiZTYxIn0.IGF1LFOc4_PcGVeq7Yw7OGz4Gj7xXZK6p8bP9CSEIXz7mNFPM0v0nuevTZ47a0I8XgLfCFNkUrIIscjH8MFx_wE'

const vcPayload = {
iat: 1582619676,
sub: 'did:ethr:rinkeby:0x3c357ba458933a19c1df1c7f6b473b3302bbbe61',
vc: {
'@context': ['https://www.w3.org/2018/credentials/v1'],
type: ['VerifiableCredential'],
credentialSubject: {
name: 'Alice',
},
},
iss: 'did:ethr:rinkeby:0x3c357ba458933a19c1df1c7f6b473b3302bbbe61',
}

const vpJwt =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NkstUiJ9.eyJpYXQiOjE1ODI2MTk4NzUsImF1ZCI6ImRpZDpldGhyOnJpbmtlYnk6MHgzYzM1N2JhNDU4OTMzYTE5YzFkZjFjN2Y2YjQ3M2IzMzAyYmJiZTYxIiwidGFnIjoieHl6LTEyMyIsInZwIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIl0sInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJdLCJ2ZXJpZmlhYmxlQ3JlZGVudGlhbCI6WyJleUowZVhBaU9pSktWMVFpTENKaGJHY2lPaUpGVXpJMU5rc3RVaUo5LmV5SnBZWFFpT2pFMU9ESTJNVGsyTnpZc0luTjFZaUk2SW1ScFpEcGxkR2h5T25KcGJtdGxZbms2TUhnell6TTFOMkpoTkRVNE9UTXpZVEU1WXpGa1pqRmpOMlkyWWpRM00ySXpNekF5WW1KaVpUWXhJaXdpZG1NaU9uc2lRR052Ym5SbGVIUWlPbHNpYUhSMGNITTZMeTkzZDNjdWR6TXViM0puTHpJd01UZ3ZZM0psWkdWdWRHbGhiSE12ZGpFaVhTd2lkSGx3WlNJNld5SldaWEpwWm1saFlteGxRM0psWkdWdWRHbGhiQ0pkTENKamNtVmtaVzUwYVdGc1UzVmlhbVZqZENJNmV5SnVZVzFsSWpvaVFXeHBZMlVpZlgwc0ltbHpjeUk2SW1ScFpEcGxkR2h5T25KcGJtdGxZbms2TUhnell6TTFOMkpoTkRVNE9UTXpZVEU1WXpGa1pqRmpOMlkyWWpRM00ySXpNekF5WW1KaVpUWXhJbjAuSUdGMUxGT2M0X1BjR1ZlcTdZdzdPR3o0R2o3eFhaSzZwOGJQOUNTRUlYejdtTkZQTTB2MG51ZXZUWjQ3YTBJOFhnTGZDRk5rVXJJSXNjakg4TUZ4X3dFIl19LCJpc3MiOiJkaWQ6ZXRocjpyaW5rZWJ5OjB4M2MzNTdiYTQ1ODkzM2ExOWMxZGYxYzdmNmI0NzNiMzMwMmJiYmU2MSJ9.7gIGq437moBKMwF3PUrycjCP4Op6dL6IJV6GygSq1KGV7QU0II16YzETsr412AlHl_kaYgUJjRav7unJdyJL0wA'

const vpPayload = {
iat: 1582619875,
aud: 'did:ethr:rinkeby:0x3c357ba458933a19c1df1c7f6b473b3302bbbe61',
tag: 'xyz-123',
vp: {
'@context': ['https://www.w3.org/2018/credentials/v1'],
type: ['VerifiablePresentation'],
verifiableCredential: [
'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NkstUiJ9.eyJpYXQiOjE1ODI2MTk2NzYsInN1YiI6ImRpZDpldGhyOnJpbmtlYnk6MHgzYzM1N2JhNDU4OTMzYTE5YzFkZjFjN2Y2YjQ3M2IzMzAyYmJiZTYxIiwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJuYW1lIjoiQWxpY2UifX0sImlzcyI6ImRpZDpldGhyOnJpbmtlYnk6MHgzYzM1N2JhNDU4OTMzYTE5YzFkZjFjN2Y2YjQ3M2IzMzAyYmJiZTYxIn0.IGF1LFOc4_PcGVeq7Yw7OGz4Gj7xXZK6p8bP9CSEIXz7mNFPM0v0nuevTZ47a0I8XgLfCFNkUrIIscjH8MFx_wE',
],
},
iss: 'did:ethr:rinkeby:0x3c357ba458933a19c1df1c7f6b473b3302bbbe61',
}

const vpMultiAudJwt =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NkstUiJ9.eyJpYXQiOjE1ODg2NzY3MzksInZwIjp7IkBjb250ZXh0IjpbImh0dHBzOi8vd3d3LnczLm9yZy8yMDE4L2NyZWRlbnRpYWxzL3YxIl0sInR5cGUiOlsiVmVyaWZpYWJsZVByZXNlbnRhdGlvbiJdLCJ2ZXJpZmlhYmxlQ3JlZGVudGlhbCI6WyJleUowZVhBaU9pSktWMVFpTENKaGJHY2lPaUpGVXpJMU5rc3RVaUo5LmV5SnBZWFFpT2pFMU9ESTJNVGsyTnpZc0luTjFZaUk2SW1ScFpEcGxkR2h5T25KcGJtdGxZbms2TUhnell6TTFOMkpoTkRVNE9UTXpZVEU1WXpGa1pqRmpOMlkyWWpRM00ySXpNekF5WW1KaVpUWXhJaXdpZG1NaU9uc2lRR052Ym5SbGVIUWlPbHNpYUhSMGNITTZMeTkzZDNjdWR6TXViM0puTHpJd01UZ3ZZM0psWkdWdWRHbGhiSE12ZGpFaVhTd2lkSGx3WlNJNld5SldaWEpwWm1saFlteGxRM0psWkdWdWRHbGhiQ0pkTENKamNtVmtaVzUwYVdGc1UzVmlhbVZqZENJNmV5SnVZVzFsSWpvaVFXeHBZMlVpZlgwc0ltbHpjeUk2SW1ScFpEcGxkR2h5T25KcGJtdGxZbms2TUhnell6TTFOMkpoTkRVNE9UTXpZVEU1WXpGa1pqRmpOMlkyWWpRM00ySXpNekF5WW1KaVpUWXhJbjAuSUdGMUxGT2M0X1BjR1ZlcTdZdzdPR3o0R2o3eFhaSzZwOGJQOUNTRUlYejdtTkZQTTB2MG51ZXZUWjQ3YTBJOFhnTGZDRk5rVXJJSXNjakg4TUZ4X3dFIl19LCJ0YWciOiJ0YWcxMjMiLCJhdWQiOlsiZGlkOmV4YW1wbGU6MzQ1NiIsImRpZDp3ZWI6dXBvcnQubWUiXSwiaXNzIjoiZGlkOmV0aHI6cmlua2VieToweGIwOWI2NjAyNmJhNTkwOWE3Y2ZlOTliNzY4NzU0MzFkMmI4ZDUxOTAifQ.4SWpp8siCBHP47KrOT_28IJIQPZLCWO9VS0Ir-VVYOGUAVj7vHtXLxl3Y6lLAxYeNqWrRPCAVkDArBFCNRjYUgA'

const vpMultiAudPayload = {
iat: 1588676739,
vp: {
'@context': ['https://www.w3.org/2018/credentials/v1'],
type: ['VerifiablePresentation'],
verifiableCredential: [
'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NkstUiJ9.eyJpYXQiOjE1ODI2MTk2NzYsInN1YiI6ImRpZDpldGhyOnJpbmtlYnk6MHgzYzM1N2JhNDU4OTMzYTE5YzFkZjFjN2Y2YjQ3M2IzMzAyYmJiZTYxIiwidmMiOnsiQGNvbnRleHQiOlsiaHR0cHM6Ly93d3cudzMub3JnLzIwMTgvY3JlZGVudGlhbHMvdjEiXSwidHlwZSI6WyJWZXJpZmlhYmxlQ3JlZGVudGlhbCJdLCJjcmVkZW50aWFsU3ViamVjdCI6eyJuYW1lIjoiQWxpY2UifX0sImlzcyI6ImRpZDpldGhyOnJpbmtlYnk6MHgzYzM1N2JhNDU4OTMzYTE5YzFkZjFjN2Y2YjQ3M2IzMzAyYmJiZTYxIn0.IGF1LFOc4_PcGVeq7Yw7OGz4Gj7xXZK6p8bP9CSEIXz7mNFPM0v0nuevTZ47a0I8XgLfCFNkUrIIscjH8MFx_wE',
],
},
tag: 'tag123',
aud: ['did:example:3456', 'did:web:uport.me'],
iss: 'did:ethr:rinkeby:0xb09b66026ba5909a7cfe99b76875431d2b8d5190',
}

const agent = new Agent({
identityProviders: [],
serviceControllers: [],
messageHandler: {
setNext: jest.fn(),
handle: jest.fn().mockResolvedValue(true),
},
didResolver: {
resolve: async (did: string) => ({
'@context': 'https://w3id.org/did/v1',
id: did,
publicKey: [
{
id: `${did}#owner`,
type: 'Secp256k1VerificationKey2018',
owner: did,
ethereumAddress: did.slice(-42),
},
],
authentication: [
{
type: 'Secp256k1SignatureAuthentication2018',
publicKey: `${did}#owner`,
},
],
}),
},
})

it('should reject unknown message type', async () => {
const mockNextHandler = {
setNext: jest.fn(),
handle: jest.fn().mockRejectedValue('Unsupported message type'),
}
const handler = new JwtMessageHandler()
handler.setNext(mockNextHandler)
const message = new Message({ raw: 'test', metaData: [{ type: 'test' }] })
expect(handler.handle(message, agent)).rejects.toEqual('Unsupported message type')
})

it('should set data field for VC jwt', async () => {
const mockNextHandler = {
setNext: jest.fn(),
handle: jest.fn().mockResolvedValue(true),
}
const handler = new JwtMessageHandler()
handler.setNext(mockNextHandler)

const message = new Message({ raw: vcJwt, metaData: [{ type: 'test' }] })
await handler.handle(message, agent)
expect(mockNextHandler.handle).toBeCalledWith(
expect.objectContaining({
raw: vcJwt,
data: vcPayload,
metaData: [{ type: 'test' }, { type: 'JWT', value: 'ES256K-R' }],
}),
agent,
)
})

it('should set data field for VP jwt', async () => {
const mockNextHandler = {
setNext: jest.fn(),
handle: jest.fn().mockResolvedValue(true),
}
const handler = new JwtMessageHandler()
handler.setNext(mockNextHandler)

const message = new Message({ raw: vpJwt, metaData: [{ type: 'test' }] })
await handler.handle(message, agent)
expect(mockNextHandler.handle).toBeCalledWith(
expect.objectContaining({
raw: vpJwt,
data: vpPayload,
metaData: [{ type: 'test' }, { type: 'JWT', value: 'ES256K-R' }],
}),
agent,
)
})

it('should set data field for multi audience VP jwt', async () => {
const mockNextHandler = {
setNext: jest.fn(),
handle: jest.fn(),
}
const handler = new JwtMessageHandler()
handler.setNext(mockNextHandler)

const message = new Message({ raw: vpMultiAudJwt, metaData: [{ type: 'test' }] })
await handler.handle(message, agent)
expect(mockNextHandler.handle).toBeCalledWith(
expect.objectContaining({
raw: vpMultiAudJwt,
data: vpMultiAudPayload,
metaData: [{ type: 'test' }, { type: 'JWT', value: 'ES256K-R' }],
}),
agent,
)
})
})
2 changes: 1 addition & 1 deletion packages/daf-did-jwt/src/message-handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class JwtMessageHandler extends AbstractMessageHandler {
async handle(message: Message, agent: Agent): Promise<Message> {
try {
const decoded = decodeJWT(message.raw)
const audience = decoded.payload.aud
const audience = Array.isArray(decoded.payload.aud) ? decoded.payload.aud[0] : decoded.payload.aud
const verified = await verifyJWT(message.raw, { resolver: agent.didResolver, audience })
debug('Message.raw is a valid JWT')
message.addMetaData({ type: decoded.header.typ, value: decoded.header.alg })
Expand Down

0 comments on commit dbbb85f

Please sign in to comment.