Skip to content
This repository has been archived by the owner on Jun 27, 2024. It is now read-only.

Commit

Permalink
refactor(jwt): accept secret as first arg (#179)
Browse files Browse the repository at this point in the history
  • Loading branch information
boywithkeyboard committed Aug 18, 2023
1 parent ac6e82c commit 1bec5ba
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 16 deletions.
39 changes: 23 additions & 16 deletions jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,8 @@ import {
decode,
encode,
} from 'https://deno.land/std@0.198.0/encoding/base64.ts'
import {
create,
getNumericDate,
Payload as JwtPayload,
verify as _verify,
VerifyOptions,
} from 'https://deno.land/x/djwt@v2.8/mod.ts'
import * as Jwt from 'https://deno.land/x/djwt@v2.8/mod.ts'
import { Context } from './mod.ts'

interface Payload {
iss?: string
Expand Down Expand Up @@ -55,16 +50,22 @@ export function importKey(key: string) {
*/
// deno-lint-ignore ban-types
export async function sign<T extends Record<string, unknown> = {}>(
secret: string | CryptoKey | Context,
payload: T & Payload,
secret: string | CryptoKey,
) {
const key = typeof secret === 'string' ? await importKey(secret) : secret
const key = typeof secret === 'string'
? await importKey(secret)
: secret instanceof Context
? await importKey(
(secret.env('jwt_secret') ?? secret.env('JWT_SECRET')) as string,
)
: secret

const { exp, nbf, ...rest } = payload

return await create({ alg: 'HS512', typ: 'JWT' }, {
...(exp && { exp: getNumericDate(exp) }),
...(nbf && { nbf: getNumericDate(nbf) }),
return await Jwt.create({ alg: 'HS512', typ: 'JWT' }, {
...(exp && { exp: Jwt.getNumericDate(exp) }),
...(nbf && { nbf: Jwt.getNumericDate(nbf) }),
...rest,
}, key)
}
Expand All @@ -73,14 +74,20 @@ export async function sign<T extends Record<string, unknown> = {}>(
* Verify the validity of a JWT.
*/
export async function verify<T extends Record<string, unknown> = Payload>(
secret: string | CryptoKey | Context,
token: string,
secret: string | CryptoKey,
options?: VerifyOptions,
options?: Jwt.VerifyOptions,
) {
try {
const key = typeof secret === 'string' ? await importKey(secret) : secret
const key = typeof secret === 'string'
? await importKey(secret)
: secret instanceof Context
? await importKey(
(secret.env('jwt_secret') ?? secret.env('JWT_SECRET')) as string,
)
: secret

return await _verify(token, key, options) as JwtPayload & T
return await Jwt.verify(token, key, options) as Jwt.Payload & T
} catch (_err) {
return
}
Expand Down
37 changes: 37 additions & 0 deletions test/jwt.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright 2023 Samuel Kopp. All rights reserved. Apache-2.0 license.
import { cheetah } from '../cheetah.ts'
import { createKey, importKey } from '../jwt.ts'
import { jwt } from '../mod.ts'
import { assertEquals, assertInstanceOf } from '../test/deps.ts'

Deno.test('jwt', async () => {
const key = await createKey()
const cryptoKey = await importKey(key)

assertInstanceOf(cryptoKey, CryptoKey)

const token = await jwt.sign(key, { example: 'object' })

assertEquals(await jwt.verify(await createKey(), token) === undefined, true)
assertEquals(await jwt.verify(key, token) !== undefined, true)
assertEquals(await jwt.verify(cryptoKey, token) !== undefined, true)

Deno.env.set('jwt_secret', key)

const app = new cheetah()

app.get('/one', async (c) => {
assertEquals(await jwt.verify(c, token) !== undefined, true)
})

await app.fetch(new Request('http://localhost/one'))

Deno.env.delete('jwt_secret')
Deno.env.set('JWT_SECRET', key)

app.get('/two', async (c) => {
assertEquals(await jwt.verify(c, token) !== undefined, true)
})

await app.fetch(new Request('http://localhost/two'))
})
2 changes: 2 additions & 0 deletions x/x.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { assertEquals, assertInstanceOf } from '../test/deps.ts'
import { h, jsx } from './jsx.tsx'
import { createKey, importKey, sign, verify } from './jwt.ts'

// TODO delete at v2.0

Deno.test('x', async (t) => {
await t.step('jwt', async () => {
const key = await createKey()
Expand Down

0 comments on commit 1bec5ba

Please sign in to comment.