Skip to content

Commit

Permalink
feat: set the subject as sub context variable (#17)
Browse files Browse the repository at this point in the history
This is required for native support of the @hono-middleware/permify middleware
  • Loading branch information
waigel committed Sep 6, 2024
1 parent 85ad56b commit 13adbc2
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 1 deletion.
24 changes: 24 additions & 0 deletions packages/jwks/src/middleware.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ type Env = {
Variables: {
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
jwtPayload: any;
sub?: string;
};
};

Expand Down Expand Up @@ -55,6 +56,10 @@ describe("JWKS", () => {
const app = new Hono<Env>();

app.use("/auth/*", jwks({ domain: jwksUrl }));
app.use(
"/auth-sub/*",
jwks({ domain: jwksUrl, subjectToSubContextVariable: "message" }),
);
app.use("/auth-unicode/*", jwks({ domain: jwksUrl }));
app.use("/nested/*", async (c, next) => {
const auth = jwks({ domain: jwksUrl });
Expand All @@ -66,6 +71,11 @@ describe("JWKS", () => {
const payload = c.get("jwtPayload");
return c.json(payload);
});
app.get("/auth-sub/*", (c) => {
handlerExecuted = true;
const sub = c.get("sub");
return c.json({ sub });
});
app.get("/auth-unicode/*", (c) => {
handlerExecuted = true;
const payload = c.get("jwtPayload");
Expand Down Expand Up @@ -98,6 +108,20 @@ describe("JWKS", () => {
expect(handlerExecuted).toBeTruthy();
});

it("should set the 'sub' context variable", async () => {
const credential =
"eyJhbGciOiJSUzI1NiIsImtpZCI6IjIzZmY2ODNjZDIzNGE5MTdmYTcyNWIifQ.eyJtZXNzYWdlIjoiaGVsbG8gd29ybGQifQ.RSfeJmhhbv0DONbwml-V0TwHLjKHaaON3-keyjacD1-RlvGiXpK2uerkrtgz-on4qLPJlh6c1qe6VCnatYlGeFQ3QQJIqXM-Q2ZNS0kNHz4oeJWdzvPRTM-gUmMb3rmw2EK7TlBAg2mVRCfqNW9jdwnfbd56JmfwTT7rYCVQKzZbgUNLFfB0lHtA86AUWZmpc-es3l-b1mxYLsdQroGS1cpCUsRe7et2nCmJSu3qJybKvYC4gDd8mmMEii-Fej69Esxl4UWgcEwD2cqViyvpClKtrhcgA5Nf0a624NUBVcS-7nHZNX1TJPTbnx6LQThBx7A7GU1b_XB0ig0wZ8Zpew";
const req = new Request("http://localhost/auth-sub/a");
req.headers.set("Authorization", `Bearer ${credential}`);
const res = await app.request(req);
expect(res).not.toBeNull();
expect(res.status).toBe(200);
expect(await res.json()).toEqual({
sub: "hello world",
});
expect(handlerExecuted).toBeTruthy();
});

it("Should authorize Unicode", async () => {
const credential =
"eyJhbGciOiJSUzI1NiIsImtpZCI6IjIzZmY2ODNjZDIzNGE5MTdmYTcyNWIifQ.eyJtZXNzYWdlIjoiaGVsbG8gd29ybGQifQ.RSfeJmhhbv0DONbwml-V0TwHLjKHaaON3-keyjacD1-RlvGiXpK2uerkrtgz-on4qLPJlh6c1qe6VCnatYlGeFQ3QQJIqXM-Q2ZNS0kNHz4oeJWdzvPRTM-gUmMb3rmw2EK7TlBAg2mVRCfqNW9jdwnfbd56JmfwTT7rYCVQKzZbgUNLFfB0lHtA86AUWZmpc-es3l-b1mxYLsdQroGS1cpCUsRe7et2nCmJSu3qJybKvYC4gDd8mmMEii-Fej69Esxl4UWgcEwD2cqViyvpClKtrhcgA5Nf0a624NUBVcS-7nHZNX1TJPTbnx6LQThBx7A7GU1b_XB0ig0wZ8Zpew";
Expand Down
20 changes: 19 additions & 1 deletion packages/jwks/src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,13 @@ interface MiddlewareOptions {
secret?: string | BufferSource;
prefixOptions?: CookiePrefixOptions;
};
/**
* Set the JWT subject claim to a context variable.
*
* ctx.set("sub", payload.claim.subjectToContextVariable);
* @default "sub" - The subject claim is set to the "sub" context variable.
*/
subjectToSubContextVariable?: string;
}

/**
Expand All @@ -57,12 +64,20 @@ export type JWTPayload = {
* The token is checked to ensure it is not issued in the future.
*/
iat?: number;
/**
* The subject of the token. This is usually the identifier of the user the token represents.
*/
sub?: string;
};

export function createJWKSMiddleware<T extends JWTPayload>(
options: MiddlewareOptions,
): MiddlewareHandler {
const { domain, getJwksOptions } = options;
const {
domain,
getJwksOptions,
subjectToSubContextVariable = "sub",
} = options;

const getJwks = buildGetJwks({
...getJwksOptions,
Expand Down Expand Up @@ -101,6 +116,9 @@ export function createJWKSMiddleware<T extends JWTPayload>(
}

ctx.set("jwtPayload", payload);
if (subjectToSubContextVariable && subjectToSubContextVariable in payload) {
ctx.set("sub", payload[subjectToSubContextVariable]);
}

await next();
});
Expand Down
2 changes: 2 additions & 0 deletions packages/permify/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ const { checkPermission } = createCheckPermissionMiddleware({
});

// Set the subject id for permify validation
// If you using the @hono-middlewares/jwks middleware, you can skip this step
// because the middleware will set the subject id automatically
app.use("*", createMiddleware(async (c, next) => {
c.set("sub", "acct_01j6wwsyzteqqbe76dt28vdfdr");
await next();
Expand Down

0 comments on commit 13adbc2

Please sign in to comment.