Skip to content

Commit 044500b

Browse files
authored
chore: accept public key hash in kid header (#649)
* chore: accept public key ID in kid header * fix build
1 parent fc035fc commit 044500b

File tree

3 files changed

+55
-24
lines changed

3 files changed

+55
-24
lines changed

src/db/keypair/get.ts

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,17 @@ import { Keypairs } from "@prisma/client";
22
import { createHash } from "crypto";
33
import { prisma } from "../client";
44

5-
export const getKeypairByPublicKey = async ({
6-
publicKey,
7-
}: {
8-
publicKey: string;
9-
}): Promise<Keypairs | null> => {
10-
const hash = createHash("sha256").update(publicKey).digest("hex");
11-
5+
export const getKeypairByHash = async (
6+
hash: string,
7+
): Promise<Keypairs | null> => {
128
return prisma.keypairs.findUnique({
139
where: { hash },
1410
});
1511
};
12+
13+
export const getKeypairByPublicKey = async (
14+
publicKey: string,
15+
): Promise<Keypairs | null> => {
16+
const hash = createHash("sha256").update(publicKey).digest("hex");
17+
return getKeypairByHash(hash);
18+
};

src/server/middleware/auth.ts

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -165,18 +165,24 @@ export const onRequest = async ({
165165
const payload = decoded.payload as JwtPayload;
166166
const header = decoded.header;
167167

168-
// Get the public key from the `iss` payload field or `kid` header field.
169-
const publicKey = payload.iss ?? header.kid;
168+
// Get the public key from the `iss` payload field.
169+
const publicKey = payload.iss;
170170
if (publicKey) {
171171
const authWallet = await getAuthWallet();
172172
if (publicKey === (await authWallet.getAddress())) {
173173
return await handleAccessToken(jwt, req, getUser);
174174
} else if (publicKey === THIRDWEB_DASHBOARD_ISSUER) {
175175
return await handleDashboardAuth(jwt);
176176
} else {
177-
return await handleKeypairAuth(jwt, req, publicKey);
177+
return await handleKeypairAuth({ jwt, req, publicKey });
178178
}
179179
}
180+
181+
// Get the public key hash from the `kid` header.
182+
const publicKeyHash = header.kid;
183+
if (publicKeyHash) {
184+
return await handleKeypairAuth({ jwt, req, publicKeyHash });
185+
}
180186
}
181187
}
182188

@@ -291,19 +297,22 @@ const handleWebsocketAuth = async (
291297
* @param publicKey string
292298
* @returns AuthResponse
293299
*/
294-
const handleKeypairAuth = async (
295-
jwt: string,
296-
req: FastifyRequest,
297-
publicKey: string,
298-
): Promise<AuthResponse> => {
300+
const handleKeypairAuth = async (args: {
301+
jwt: string;
302+
req: FastifyRequest;
303+
publicKey?: string;
304+
publicKeyHash?: string;
305+
}): Promise<AuthResponse> => {
299306
// The keypair auth feature must be explicitly enabled.
300307
if (!env.ENABLE_KEYPAIR_AUTH) {
301308
return { isAuthed: false };
302309
}
303310

311+
const { jwt, req, publicKey, publicKeyHash } = args;
312+
304313
let error: string | undefined;
305314
try {
306-
const keypair = await getKeypair({ publicKey });
315+
const keypair = await getKeypair({ publicKey, publicKeyHash });
307316
if (!keypair) {
308317
error = "The provided public key is incorrect or not added to Engine.";
309318
throw error;

src/utils/cache/keypair.ts

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,39 @@
11
import type { Keypairs } from "@prisma/client";
2-
import { getKeypairByPublicKey } from "../../db/keypair/get";
2+
import { getKeypairByHash, getKeypairByPublicKey } from "../../db/keypair/get";
33

44
// Cache a public key to the Keypair object, or null if not found.
55
export const keypairCache = new Map<string, Keypairs | null>();
66

7-
export const getKeypair = async ({
8-
publicKey,
9-
}: {
10-
publicKey: string;
7+
/**
8+
* Get a keypair by public key or hash.
9+
*/
10+
export const getKeypair = async (args: {
11+
publicKey?: string;
12+
publicKeyHash?: string;
1113
}): Promise<Keypairs | null> => {
12-
const cached = keypairCache.get(publicKey);
14+
const { publicKey, publicKeyHash } = args;
15+
16+
const key = publicKey
17+
? `public-key:${args.publicKey}`
18+
: publicKeyHash
19+
? `public-key-hash:${args.publicKeyHash}`
20+
: null;
21+
22+
if (!key) {
23+
throw new Error('Must provide "publicKey" or "publicKeyHash".');
24+
}
25+
26+
const cached = keypairCache.get(key);
1327
if (cached) {
1428
return cached;
1529
}
1630

17-
const keypair = await getKeypairByPublicKey({ publicKey });
18-
keypairCache.set(publicKey, keypair);
31+
const keypair = publicKey
32+
? await getKeypairByPublicKey(publicKey)
33+
: publicKeyHash
34+
? await getKeypairByHash(publicKeyHash)
35+
: null;
36+
37+
keypairCache.set(key, keypair);
1938
return keypair;
2039
};

0 commit comments

Comments
 (0)