Skip to content

Commit 799abc2

Browse files
authored
fix(backend): Fix getToken() from getAuth() return value in v5 (clerk#2539)
1 parent e4ef3cd commit 799abc2

3 files changed

Lines changed: 73 additions & 7 deletions

File tree

.changeset/eight-cherries-tan.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
'@clerk/backend': major
3+
---
4+
5+
Change `SessionApi.getToken()` to return consistent `{ data, errors }` return value
6+
and fix the `getToken()` from requestState to have the same return behavior as v4
7+
(return Promise<string> or throw error).
8+
This change fixes issues with `getToken()` in `@clerk/nextjs` / `@clerk/remix` / `@clerk/fastify` / `@clerk/sdk-node` / `gatsby-plugin-clerk`:
9+
10+
Example:
11+
```typescript
12+
import { getAuth } from '@clerk/nextjs/server';
13+
14+
const { getToken } = await getAuth(...);
15+
const jwtString = await getToken(...);
16+
```
17+
18+
The change in `SessionApi.getToken()` return value is a breaking change, to keep the existing behavior use the following:
19+
```typescript
20+
import { ClerkAPIResponseError } from '@clerk/shared/error';
21+
22+
const response = await clerkClient.sessions.getToken(...);
23+
24+
if (response.errors) {
25+
const { status, statusText, clerkTraceId } = response;
26+
const error = new ClerkAPIResponseError(statusText || '', {
27+
data: [],
28+
status: Number(status || ''),
29+
clerkTraceId,
30+
});
31+
error.errors = response.errors;
32+
33+
throw error;
34+
}
35+
36+
// the value of the v4 `clerkClient.sessions.getToken(...)`
37+
const jwtString = response.data.jwt;
38+
```

packages/backend/src/api/endpoints/SessionApi.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,9 @@ export class SessionAPI extends AbstractAPI {
4949

5050
public async getToken(sessionId: string, template: string) {
5151
this.requireId(sessionId);
52-
return (
53-
(await this.request<Token>({
54-
method: 'POST',
55-
path: joinPaths(basePath, sessionId, 'tokens', template || ''),
56-
})) as any
57-
).jwt;
52+
return this.request<Token>({
53+
method: 'POST',
54+
path: joinPaths(basePath, sessionId, 'tokens', template || ''),
55+
});
5856
}
5957
}

packages/backend/src/tokens/authObjects.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ClerkAPIResponseError } from '@clerk/shared/error';
12
import type {
23
ActClaim,
34
CheckAuthorizationWithCustomPermissions,
@@ -10,6 +11,7 @@ import type {
1011

1112
import type { CreateBackendApiOptions } from '../api';
1213
import { createBackendApiClient } from '../api';
14+
import type { ClerkBackendApiResponse } from '../api/request';
1315
import type { AuthenticateContext } from './authenticateContext';
1416

1517
type AuthObjectDebugData = Record<string, any>;
@@ -73,6 +75,27 @@ const createDebug = (data: AuthObjectDebugData | undefined) => {
7375
};
7476
};
7577

78+
// This helper is introduced as compat layer between the v4 and v5 implementations to keep the
79+
// exposed top-level getToken API the same since it's critical and there are already a lot of
80+
// breaking changes.
81+
// TODO: Revamp AuthObject `getToken()` to return { data, errors } in next major version
82+
const throwResponseErrors = <T>(response: ClerkBackendApiResponse<T>): never => {
83+
// used to by-pass type-safety for the `{ status, statusText, clerkTraceId } = response` line below
84+
if (!response.errors) {
85+
throw new Error('no error to throw');
86+
}
87+
88+
const { status, statusText, clerkTraceId } = response;
89+
const error = new ClerkAPIResponseError(statusText || '', {
90+
data: [],
91+
status: Number(status || ''),
92+
clerkTraceId,
93+
});
94+
error.errors = response.errors;
95+
96+
throw error;
97+
};
98+
7699
/**
77100
* @internal
78101
*/
@@ -93,7 +116,14 @@ export function signedInAuthObject(
93116
const getToken = createGetToken({
94117
sessionId,
95118
sessionToken: authenticateContext.sessionToken || '',
96-
fetcher: (...args) => apiClient.sessions.getToken(...args),
119+
fetcher: async (...args) => {
120+
const response = await apiClient.sessions.getToken(...args);
121+
if (response.errors) {
122+
return throwResponseErrors(response);
123+
}
124+
125+
return response.data.jwt;
126+
},
97127
});
98128

99129
return {

0 commit comments

Comments
 (0)