Skip to content

Commit

Permalink
feat: adding isGranted to check for scopes (#123)
Browse files Browse the repository at this point in the history
  • Loading branch information
aversini authored Jul 21, 2024
1 parent cb10c89 commit 7521e24
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 0 deletions.
105 changes: 105 additions & 0 deletions packages/auth-common/src/components/__tests__/getScopes.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { importSPKI, jwtVerify } from "jose";
import { isGranted } from "..";
import { JWT, JWT_PUBLIC_KEY } from "../constants";
vi.mock("jose");

describe("isGranted", () => {
const token = "testToken";

it("should return false on error", async () => {
// @ts-expect-error
(importSPKI as vi.Mock).mockRejectedValue(new Error("test error"));

const result = await isGranted(token, ["scope1"]);

expect(result).toBe(false);
});

it("should verify that one scope is allowed", async () => {
const mockPublicKey = {};
const mockJwtVerifyResult = {
payload: {
scopes: ["scope1", "scope2"],
},
protectedHeader: "testHeader",
};
// @ts-expect-error
(importSPKI as vi.Mock).mockResolvedValue(mockPublicKey);
// @ts-expect-error
(jwtVerify as vi.Mock).mockResolvedValue(mockJwtVerifyResult);

const result = await isGranted(token, ["scope1"]);

expect(importSPKI).toHaveBeenCalledWith(JWT_PUBLIC_KEY, JWT.ALG);
expect(jwtVerify).toHaveBeenCalledWith(token, mockPublicKey, {
issuer: JWT.ISSUER,
});
expect(result).toBe(true);
});

it("should verify that 2 scopes are allowed", async () => {
const mockPublicKey = {};
const mockJwtVerifyResult = {
payload: {
scopes: ["scope1", "scope2"],
},
protectedHeader: "testHeader",
};
// @ts-expect-error
(importSPKI as vi.Mock).mockResolvedValue(mockPublicKey);
// @ts-expect-error
(jwtVerify as vi.Mock).mockResolvedValue(mockJwtVerifyResult);

const result = await isGranted(token, ["scope1", "scope2"]);

expect(importSPKI).toHaveBeenCalledWith(JWT_PUBLIC_KEY, JWT.ALG);
expect(jwtVerify).toHaveBeenCalledWith(token, mockPublicKey, {
issuer: JWT.ISSUER,
});
expect(result).toBe(true);
});

it("should verify that 1 scope is NOT allowed", async () => {
const mockPublicKey = {};
const mockJwtVerifyResult = {
payload: {
scopes: ["scope1", "scope2"],
},
protectedHeader: "testHeader",
};
// @ts-expect-error
(importSPKI as vi.Mock).mockResolvedValue(mockPublicKey);
// @ts-expect-error
(jwtVerify as vi.Mock).mockResolvedValue(mockJwtVerifyResult);

const result = await isGranted(token, ["scope3"]);

expect(importSPKI).toHaveBeenCalledWith(JWT_PUBLIC_KEY, JWT.ALG);
expect(jwtVerify).toHaveBeenCalledWith(token, mockPublicKey, {
issuer: JWT.ISSUER,
});
expect(result).toBe(false);
});

it("should verify that 1 allowed scope and 1 disallowed scope returns false", async () => {
const mockPublicKey = {};
const mockJwtVerifyResult = {
payload: {
scopes: ["scope1", "scope2"],
},
protectedHeader: "testHeader",
};
// @ts-expect-error
(importSPKI as vi.Mock).mockResolvedValue(mockPublicKey);
// @ts-expect-error
(jwtVerify as vi.Mock).mockResolvedValue(mockJwtVerifyResult);

const result = await isGranted(token, ["scope1", "scope3"]);

expect(importSPKI).toHaveBeenCalledWith(JWT_PUBLIC_KEY, JWT.ALG);
expect(jwtVerify).toHaveBeenCalledWith(token, mockPublicKey, {
issuer: JWT.ISSUER,
});
expect(result).toBe(false);
});
});
1 change: 1 addition & 0 deletions packages/auth-common/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from "./constants";
export * from "./verifyToken";
export * from "./pkce";
export * from "./getToken";
export * from "./isGranted";
15 changes: 15 additions & 0 deletions packages/auth-common/src/components/isGranted.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { JWT } from "./constants";
import { verifyAndExtractToken } from "./verifyToken";

export const isGranted = async (
token: string,
scopes: string[],
): Promise<boolean> => {
const jwt = await verifyAndExtractToken(token);

if ((jwt && (jwt?.payload?.[JWT.SCOPES_KEY] as string[]))?.length) {
const tokenScopes = jwt.payload[JWT.SCOPES_KEY] as string[];
return scopes.every((scope) => tokenScopes.includes(scope));
}
return false;
};

0 comments on commit 7521e24

Please sign in to comment.