JWT : Test audience, add tests
ci/woodpecker/push/test Pipeline was successful

Closes #17
Closes #14
This commit is contained in:
2024-06-05 10:34:56 +02:00
parent 22c60fc46a
commit fdba7f0cf8
2 changed files with 111 additions and 11 deletions
+3 -2
View File
@@ -54,12 +54,13 @@ export class JWTcontext {
public async verify<T>(jwt: string, audience?: string | string[], issuer?: string | string[]): Promise<Result<T>> {
log.debug('Verify JWT')
log.trace('Issuers :', issuer)
log.trace('Issuer :', issuer)
log.trace('Audience :', audience)
const key = this.get_key(false)
try {
let payload = await jose.jwtVerify(jwt, key)
let payload = await jose.jwtVerify(jwt, key, {audience, issuer})
return Result.ok(payload.payload.message as T)
} catch(e) {
log.warn('JWT verification failed')
+108 -9
View File
@@ -1,10 +1,16 @@
import {beforeAll, expect, test} from 'bun:test'
import {JWTcontext, type JWTalgorithm} from '../src/jwt'
import {beforeAll, describe, expect, setSystemTime, test} from 'bun:test'
import {JWTcontext, type JWTalgorithm, type Key} from '../src/jwt'
let k!: Key;
let c!: JWTcontext;
const algs: JWTalgorithm[] = ["HS256", "HS512", "ES256", "ES512", "EdDSA"]
const contexts: Map<JWTalgorithm, JWTcontext> = new Map()
beforeAll(async () => {
k = (await JWTcontext.gen_key("HS256")) as Key
c = new JWTcontext(k, "HS256")
for (const alg of algs) {
const key = await JWTcontext.gen_key(alg as JWTalgorithm)
expect(key).not.toBeUndefined()
@@ -28,10 +34,103 @@ test('Base case', async () => {
}
})
test.todo("Multiple audience can be verified")
test.todo("Multiple issuer can be verified")
test.todo("Wrong audience is rejected")
test.todo("Wrong issuer is rejected")
test.todo("Expired JWT is rejected")
test.todo("Wrong key won't decrypt")
test.todo("tampered JWT are rejected (test 3 parts) (TODO : decode ?)")
describe("Audience verification", () => {
const cases : [string|string[]|undefined, string|string[]|undefined, boolean][] = [
// undefined at verify means we don't enforce that field
[undefined, undefined, true],
["value", undefined, true],
[["value", "other"], undefined, true],
[undefined, "value", false],
[undefined, ["value", "other"], false],
["value", "value", true],
["value", ["value", "other"], true],
["value", "yeet", false],
["value", ["yeet", "other"], false],
[["value", "other"], "value", true],
[["value", "other"], ["value", "yeet"], true],
[["value", "other"], ["value", "other"], true],
[["yeet", "other"], "value", false],
[["value", "other"], ["yeet", "yaat"], false],
]
for (const [at_sign, at_verify, result] of cases) {
test(`${at_sign} and ${at_verify} ${result ? 'should' : "shouldn't"} work`, async () => {
const message = "Yeet"
const context = [...contexts.values()][0]
const jwt = await context.sign(message, false, undefined, at_sign)
const res = await context.verify<string>(jwt, at_verify)
if (result) {
res.expect("The JWT should be valid")
} else {
res.expect_err("The JWT shouldn't be valid")
}
})
}
})
describe("Issuer verification", () => {
const cases: [string|undefined, string|string[]|undefined, boolean][] = [
// undefined at verify means don't enforce the field
[undefined, undefined, true],
["value", undefined, true],
[undefined, "value", false],
[undefined, ["value", "other"], false],
["value", "value", true],
["value", ["value", "other"], true],
["value", "yeet", false],
["value", ["yeet", "other"], false],
]
for (const [at_sign, at_verify, result] of cases) {
test(`${at_sign} and ${at_verify} ${result ? 'should' : "shouldn't"} work`, async () => {
const message = "Yaat"
const context = [...contexts.values()][0]
const jwt = await context.sign(message, false, undefined, undefined, at_sign)
const res = await context.verify<string>(jwt, undefined, at_verify)
if (result) {
res.expect("The JWT should be valid")
} else {
res.expect_err("The JWT shouldn't be valid")
}
})
}
})
test("Expired JWT is rejected", async () => {
const message = "yeet"
const jwt = await c.sign(message, false, "5min")
const today = new Date()
today.setDate(today.getDate() + 1)
setSystemTime(today)
const res = await c.verify<string>(jwt)
res.expect_err("Shouldn't verify expired JWT")
})
test("Wrong key won't decrypt", async () => {
const alg = "HS256"
const k2 = await JWTcontext.gen_key(alg, false)
const c2 = new JWTcontext(k2, alg)
const message = "yeet"
const jwt = await c.sign(message)
const res = await c2.verify<string>(jwt)
res.expect_err("Shouldn't verify with a different key")
})
test("tampered JWT are rejected", async () => {
const message = "yeet"
let jwt = await c.sign(message)
if (jwt[0] === "a") jwt = "b" + jwt.substring(1)
else jwt = "a" + jwt.substring(1)
const res = await c.verify<string>(jwt)
res.expect_err("Shouldn't verify a tampered JWT")
})