diff --git a/apps/backend/src/app/api/latest/connected-accounts/[user_id]/[provider_id]/access-token/crud.tsx b/apps/backend/src/app/api/latest/connected-accounts/[user_id]/[provider_id]/access-token/crud.tsx index 824ccdda6..093a52a0d 100644 --- a/apps/backend/src/app/api/latest/connected-accounts/[user_id]/[provider_id]/access-token/crud.tsx +++ b/apps/backend/src/app/api/latest/connected-accounts/[user_id]/[provider_id]/access-token/crud.tsx @@ -111,14 +111,14 @@ export const connectedAccountAccessTokenCrudHandlers = createLazyProxy(() => cre scope: data.scope, }); } catch (error) { - captureError('oauth-access-token-refresh-error', { + captureError('oauth-access-token-refresh-error', new StackAssertionError('Error refreshing access token — this might be nothing bad and the refresh token might just be expired, but we should instead of throwing an error check whether this is a legit error or not', { error, tenancyId: auth.tenancy.id, providerId: params.provider_id, userId: params.user_id, refreshToken: token.refreshToken, scope: data.scope, - }); + })); // mark the token as invalid await prisma.oAuthToken.update({ diff --git a/apps/backend/src/oauth/providers/github.tsx b/apps/backend/src/oauth/providers/github.tsx index 23b7ab980..260109bac 100644 --- a/apps/backend/src/oauth/providers/github.tsx +++ b/apps/backend/src/oauth/providers/github.tsx @@ -1,5 +1,6 @@ import { getEnvVariable } from "@stackframe/stack-shared/dist/utils/env"; import { StackAssertionError, StatusError } from "@stackframe/stack-shared/dist/utils/errors"; +import { getJwtInfo } from "@stackframe/stack-shared/dist/utils/jwt"; import { OAuthUserInfo, validateUserInfo } from "../utils"; import { OAuthBaseProvider, TokenSet } from "./base"; @@ -42,6 +43,7 @@ export class GithubProvider extends OAuthBaseProvider { hasAccessToken: !!tokenSet.accessToken, hasRefreshToken: !!tokenSet.refreshToken, accessTokenExpiredAt: tokenSet.accessTokenExpiredAt, + jwtInfo: await getJwtInfo({ jwt: tokenSet.accessToken }), }); } const rawUserInfo = await rawUserInfoRes.json(); diff --git a/packages/init-stack/src/index.ts b/packages/init-stack/src/index.ts index 00cbb34fe..11059a178 100644 --- a/packages/init-stack/src/index.ts +++ b/packages/init-stack/src/index.ts @@ -234,8 +234,16 @@ async function main(): Promise { // Install dependencies console.log(); console.log(colorize.bold`Installing dependencies...`); - const installCommand = packageManager === "yarn" ? "yarn add" : `${packageManager} install`; - await shellNicelyFormatted(`${installCommand} ${packagesToInstall.join(' ')}`, { + const installCommandMap = new Map([ + ["npm", "npm install"], + ["yarn", "yarn add"], + ["pnpm", "pnpm add"], + ["bun", "bun add"], + ]); + const installCommand = installCommandMap.get(packageManager) ?? `${packageManager} install`; + // Quote each package name to avoid shell interpretation of env-overridden values. + const safePackages = packagesToInstall.map((p) => JSON.stringify(p)); + await shellNicelyFormatted(`${installCommand} ${safePackages.join(' ')}`, { shell: true, cwd: projectPath, }); diff --git a/packages/stack-shared/src/utils/jwt.tsx b/packages/stack-shared/src/utils/jwt.tsx index 08c701c98..0939a0056 100644 --- a/packages/stack-shared/src/utils/jwt.tsx +++ b/packages/stack-shared/src/utils/jwt.tsx @@ -7,6 +7,7 @@ import { getEnvVariable } from "./env"; import { StackAssertionError } from "./errors"; import { globalVar } from "./globals"; import { pick } from "./objects"; +import { Result } from "./results"; function getStackServerSecret() { const STACK_SERVER_SECRET = getEnvVariable("STACK_SERVER_SECRET"); @@ -18,6 +19,17 @@ function getStackServerSecret() { return STACK_SERVER_SECRET; } +export async function getJwtInfo(options: { + jwt: string, +}) { + try { + const decodedJwt = jose.decodeJwt(options.jwt); + return Result.ok({ payload: decodedJwt }); + } catch (e) { + return Result.error(e); + } +} + export async function signJWT(options: { issuer: string, audience: string,