Skip to content

Commit

Permalink
feat: add aud override policy for verification
Browse files Browse the repository at this point in the history
fixes #239
  • Loading branch information
mirceanis committed Aug 15, 2022
1 parent c0b14de commit b4cdd12
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 13 deletions.
7 changes: 4 additions & 3 deletions src/JWT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ export interface JWTVerifyPolicies {
nbf?: boolean
iat?: boolean
exp?: boolean
aud?: boolean
}

export interface JWSCreationOptions {
Expand Down Expand Up @@ -149,9 +150,9 @@ export const SUPPORTED_PUBLIC_KEY_TYPES: PublicKeyTypes = {
export const SELF_ISSUED_V2 = 'https://self-issued.me/v2'
export const SELF_ISSUED_V0_1 = 'https://self-issued.me'

// Exporting errorCodes in a machine readable format rather than human readable format to be used in higher level module
// Exporting errorCodes in a machine-readable format rather than human-readable format to be used in higher level module
export const INVALID_JWT = 'invalid_jwt'
export const INAVLID_CONFIG = 'invalid_config'
export const INVALID_CONFIG = 'invalid_config'
export const INVALID_SIGNATURE = 'invalid_signature'
export const NOT_SUPPORTED = 'not_supported'
export const NO_SUITABLE_KEYS = 'no_suitable_keys'
Expand Down Expand Up @@ -400,7 +401,7 @@ export async function verifyJWT(
if (options.policies?.exp !== false && payload.exp && payload.exp <= now - skewTime) {
throw new Error(`invalid_jwt: JWT has expired: exp: ${payload.exp} < now: ${now}`)
}
if (payload.aud) {
if (options.policies?.aud !== false && payload.aud) {
if (!options.audience && !options.callbackUrl) {
throw new Error('invalid_config: JWT audience is required but your app address has not been configured')
}
Expand Down
40 changes: 30 additions & 10 deletions src/__tests__/JWT.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { VerificationMethod } from 'did-resolver'
import { TokenVerifier } from 'jsontokens'
import MockDate from 'mockdate'
import { fromString } from 'uint8arrays/from-string'
import { getAddress } from "@ethersproject/address"
import { getAddress } from '@ethersproject/address'
import {
createJWS,
createJWT,
Expand Down Expand Up @@ -466,7 +466,13 @@ describe('verifyJWT()', () => {
expect.assertions(2)
// const jwt = await createJWT({nbf:FUTURE},{issuer:did,signer})

const jwt = await createJWT({ requested: ['name', 'phone'], nbf: new Date().getTime() + 1000000 }, { issuer: did, signer })
const jwt = await createJWT(
{ requested: ['name', 'phone'], nbf: new Date().getTime() + 1000000 },
{
issuer: did,
signer,
}
)
expect(verifier.verify(jwt)).toBe(true)

const { payload } = await verifyJWT(jwt, { resolver, policies: { nbf: false } })
Expand All @@ -477,14 +483,19 @@ describe('verifyJWT()', () => {
expect.assertions(2)
// const jwt = await createJWT({nbf:FUTURE},{issuer:did,signer})

const jwt = await createJWT({ requested: ['name', 'phone'], nbf: new Date().getTime() + 10000 }, { issuer: did, signer })
const jwt = await createJWT(
{ requested: ['name', 'phone'], nbf: new Date().getTime() + 10000 },
{
issuer: did,
signer,
}
)
expect(verifier.verify(jwt)).toBe(true)

const { payload } = await verifyJWT(jwt, { resolver, policies: { now: new Date().getTime() + 100000 } })
return expect(payload).toBeDefined()
})


it('fails when nbf is in the future and iat is in the past', async () => {
expect.assertions(1)
const jwt =
Expand All @@ -499,7 +510,7 @@ describe('verifyJWT()', () => {
// const jwt = await createJWT({nbf:FUTURE,iat:PAST},{issuer:did,signer})

const { payload } = await verifyJWT(jwt, { resolver, policies: { nbf: false } })
expect(payload).toBeDefined();
expect(payload).toBeDefined()
})
it('passes when nbf is missing and iat is in the past', async () => {
expect.assertions(1)
Expand All @@ -520,7 +531,7 @@ describe('verifyJWT()', () => {
const jwt =
'eyJ0eXAiOiJKV1QiLCJhbGciOiJFUzI1NksifQ.eyJpYXQiOjE0ODUzODExMzMsImlzcyI6ImRpZDpldGhyOjB4ZjNiZWFjMzBjNDk4ZDllMjY4NjVmMzRmY2FhNTdkYmI5MzViMGQ3NCJ9.FJuHvf9Tby7b4I54Cm1nh8CvLg4QH2wt2K0WfyQaLqlr3NKKI5hAdLalgZksI25gLhNrZwQFnC-nzEOs9PI1SQ'
// const jwt = await createJWT({iat:FUTURE},{issuer:did,signer})
const { payload } = await verifyJWT(jwt, { resolver, policies: { iat: false }})
const { payload } = await verifyJWT(jwt, { resolver, policies: { iat: false } })
return expect(payload).toBeDefined()
})
it('passes when nbf and iat are both missing', async () => {
Expand Down Expand Up @@ -602,9 +613,7 @@ describe('verifyJWT()', () => {
resolve: jest.fn().mockReturnValue({
didDocument: {
id: did,
verificationMethod: [
verificationMethod
],
verificationMethod: [verificationMethod],
},
}),
}
Expand Down Expand Up @@ -643,7 +652,7 @@ describe('verifyJWT()', () => {
expect.assertions(1)
const jwt = await createJWT({ exp: NOW - 1 }, { issuer: did, signer })
const { payload } = await verifyJWT(jwt, { resolver, skewTime: 0, policies: { exp: false } })
return expect(payload).toBeDefined();
return expect(payload).toBeDefined()
})

it('accepts a valid audience', async () => {
Expand Down Expand Up @@ -686,6 +695,17 @@ describe('verifyJWT()', () => {
)
})

it('accepts invalid audience when override policy is used', async () => {
expect.assertions(2)
const jwt = await createJWT({ aud }, { issuer: did, signer })
const { payload, issuer } = await verifyJWT(jwt, {
resolver,
policies: { aud: false }
})
expect(payload).toBeDefined()
expect(issuer).toEqual(did)
})

it('rejects an invalid audience using callback_url where callback is wrong', async () => {
expect.assertions(1)
const jwt = await createJWT({ aud: 'http://pututu.uport.me/unique' }, { issuer: did, signer })
Expand Down

0 comments on commit b4cdd12

Please sign in to comment.