Skip to content

Commit

Permalink
feat(backend): Use User-Agent header with package name and version …
Browse files Browse the repository at this point in the history
…in BAPI requests (#2558)

* fix(backend): Use tsup bundling in tests

* chore(backend): Rename Clerk-Backend-SDK BAPI request header to User-Agent

* feat(backend): Add package version in User-Agent header of BAPI requests

* feat(nextjs): Add package@version to BAPI requests User-Agent header

* feat(fastify): Add package@version to BAPI requests User-Agent header

* feat(gatsby-plugin-clerk): Add package@version to BAPI requests User-Agent header

* feat(remix): Add package@version to BAPI requests User-Agent header

* feat(clerk-sdk-node): Add package@version to BAPI requests User-Agent header

* chore(repo): Add changeset

* fix(backend): Extract test-specific build config to tsup.config.test.ts

---------

Co-authored-by: Nikos Douvlis <nikosdouvlis@gmail.com>
  • Loading branch information
dimkl and nikosdouvlis authored Jan 11, 2024
1 parent 41f8832 commit b4e79c1
Show file tree
Hide file tree
Showing 15 changed files with 75 additions and 21 deletions.
13 changes: 13 additions & 0 deletions .changeset/thin-coats-serve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
'gatsby-plugin-clerk': minor
'@clerk/clerk-sdk-node': minor
'@clerk/backend': minor
'@clerk/fastify': minor
'@clerk/nextjs': minor
'@clerk/remix': minor
---

Replace the `Clerk-Backend-SDK` header with `User-Agent` in BAPI requests and update it's value to contain both the package name and the package version of the clerk package
executing the request. Eg request from `@clerk/nextjs` to BAPI with append `User-Agent: @clerk/nextjs@5.0.0-alpha-v5.16` using the latest version.

Miscellaneous changes: The backend test build changed to use tsup.
2 changes: 1 addition & 1 deletion packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@
"build:declarations": "tsc -p tsconfig.declarations.json",
"publish:local": "npx yalc push --replace --sig",
"build:lib": "tsup --env.NODE_ENV production",
"build:tests": "tsc -p tsconfig.test.json",
"build:tests": "tsup --config tsup.config.test.ts",
"build:runtime": "cpy 'src/runtime/**/*.{mjs,js,cjs}' dist/runtime",
"clean": "rimraf ./dist",
"clean:tests": "rimraf ./tests/dist",
Expand Down
16 changes: 8 additions & 8 deletions packages/backend/src/api/__tests__/factory.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export default (QUnit: QUnit) => {
headers: {
Authorization: 'Bearer deadbeef',
'Content-Type': 'application/json',
'Clerk-Backend-SDK': '@clerk/backend',
'User-Agent': '@clerk/backend@0.0.0-test',
},
}),
);
Expand Down Expand Up @@ -82,7 +82,7 @@ export default (QUnit: QUnit) => {
headers: {
Authorization: 'Bearer deadbeef',
'Content-Type': 'application/json',
'Clerk-Backend-SDK': '@clerk/backend',
'User-Agent': '@clerk/backend@0.0.0-test',
},
}),
);
Expand Down Expand Up @@ -115,7 +115,7 @@ export default (QUnit: QUnit) => {
headers: {
Authorization: 'Bearer deadbeef',
'Content-Type': 'application/json',
'Clerk-Backend-SDK': '@clerk/backend',
'User-Agent': '@clerk/backend@0.0.0-test',
},
}),
);
Expand Down Expand Up @@ -145,7 +145,7 @@ export default (QUnit: QUnit) => {
headers: {
Authorization: 'Bearer deadbeef',
'Content-Type': 'application/json',
'Clerk-Backend-SDK': '@clerk/backend',
'User-Agent': '@clerk/backend@0.0.0-test',
},
}),
);
Expand Down Expand Up @@ -173,7 +173,7 @@ export default (QUnit: QUnit) => {
headers: {
Authorization: 'Bearer deadbeef',
'Content-Type': 'application/json',
'Clerk-Backend-SDK': '@clerk/backend',
'User-Agent': '@clerk/backend@0.0.0-test',
},
body: JSON.stringify({
first_name: 'John',
Expand Down Expand Up @@ -214,7 +214,7 @@ export default (QUnit: QUnit) => {
headers: {
Authorization: 'Bearer deadbeef',
'Content-Type': 'application/json',
'Clerk-Backend-SDK': '@clerk/backend',
'User-Agent': '@clerk/backend@0.0.0-test',
},
}),
);
Expand All @@ -237,7 +237,7 @@ export default (QUnit: QUnit) => {
headers: {
Authorization: 'Bearer deadbeef',
'Content-Type': 'application/json',
'Clerk-Backend-SDK': '@clerk/backend',
'User-Agent': '@clerk/backend@0.0.0-test',
},
}),
);
Expand All @@ -262,7 +262,7 @@ export default (QUnit: QUnit) => {
headers: {
Authorization: 'Bearer deadbeef',
'Content-Type': 'application/json',
'Clerk-Backend-SDK': '@clerk/backend',
'User-Agent': '@clerk/backend@0.0.0-test',
},
}),
);
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/api/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export function buildRequest(options: BuildRequestOptions) {
// Build headers
const headers: Record<string, any> = {
Authorization: `Bearer ${secretKey}`,
'Clerk-Backend-SDK': userAgent,
'User-Agent': userAgent,
...headerParams,
};

Expand Down
3 changes: 1 addition & 2 deletions packages/backend/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
export const API_URL = 'https://api.clerk.com';
export const API_VERSION = 'v1';

// TODO: Get information from package.json or define them from ESBuild
export const USER_AGENT = `@clerk/backend`;
export const USER_AGENT = `${PACKAGE_NAME}@${PACKAGE_VERSION}`;
export const MAX_CACHE_LAST_UPDATED_AT_SECONDS = 5 * 60;
export const JWKS_CACHE_TTL_MS = 1000 * 60 * 60;

Expand Down
4 changes: 2 additions & 2 deletions packages/backend/src/tokens/__tests__/keys.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export default (QUnit: QUnit) => {
headers: {
Authorization: 'Bearer deadbeef',
'Content-Type': 'application/json',
'Clerk-Backend-SDK': '@clerk/backend',
'User-Agent': '@clerk/backend@0.0.0-test',
},
});
assert.propEqual(jwk, mockRsaJwk);
Expand All @@ -87,7 +87,7 @@ export default (QUnit: QUnit) => {
headers: {
Authorization: 'Bearer sk_test_deadbeef',
'Content-Type': 'application/json',
'Clerk-Backend-SDK': '@clerk/backend',
'User-Agent': '@clerk/backend@0.0.0-test',
},
});
assert.propEqual(jwk, mockRsaJwk);
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/tokens/__tests__/verify.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default (QUnit: QUnit) => {
headers: {
Authorization: 'Bearer a-valid-key',
'Content-Type': 'application/json',
'Clerk-Backend-SDK': '@clerk/backend',
'User-Agent': '@clerk/backend@0.0.0-test',
},
});
assert.propEqual(data, mockJwtPayload);
Expand Down
25 changes: 25 additions & 0 deletions packages/backend/tsup.config.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { defineConfig } from 'tsup';

// @ts-ignore
import { name } from './package.json';

export default defineConfig(overrideOptions => {
const isWatch = !!overrideOptions.watch;

return {
entry: ['./src/**/*.{ts,js}'],
outDir: 'tests/dist/',
define: {
PACKAGE_NAME: `"${name}"`,
// use "test" instead of actual package version to avoid updating the tests
// depending on it (eg userAgent related) on every version bump
PACKAGE_VERSION: `"0.0.0-test"`,
__DEV__: `${isWatch}`,
},
external: ['#crypto'],
clean: true,
minify: false,
tsconfig: 'tsconfig.test.json',
format: 'cjs',
};
});
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ exports[`clerk initializes clerk with constants 1`] = `
"version": "0.0.0-test",
},
"secretKey": "TEST_SECRET_KEY",
"userAgent": "@clerk/fastify@0.0.0-test",
},
],
]
Expand Down
1 change: 1 addition & 0 deletions packages/fastify/src/clerkClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ export const clerkClient = createClerkClient({
apiUrl: API_URL,
apiVersion: API_VERSION,
jwtKey: JWT_KEY,
userAgent: `${PACKAGE_NAME}@${PACKAGE_VERSION}`,
sdkMetadata: SDK_METADATA,
});
3 changes: 1 addition & 2 deletions packages/gatsby-plugin-clerk/src/ssr/clerkClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ const clerkClient = createClerkClient({
secretKey: SECRET_KEY,
apiUrl: API_URL,
apiVersion: API_VERSION,
// TODO: Fetch version from package.json
userAgent: 'gatsby-plugin-clerk',
userAgent: `${PACKAGE_NAME}@${PACKAGE_VERSION}`,
sdkMetadata: SDK_METADATA,
telemetry: {
disabled: TELEMETRY_DISABLED,
Expand Down
16 changes: 16 additions & 0 deletions packages/nextjs/src/server/__tests__/clerkClient.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
global.fetch = jest.fn(() => Promise.resolve(new Response(null)));

import { clerkClient } from '../clerkClient';

describe('clerkClient', () => {
it('should pass version package to userAgent', async () => {
await clerkClient.users.getUser('user_test');

expect(global.fetch).toBeCalled();
expect((global.fetch as any).mock.calls[0][1].headers).toMatchObject({
Authorization: 'Bearer TEST_SECRET_KEY',
'Content-Type': 'application/json',
'User-Agent': '@clerk/nextjs@0.0.0-test',
});
});
});
3 changes: 1 addition & 2 deletions packages/nextjs/src/server/clerkClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ const clerkClient = createClerkClient({
secretKey: SECRET_KEY,
apiUrl: API_URL,
apiVersion: API_VERSION,
// TODO: Fetch version from package.json
userAgent: '@clerk/nextjs',
userAgent: `${PACKAGE_NAME}@${PACKAGE_VERSION}`,
proxyUrl: PROXY_URL,
domain: DOMAIN,
isSatellite: IS_SATELLITE,
Expand Down
1 change: 1 addition & 0 deletions packages/remix/src/ssr/authenticateRequest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export async function authenticateRequest(
proxyUrl,
isSatellite,
domain,
userAgent: `${PACKAGE_NAME}@${PACKAGE_VERSION}`,
}).authenticateRequest(request, {
audience,
secretKey,
Expand Down
4 changes: 2 additions & 2 deletions packages/sdk-node/src/clerkClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,12 @@ export const clerkClient = new Proxy(clerkClientSingleton, {

const env = { ...loadApiEnv(), ...loadClientEnv() };
if (env.secretKey) {
clerkClientSingleton = createClerkClient({ ...env, userAgent: PACKAGE_NAME });
clerkClientSingleton = createClerkClient({ ...env, userAgent: `${PACKAGE_NAME}@${PACKAGE_VERSION}` });
// @ts-expect-error - Element implicitly has an 'any' type because expression of type 'string | symbol' can't be used to index type 'ExtendedClerk'.
return clerkClientSingleton[property];
}

const c = createClerkClient({ ...env, userAgent: PACKAGE_NAME });
const c = createClerkClient({ ...env, userAgent: `${PACKAGE_NAME}@${PACKAGE_VERSION}` });
// @ts-expect-error - Element implicitly has an 'any' type because expression of type 'string | symbol' can't be used to index type 'ExtendedClerk'.
return c[property];
},
Expand Down

0 comments on commit b4e79c1

Please sign in to comment.