Skip to content

Commit c2960fe

Browse files
fahe1em1hntrl
andauthored
fix(google): lazy-load jose in CJS auth helpers (#10407)
Co-authored-by: Hunter Lovell <40191806+hntrl@users.noreply.github.com> Co-authored-by: Hunter Lovell <hunter@hntrl.io>
1 parent d69dfcc commit c2960fe

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed

.changeset/shy-dolls-admire.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@langchain/google": patch
3+
---
4+
5+
lazy-load jose in CJS auth helpers

libs/providers/langchain-google/src/utils/gcp-auth.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,18 @@
66
* License: MIT (https://github.com/kriasoft/web-auth-library/blob/main/LICENSE)
77
*/
88

9-
import { decodeJwt, importPKCS8, SignJWT } from "jose";
109
import { AuthError } from "../utils/errors.js";
1110
import { iife } from "../utils/misc.js";
1211

12+
type JoseModule = typeof import("jose");
13+
14+
let joseModulePromise: Promise<JoseModule> | undefined;
15+
16+
async function getJose(): Promise<JoseModule> {
17+
joseModulePromise ??= import("jose");
18+
return joseModulePromise;
19+
}
20+
1321
/**
1422
* Google Cloud Platform service account credentials interface.
1523
*
@@ -107,7 +115,8 @@ export function normalizeGCPCredentials(
107115
* // Use privateKey for signing operations
108116
* ```
109117
*/
110-
export function getGCPPrivateKey(credentials: GCPCredentials) {
118+
export async function getGCPPrivateKey(credentials: GCPCredentials) {
119+
const { importPKCS8 } = await getJose();
111120
return importPKCS8(credentials.private_key, "RS256");
112121
}
113122

@@ -138,6 +147,7 @@ export function getGCPPrivateKey(credentials: GCPCredentials) {
138147
* ```
139148
*/
140149
export async function getGCPCustomToken(credentials: GCPCredentials) {
150+
const { SignJWT } = await getJose();
141151
const privateKey = await getGCPPrivateKey(credentials);
142152
const customToken = await new SignJWT()
143153
.setIssuer(credentials.client_email)
@@ -249,6 +259,7 @@ export async function getGCPCredentialsAccessToken(
249259
const data = await res.json();
250260

251261
if ("id_token" in data) {
262+
const { decodeJwt } = await getJose();
252263
const claims = decodeJwt(data.id_token);
253264
return { token: data.id_token, expires: claims.exp as number };
254265
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { describe, expect, it, vi } from "vitest";
2+
3+
describe("gcp-auth", () => {
4+
it("does not import jose eagerly when loading the auth helpers", async () => {
5+
vi.resetModules();
6+
vi.doMock("jose", () => {
7+
throw new Error("jose should not load during module import");
8+
});
9+
10+
const { normalizeGCPCredentials } = await import("../gcp-auth.js");
11+
12+
expect(
13+
normalizeGCPCredentials(
14+
'{"type":"service_account","project_id":"p","private_key_id":"k","private_key":"pem","client_id":"c","client_email":"a@b.c","auth_uri":"https://auth","token_uri":"https://token","auth_provider_x509_cert_url":"https://cert","client_x509_cert_url":"https://client-cert"}'
15+
)
16+
).toMatchObject({
17+
project_id: "p",
18+
private_key_id: "k",
19+
});
20+
});
21+
22+
it("loads jose lazily when a signing helper is called", async () => {
23+
vi.resetModules();
24+
const importPKCS8 = vi.fn().mockResolvedValue("imported-key");
25+
26+
vi.doMock("jose", () => ({
27+
importPKCS8,
28+
SignJWT: class {},
29+
decodeJwt: vi.fn(),
30+
}));
31+
32+
const { getGCPPrivateKey } = await import("../gcp-auth.js");
33+
34+
const result = await getGCPPrivateKey({
35+
type: "service_account",
36+
project_id: "p",
37+
private_key_id: "k",
38+
private_key: "pem",
39+
client_id: "c",
40+
client_email: "a@b.c",
41+
auth_uri: "https://auth",
42+
token_uri: "https://token",
43+
auth_provider_x509_cert_url: "https://cert",
44+
client_x509_cert_url: "https://client-cert",
45+
});
46+
47+
expect(result).toBe("imported-key");
48+
expect(importPKCS8).toHaveBeenCalledWith("pem", "RS256");
49+
});
50+
});

0 commit comments

Comments
 (0)