Skip to content

Commit

Permalink
Merge pull request #20 from nats-io/custom-aud
Browse files Browse the repository at this point in the history
[CHANGE] `aud` can now be passed as an encode option
  • Loading branch information
aricart authored Jan 17, 2023
2 parents 05dd196 + dcd694f commit 778d88d
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/jwtjs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
test:
strategy:
matrix:
deno-version: [1.17.0]
deno-version: [1.29.2]
environment: CI
runs-on: ubuntu-latest
steps:
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nats-jwt",
"version": "0.0.3",
"version": "0.0.4-1",
"description": "NATS jwt.js",
"main": "cjs/jwt.js",
"module": "./esm/jwt.js",
Expand Down
4 changes: 2 additions & 2 deletions src/base64.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export class Base64Codec {
return btoa(String.fromCharCode(...a));
}

static decode(s: string, binary = false): (Uint8Array | string) {
static decode(s: string, binary = false): Uint8Array | string {
const bin = atob(s);
if (!binary) {
return bin;
Expand All @@ -38,7 +38,7 @@ export class Base64UrlCodec {
return Base64UrlCodec.toB64URLEncoding(Base64Codec.encode(bytes));
}

static decode(s: string, binary = false): (Uint8Array | string) {
static decode(s: string, binary = false): Uint8Array | string {
return Base64Codec.decode(Base64UrlCodec.fromB64URLEncoding(s), binary);
}

Expand Down
8 changes: 4 additions & 4 deletions src/jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,14 @@ export interface UserEncodingOptions extends EncodingOptions {
}

export interface EncodingOptions extends ValidDates {
aud?: string;
algorithm: Algorithms;
signer?: Key;
}

function initClaim<T>(opts: Partial<EncodingOptions>): ClaimsData<T> {
const { exp, nbf } = opts;
return extend({}, { exp, nbf }) as ClaimsData<T>;
const { exp, nbf, aud } = opts;
return extend({}, { exp, nbf, aud }) as ClaimsData<T>;
}

function initAlgorithm(opts: Partial<EncodingOptions> = {}): EncodingOptions {
Expand Down Expand Up @@ -137,7 +138,6 @@ export async function encodeUser(
if (opts.signer) {
claim.nats.issuer_account = issuer.getPublicKey();
}
claim.aud = "NATS";
const o = initAlgorithm(opts);
setVersionType(o.algorithm, Types.User, claim);
return await encode(o.algorithm, claim, signer);
Expand Down Expand Up @@ -193,7 +193,7 @@ function setVersionType(
type: Types | string,
claim: ClaimsData<Generic>,
) {
claim.aud = "NATS";
claim.aud = claim.aud || "NATS";
if (version === Algorithms.v2) {
claim.nats.type = type;
} else {
Expand Down
3 changes: 2 additions & 1 deletion src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export function defaultUserLimits(): Required<UserLimits> {
}

export function defaultUserPermissionsLimits(
d: (Partial<UserPermissionsLimits> | Partial<Permissions> | Partial<Limits>) =
d: Partial<UserPermissionsLimits> | Partial<Permissions> | Partial<Limits> =
{} as Partial<UserPermissionsLimits>,
): UserPermissionsLimits {
return extend(
Expand All @@ -131,6 +131,7 @@ export function defaultUser(d: Partial<User> = {}): Partial<User> {
export function extend(a: unknown, ...b: unknown[]): unknown {
for (let i = 0; i < b.length; i++) {
const o = b[i];
//@ts-ignore: raw
Object.assign(a, o);
}
return a;
Expand Down
51 changes: 35 additions & 16 deletions tests/jwt_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
import {
assert,
assertEquals,
assertThrowsAsync,
} from "https://deno.land/std@0.103.0/testing/asserts.ts";
assertExists,
assertRejects,
} from "https://deno.land/std@0.171.0/testing/asserts.ts";
import { nsc, parseTable } from "./nsc.ts";
import {
Account,
Expand All @@ -27,6 +28,7 @@ import {
createOperator,
createUser,
decode,
defaultUserLimits,
defaultUserPermissionsLimits,
encodeAccount,
encodeActivation,
Expand All @@ -45,7 +47,6 @@ import {
User,
version,
} from "../src/mod.ts";
import { assertExists } from "https://deno.land/std@0.95.0/testing/asserts.ts";

Deno.test("parse table", () => {
const t =
Expand Down Expand Up @@ -82,7 +83,7 @@ Deno.test("parse table", () => {

Deno.test("jwt - rejects bad chunks", async () => {
const jwt = `eyJhbGciOiJIUzI1NiIsInR`;
await assertThrowsAsync(
await assertRejects(
async () => {
await decode(jwt);
},
Expand All @@ -94,7 +95,7 @@ Deno.test("jwt - rejects bad chunks", async () => {
Deno.test("jwt - rejects bad algorithm", async () => {
const jwt =
`eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c`;
await assertThrowsAsync(
await assertRejects(
async () => {
await decode(jwt);
},
Expand All @@ -120,7 +121,7 @@ Deno.test("jwt - rejects bad type", async () => {
JSON.stringify({ typ: "Foo", alg: "ed25519-nkey" }),
);

await assertThrowsAsync(
await assertRejects(
async () => {
await decode(chunks.join("."));
},
Expand All @@ -134,7 +135,7 @@ Deno.test("jwt - rejects bad signature", async () => {
const token = await encodeAccount("A", akp);
const chunks = token.split(".");
chunks[2] = chunks[2].split("").reverse().join("");
await assertThrowsAsync(
await assertRejects(
async () => {
await decode<Account>(chunks.join("."));
},
Expand Down Expand Up @@ -223,7 +224,7 @@ Deno.test("jwt - account signer can be operator or account", async () => {
const id = createAccount();
await encodeAccount("A", id, {} as Account, { signer: okp });
await encodeAccount("A", id, {} as Account, { signer: akp });
await assertThrowsAsync(
await assertRejects(
async () => {
await encodeAccount("A", id, {} as Account, { signer: ukp });
},
Expand All @@ -237,14 +238,14 @@ Deno.test("jwt - account id must be account", async () => {
const akp = createAccount();
const ukp = createUser();
await encodeAccount("A", akp, {} as Account, { signer: okp });
await assertThrowsAsync(
await assertRejects(
async () => {
await encodeAccount("A", okp, {} as Account, { signer: okp });
},
Error,
"unexpected type O - wanted A",
);
await assertThrowsAsync(
await assertRejects(
async () => {
await encodeAccount("A", ukp, {} as Account, { signer: okp });
},
Expand All @@ -258,14 +259,14 @@ Deno.test("jwt - user id must be user", async () => {
const akp = createAccount();
const ukp = createUser();
await encodeUser("A", ukp, akp);
await assertThrowsAsync(
await assertRejects(
async () => {
await encodeUser("A", akp, akp);
},
Error,
"unexpected type A - wanted U",
);
await assertThrowsAsync(
await assertRejects(
async () => {
await encodeUser("A", okp, akp);
},
Expand All @@ -279,14 +280,14 @@ Deno.test("jwt - user issuer must be account", async () => {
const akp = createAccount();
const ukp = createUser();
await encodeUser("A", ukp, akp);
await assertThrowsAsync(
await assertRejects(
async () => {
await encodeUser("A", ukp, ukp);
},
Error,
"unexpected type U - wanted A",
);
await assertThrowsAsync(
await assertRejects(
async () => {
await encodeUser("A", ukp, okp);
},
Expand All @@ -300,14 +301,14 @@ Deno.test("jwt - user issuer_account must be account", async () => {
const akp = createAccount();
const ukp = createUser();
await encodeUser("A", ukp, akp, {}, { signer: akp });
await assertThrowsAsync(
await assertRejects(
async () => {
await encodeUser("A", ukp, akp, {}, { signer: ukp });
},
Error,
"unexpected type U - wanted A",
);
await assertThrowsAsync(
await assertRejects(
async () => {
await encodeUser("A", ukp, akp, {}, { signer: okp });
},
Expand Down Expand Up @@ -727,3 +728,21 @@ Deno.test("jwt - account disallow_bearer", async () => {
ac = await decode<Account>(token);
assertEquals(ac.nats.disallow_bearer, true);
});

Deno.test("jwt - custom aud", async () => {
const akp = createAccount();
let at = await encodeAccount("A", akp, {}, { aud: "hello" });
let ac = await decode<Account>(at);
assertEquals(ac.aud, "hello");

const ukp = createUser();
let ut = await encodeUser("A", ukp, akp, defaultUserLimits(), {
aud: "hello",
});
let uc = await decode<User>(ut);
assertEquals(uc.aud, "hello");

let gt = await encodeGeneric("A", akp, "my-kind", {}, { aud: "hello" });
let gc = await decode<unknown>(ut);
assertEquals(gc.aud, "hello");
});
9 changes: 4 additions & 5 deletions typedoc.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{
"readme": "none",
"theme": "default",
"out": "docs/",
"entryPoints": ["cjs_src/mod.ts"]
"readme": "none",
"theme": "default",
"out": "docs/",
"entryPoints": ["cjs_src/mod.ts"]
}

0 comments on commit 778d88d

Please sign in to comment.