Better OAuth error logging

This commit is contained in:
Konstantin Wohlwend 2025-09-08 22:17:33 -07:00
parent 124539007e
commit 90411e29df
3 changed files with 16 additions and 2 deletions

View File

@ -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({

View File

@ -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();

View File

@ -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,