Skip to content

Commit 0c8e02c

Browse files
authored
Fetch the complete user info when the user logs in using WorkOS (cline#7026)
* Fetch the complete user info when the user logs in using WorkOS * Add changeset * fallback to token data
1 parent b636018 commit 0c8e02c

File tree

2 files changed

+36
-17
lines changed

2 files changed

+36
-17
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"claude-dev": patch
3+
---
4+
5+
fix remote config

src/services/auth/providers/ClineAuthProvider.ts

Lines changed: 31 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1+
import axios from "axios"
12
import { ClineEnv, EnvironmentConfig } from "@/config"
23
import { Controller } from "@/core/controller"
34
import { HostProvider } from "@/hosts/host-provider"
45
import { Logger } from "@/services/logging/Logger"
56
import { CLINE_API_ENDPOINT } from "@/shared/cline/api"
6-
import type { ClineAuthInfo } from "../AuthService"
7+
import type { ClineAccountUserInfo, ClineAuthInfo } from "../AuthService"
78
import { IAuthProvider } from "./IAuthProvider"
89

910
interface ClineAuthApiUser {
@@ -175,20 +176,14 @@ export class ClineAuthProvider implements IAuthProvider {
175176
throw new Error("Failed to exchange authorization code for access token")
176177
}
177178

179+
const userInfo = await this.fetchRemoteUserInfo(data.data)
180+
178181
return {
179182
idToken: data.data.accessToken,
180183
// data.data.expiresAt example: "2025-09-17T03:43:57Z"; store in seconds
181184
expiresAt: new Date(data.data.expiresAt).getTime() / 1000,
182185
refreshToken: data.data.refreshToken || refreshToken,
183-
userInfo: {
184-
createdAt: new Date().toISOString(),
185-
email: data.data.userInfo.email || "",
186-
id: data.data.userInfo.clineUserId || "",
187-
displayName: data.data.userInfo.name || "",
188-
organizations: [],
189-
appBaseUrl: this.config.appBaseUrl,
190-
subject: data.data.userInfo.subject || "",
191-
},
186+
userInfo,
192187
provider: this.name,
193188
}
194189
} catch (error: any) {
@@ -280,17 +275,13 @@ export class ClineAuthProvider implements IAuthProvider {
280275
throw new Error("Invalid token response from server")
281276
}
282277

278+
const userInfo = await this.fetchRemoteUserInfo(tokenData)
279+
283280
// Store the tokens and user info
284281
const clineAuthInfo = {
285282
idToken: tokenData.accessToken,
286283
refreshToken: tokenData.refreshToken,
287-
userInfo: {
288-
id: tokenData.userInfo.clineUserId || "",
289-
email: tokenData.userInfo.email || "",
290-
displayName: tokenData.userInfo.name || "",
291-
createdAt: new Date().toISOString(),
292-
organizations: [],
293-
},
284+
userInfo,
294285
expiresAt: new Date(tokenData.expiresAt).getTime() / 1000, // "2025-09-17T04:32:24.842636548Z"
295286
provider: this.name,
296287
}
@@ -303,4 +294,27 @@ export class ClineAuthProvider implements IAuthProvider {
303294
throw error
304295
}
305296
}
297+
298+
private async fetchRemoteUserInfo(tokenData: ClineAuthApiTokenExchangeResponse["data"]): Promise<ClineAccountUserInfo> {
299+
try {
300+
const userResponse = await axios.get(`${ClineEnv.config().apiBaseUrl}/api/v1/users/me`, {
301+
headers: {
302+
Authorization: `Bearer workos:${tokenData.accessToken}`,
303+
},
304+
})
305+
306+
return userResponse.data.data
307+
} catch (error) {
308+
console.error("Error fetching user info:", error)
309+
310+
// If fetching user info fail for whatever reason, fallback to the token data and refetch on token expiry (10 minutes)
311+
return {
312+
id: tokenData.userInfo.clineUserId || "",
313+
email: tokenData.userInfo.email || "",
314+
displayName: tokenData.userInfo.name || "",
315+
createdAt: new Date().toISOString(),
316+
organizations: [],
317+
}
318+
}
319+
}
306320
}

0 commit comments

Comments
 (0)