Skip to content

Commit

Permalink
Make 'verify' accept a generic type argument for 'Payload' (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
timonson authored Jun 10, 2022
1 parent 0e9ee0d commit e4b7695
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 8 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ Takes `jwt`, `CryptoKey` and `VerifyOptions` and returns the `Payload` of the
import { verify } from "https://deno.land/x/djwt@$VERSION/mod.ts";

const payload = await verify(jwt, key); // { foo: "bar" }
// Accepts an generic type argument optionally:
const payload = await verify<{ foo: string }>(jwt, key); // { foo: "bar" }
```

### decode
Expand Down
16 changes: 8 additions & 8 deletions mod.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ function isTooEarly(nbf: number, leeway: number): boolean {
return nbf - leeway > Date.now() / 1000;
}

function isObject(obj: unknown): obj is Record<string, unknown> {
function isObject<O extends JsonObject>(obj: JsonValue): obj is O {
return (
obj !== null && typeof obj === "object" && Array.isArray(obj) === false
);
Expand All @@ -66,7 +66,7 @@ function hasInvalidTimingClaims(...claimValues: unknown[]): boolean {
);
}

function isHeader(headerMaybe: unknown): headerMaybe is Header {
function isHeader(headerMaybe: JsonValue): headerMaybe is Header {
return isObject(headerMaybe) && typeof headerMaybe.alg === "string";
}

Expand All @@ -87,12 +87,12 @@ export function decode(jwt: string): DecodeReturnType {
}
}

export function validate(
export function validate<P extends Payload>(
[header, payload, signature]: DecodeReturnType,
{ expLeeway = 1, nbfLeeway = 1 }: VerifyOptions = {},
): {
header: Header;
payload: Payload;
payload: P;
signature: Uint8Array;
} {
if (isHeader(header)) {
Expand All @@ -101,7 +101,7 @@ export function validate(
* representation of a completely valid JSON object conforming to RFC 7159;
* let the JWT Claims Set be this JSON object.
*/
if (isObject(payload)) {
if (isObject<P>(payload)) {
if (hasInvalidTimingClaims(payload.exp, payload.nbf)) {
throw new Error(`The jwt has an invalid 'exp' or 'nbf' claim.`);
}
Expand Down Expand Up @@ -133,12 +133,12 @@ export function validate(
}
}

export async function verify(
export async function verify<P extends Payload>(
jwt: string,
key: CryptoKey | null,
options?: VerifyOptions,
): Promise<Payload> {
const { header, payload, signature } = validate(decode(jwt), options);
): Promise<P> {
const { header, payload, signature } = validate<P>(decode(jwt), options);
if (verifyAlgorithm(header.alg, key)) {
if (
!(await verifySignature(
Expand Down
15 changes: 15 additions & 0 deletions tests/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ const keyES384 = await window.crypto.subtle.generateKey(
// ["sign", "verify"],
// );

function acceptString(s: string) {
return s;
}

Deno.test({
name: "[jwt] create",
fn: async function () {
Expand Down Expand Up @@ -204,6 +208,17 @@ Deno.test({
{},
);

await assertEquals(
acceptString(
(await verify<{ name: string }>(
await create({ alg: "HS512", typ: "JWT" }, payload, keyHS512),
keyHS512,
{ expLeeway: 10 },
)).name,
),
payload.name,
);

await assertRejects(
async () => {
await verify(
Expand Down

0 comments on commit e4b7695

Please sign in to comment.