diff --git a/.changeset/serious-chicken-report.md b/.changeset/serious-chicken-report.md new file mode 100644 index 00000000000..bfba4d3f8d9 --- /dev/null +++ b/.changeset/serious-chicken-report.md @@ -0,0 +1,27 @@ +--- +"@clerk/backend": minor +--- + +Rename M2M namespace from `m2mTokens` to `m2m` in Backend API client + +Before: + +```ts +clerkClient.m2mTokens.create() + +clerkClient.m2mTokens.revoke() + +clerkClient.m2mTokens.verifySecret({ secret: 'ak_xxx' }) +``` + +After: + +```ts +clerkClient.m2m.createToken() + +clerkClient.m2m.revokeToken() + +clerkClient.m2m.verifyToken({ token: 'ak_xxx' }) +``` + +The `verifySecret()` method is removed. Please use `.verifyToken()` instead. diff --git a/integration/tests/machine-auth/m2m.test.ts b/integration/tests/machine-auth/m2m.test.ts index 0eb98458b4f..f15f32baef9 100644 --- a/integration/tests/machine-auth/m2m.test.ts +++ b/integration/tests/machine-auth/m2m.test.ts @@ -43,18 +43,7 @@ test.describe('machine-to-machine auth @machine', () => { const token = req.get('Authorization')?.split(' ')[1]; try { - const m2mToken = await clerkClient.m2mTokens.verifyToken({ token }); - res.send('Protected response ' + m2mToken.id); - } catch { - res.status(401).send('Unauthorized'); - } - }); - - app.get('/api/protected-deprecated', async (req, res) => { - const secret = req.get('Authorization')?.split(' ')[1]; - - try { - const m2mToken = await clerkClient.m2mTokens.verifySecret({ secret }); + const m2mToken = await clerkClient.m2m.verifyToken({ token }); res.send('Protected response ' + m2mToken.id); } catch { res.status(401).send('Unauthorized'); @@ -81,7 +70,7 @@ test.describe('machine-to-machine auth @machine', () => { name: `${fakeCompanyName} Email Server`, scopedMachines: [primaryApiServer.id], }); - emailServerM2MToken = await client.m2mTokens.create({ + emailServerM2MToken = await client.m2m.createToken({ machineSecretKey: emailServer.secretKey, secondsUntilExpiration: 60 * 30, }); @@ -91,7 +80,7 @@ test.describe('machine-to-machine auth @machine', () => { name: `${fakeCompanyName} Analytics Server`, // No scoped machines }); - analyticsServerM2MToken = await client.m2mTokens.create({ + analyticsServerM2MToken = await client.m2m.createToken({ machineSecretKey: analyticsServer.secretKey, secondsUntilExpiration: 60 * 30, }); @@ -102,10 +91,10 @@ test.describe('machine-to-machine auth @machine', () => { secretKey: instanceKeys.get('with-api-keys').sk, }); - await client.m2mTokens.revoke({ + await client.m2m.revokeToken({ m2mTokenId: emailServerM2MToken.id, }); - await client.m2mTokens.revoke({ + await client.m2m.revokeToken({ m2mTokenId: analyticsServerM2MToken.id, }); await client.machines.delete(emailServer.id); @@ -164,7 +153,7 @@ test.describe('machine-to-machine auth @machine', () => { // Analytics server can access primary API server after adding scope await u.services.clerk.machines.createScope(analyticsServer.id, primaryApiServer.id); - const m2mToken = await u.services.clerk.m2mTokens.create({ + const m2mToken = await u.services.clerk.m2m.createToken({ machineSecretKey: analyticsServer.secretKey, secondsUntilExpiration: 60 * 30, }); @@ -176,21 +165,8 @@ test.describe('machine-to-machine auth @machine', () => { }); expect(res2.status()).toBe(200); expect(await res2.text()).toBe('Protected response ' + m2mToken.id); - await u.services.clerk.m2mTokens.revoke({ + await u.services.clerk.m2m.revokeToken({ m2mTokenId: m2mToken.id, }); }); - - test('authorizes M2M requests with deprecated verifySecret method', async ({ page, context }) => { - const u = createTestUtils({ app, page, context }); - - // Email server can access primary API server - const res = await u.page.request.get(app.serverUrl + '/api/protected-deprecated', { - headers: { - Authorization: `Bearer ${emailServerM2MToken.token}`, - }, - }); - expect(res.status()).toBe(200); - expect(await res.text()).toBe('Protected response ' + emailServerM2MToken.id); - }); }); diff --git a/packages/backend/src/api/__tests__/M2MTokenApi.test.ts b/packages/backend/src/api/__tests__/M2MTokenApi.test.ts index ade378f102e..f2d8f99c016 100644 --- a/packages/backend/src/api/__tests__/M2MTokenApi.test.ts +++ b/packages/backend/src/api/__tests__/M2MTokenApi.test.ts @@ -40,7 +40,7 @@ describe('M2MToken', () => { ), ); - const response = await apiClient.m2mTokens.create({ + const response = await apiClient.m2m.createToken({ secondsUntilExpiration: 3600, }); @@ -65,7 +65,7 @@ describe('M2MToken', () => { ), ); - const response = await apiClient.m2mTokens.create({ + const response = await apiClient.m2m.createToken({ machineSecretKey: 'ak_xxxxx', secondsUntilExpiration: 3600, }); @@ -102,7 +102,7 @@ describe('M2MToken', () => { ), ); - const errResponse = await apiClient.m2mTokens.create().catch(err => err); + const errResponse = await apiClient.m2m.createToken().catch(err => err); expect(errResponse.status).toBe(401); expect(errResponse.errors[0].code).toBe('machine_secret_key_invalid'); @@ -143,7 +143,7 @@ describe('M2MToken', () => { ), ); - const response = await apiClient.m2mTokens.revoke({ + const response = await apiClient.m2m.revokeToken({ m2mTokenId: m2mId, revocationReason: 'revoked by test', }); @@ -171,7 +171,7 @@ describe('M2MToken', () => { ), ); - const response = await apiClient.m2mTokens.revoke({ + const response = await apiClient.m2m.revokeToken({ m2mTokenId: m2mId, revocationReason: 'revoked by test', }); @@ -195,8 +195,8 @@ describe('M2MToken', () => { ), ); - const errResponse = await apiClient.m2mTokens - .revoke({ + const errResponse = await apiClient.m2m + .revokeToken({ m2mTokenId: m2mId, revocationReason: 'revoked by test', }) @@ -223,7 +223,7 @@ describe('M2MToken', () => { ), ); - const response = await apiClient.m2mTokens.verifyToken({ + const response = await apiClient.m2m.verifyToken({ token: m2mSecret, }); @@ -249,7 +249,7 @@ describe('M2MToken', () => { ), ); - const response = await apiClient.m2mTokens.verifyToken({ + const response = await apiClient.m2m.verifyToken({ token: m2mSecret, }); @@ -273,7 +273,7 @@ describe('M2MToken', () => { ), ); - const errResponse = await apiClient.m2mTokens + const errResponse = await apiClient.m2m .verifyToken({ token: m2mSecret, }) @@ -282,81 +282,4 @@ describe('M2MToken', () => { expect(errResponse.status).toBe(401); }); }); - - describe('verifySecret (deprecated)', () => { - it('verifies a m2m token using machine secret', async () => { - const apiClient = createBackendApiClient({ - apiUrl: 'https://api.clerk.test', - machineSecretKey: 'ak_xxxxx', - }); - - server.use( - http.post( - 'https://api.clerk.test/m2m_tokens/verify', - validateHeaders(({ request }) => { - expect(request.headers.get('Authorization')).toBe('Bearer ak_xxxxx'); - return HttpResponse.json(mockM2MToken); - }), - ), - ); - - const response = await apiClient.m2mTokens.verifySecret({ - secret: m2mSecret, - }); - - expect(response.id).toBe(m2mId); - expect(response.token).toBe(m2mSecret); - expect(response.scopes).toEqual(['mch_1xxxxx', 'mch_2xxxxx']); - expect(response.claims).toEqual({ foo: 'bar' }); - }); - - it('verifies a m2m token using instance secret', async () => { - const apiClient = createBackendApiClient({ - apiUrl: 'https://api.clerk.test', - secretKey: 'sk_xxxxx', - }); - - server.use( - http.post( - 'https://api.clerk.test/m2m_tokens/verify', - validateHeaders(({ request }) => { - expect(request.headers.get('Authorization')).toBe('Bearer sk_xxxxx'); - return HttpResponse.json(mockM2MToken); - }), - ), - ); - - const response = await apiClient.m2mTokens.verifySecret({ - secret: m2mSecret, - }); - - expect(response.id).toBe(m2mId); - expect(response.token).toBe(m2mSecret); - expect(response.scopes).toEqual(['mch_1xxxxx', 'mch_2xxxxx']); - expect(response.claims).toEqual({ foo: 'bar' }); - }); - - it('requires a machine secret or instance secret to verify a m2m token', async () => { - const apiClient = createBackendApiClient({ - apiUrl: 'https://api.clerk.test', - }); - - server.use( - http.post( - 'https://api.clerk.test/m2m_tokens/verify', - validateHeaders(() => { - return HttpResponse.json(mockM2MToken); - }), - ), - ); - - const errResponse = await apiClient.m2mTokens - .verifySecret({ - secret: m2mSecret, - }) - .catch(err => err); - - expect(errResponse.status).toBe(401); - }); - }); }); diff --git a/packages/backend/src/api/__tests__/factory.test.ts b/packages/backend/src/api/__tests__/factory.test.ts index 7ed0cdb19a1..e3e0f697461 100644 --- a/packages/backend/src/api/__tests__/factory.test.ts +++ b/packages/backend/src/api/__tests__/factory.test.ts @@ -325,7 +325,7 @@ describe('api.client', () => { ), ); - const response = await apiClient.m2mTokens.verifyToken({ + const response = await apiClient.m2m.verifyToken({ machineSecretKey: 'ak_test_in_header_params', // this will be added to headerParams.Authorization token: 'mt_secret_test', }); @@ -353,7 +353,7 @@ describe('api.client', () => { ), ); - const response = await apiClient.m2mTokens.verifyToken({ + const response = await apiClient.m2m.verifyToken({ token: 'mt_secret_test', }); expect(response.id).toBe('mt_test'); @@ -425,7 +425,7 @@ describe('api.client', () => { ), ); - const response = await apiClient.m2mTokens.verifyToken({ + const response = await apiClient.m2m.verifyToken({ token: 'mt_secret_test', }); expect(response.id).toBe('mt_test'); diff --git a/packages/backend/src/api/endpoints/M2MTokenApi.ts b/packages/backend/src/api/endpoints/M2MTokenApi.ts index 4689e5d2724..8ea48c1c105 100644 --- a/packages/backend/src/api/endpoints/M2MTokenApi.ts +++ b/packages/backend/src/api/endpoints/M2MTokenApi.ts @@ -1,5 +1,3 @@ -import { deprecated } from '@clerk/shared/deprecated'; - import { joinPaths } from '../../util/path'; import type { ClerkBackendApiRequestOptions } from '../request'; import type { M2MToken } from '../resources/M2MToken'; @@ -33,17 +31,6 @@ type RevokeM2MTokenParams = { revocationReason?: string | null; }; -type VerifyM2MTokenParamsDeprecated = { - /** - * Custom machine secret key for authentication. - */ - machineSecretKey?: string; - /** - * Machine-to-machine token secret to verify. - */ - secret: string; -}; - type VerifyM2MTokenParams = { /** * Custom machine secret key for authentication. @@ -70,7 +57,7 @@ export class M2MTokenApi extends AbstractAPI { return options; } - async create(params?: CreateM2MTokenParams) { + async createToken(params?: CreateM2MTokenParams) { const { claims = null, machineSecretKey, secondsUntilExpiration = null } = params || {}; const requestOptions = this.#createRequestOptions( @@ -88,7 +75,7 @@ export class M2MTokenApi extends AbstractAPI { return this.request(requestOptions); } - async revoke(params: RevokeM2MTokenParams) { + async revokeToken(params: RevokeM2MTokenParams) { const { m2mTokenId, revocationReason = null, machineSecretKey } = params; this.requireId(m2mTokenId); @@ -107,28 +94,6 @@ export class M2MTokenApi extends AbstractAPI { return this.request(requestOptions); } - /** - * Verify a machine-to-machine token. - * - * @deprecated Use {@link verifyToken} instead. - */ - async verifySecret(params: VerifyM2MTokenParamsDeprecated) { - const { secret, machineSecretKey } = params; - - deprecated('verifySecret', 'Use `verifyToken({ token: mt_xxx })` instead'); - - const requestOptions = this.#createRequestOptions( - { - method: 'POST', - path: joinPaths(basePath, 'verify'), - bodyParams: { secret }, - }, - machineSecretKey, - ); - - return this.request(requestOptions); - } - async verifyToken(params: VerifyM2MTokenParams) { const { token, machineSecretKey } = params; diff --git a/packages/backend/src/api/factory.ts b/packages/backend/src/api/factory.ts index f2228b49ca7..31df669eeb9 100644 --- a/packages/backend/src/api/factory.ts +++ b/packages/backend/src/api/factory.ts @@ -72,7 +72,7 @@ export function createBackendApiClient(options: CreateBackendApiOptions) { jwks: new JwksAPI(request), jwtTemplates: new JwtTemplatesApi(request), machines: new MachineApi(request), - m2mTokens: new M2MTokenApi( + m2m: new M2MTokenApi( buildRequest({ ...options, skipApiVersionInUrl: true, diff --git a/packages/backend/src/tokens/verify.ts b/packages/backend/src/tokens/verify.ts index 32a9803c7ca..284d244049d 100644 --- a/packages/backend/src/tokens/verify.ts +++ b/packages/backend/src/tokens/verify.ts @@ -206,7 +206,7 @@ async function verifyM2MToken( ): Promise> { try { const client = createBackendApiClient(options); - const verifiedToken = await client.m2mTokens.verifyToken({ token }); + const verifiedToken = await client.m2m.verifyToken({ token }); return { data: verifiedToken, tokenType: TokenType.M2MToken, errors: undefined }; } catch (err: any) { return handleClerkAPIError(TokenType.M2MToken, err, 'Machine token not found');