fix: github radar app connection errors and clear aod cookie on signout (#4188)

* fix: clear aod cookie on sign out

* fix: propogate github radar connection errors properly

* chore: add `aod` comment
This commit is contained in:
Sid
2025-07-18 13:09:54 +05:30
committed by GitHub
parent bc98c42c79
commit a3b0d86996
4 changed files with 35 additions and 24 deletions
+5
View File
@@ -3,6 +3,11 @@ import { FastifyReply } from "fastify";
import { getConfig } from "@app/lib/config/env"; import { getConfig } from "@app/lib/config/env";
import { logger } from "@app/lib/logger"; import { logger } from "@app/lib/logger";
/**
* `aod` (Auth Origin Domain) cookie is used to store the origin domain of the application when user was last authenticated.
* This is useful for determining the target domain for authentication redirects, especially in cloud deployments.
* It is set only in cloud mode to ensure that the cookie is shared across subdomains.
*/
export function addAuthOriginDomainCookie(res: FastifyReply) { export function addAuthOriginDomainCookie(res: FastifyReply) {
try { try {
const appCfg = getConfig(); const appCfg = getConfig();
@@ -42,6 +42,14 @@ export const registerAuthRoutes = async (server: FastifyZodProvider) => {
maxAge: 0 maxAge: 0
}); });
void res.cookie("aod", "", {
httpOnly: false,
path: "/",
sameSite: "lax",
secure: appCfg.HTTPS_ENABLED,
maxAge: 0
});
return { message: "Successfully logged out" }; return { message: "Successfully logged out" };
} }
}); });
@@ -9,6 +9,7 @@ import { getAppConnectionMethodName } from "@app/services/app-connection/app-con
import { IntegrationUrls } from "@app/services/integration-auth/integration-list"; import { IntegrationUrls } from "@app/services/integration-auth/integration-list";
import { AppConnection } from "../app-connection-enums"; import { AppConnection } from "../app-connection-enums";
import { GithubTokenRespData, isGithubErrorResponse } from "../github/github-connection-fns";
import { GitHubRadarConnectionMethod } from "./github-radar-connection-enums"; import { GitHubRadarConnectionMethod } from "./github-radar-connection-enums";
import { import {
TGitHubRadarConnection, TGitHubRadarConnection,
@@ -71,13 +72,6 @@ export const listGitHubRadarRepositories = async (appConnection: TGitHubRadarCon
return repositories; return repositories;
}; };
type TokenRespData = {
access_token: string;
scope: string;
token_type: string;
error?: string;
};
export const validateGitHubRadarConnectionCredentials = async (config: TGitHubRadarConnectionConfig) => { export const validateGitHubRadarConnectionCredentials = async (config: TGitHubRadarConnectionConfig) => {
const { credentials, method } = config; const { credentials, method } = config;
@@ -93,10 +87,10 @@ export const validateGitHubRadarConnectionCredentials = async (config: TGitHubRa
}); });
} }
let tokenResp: AxiosResponse<TokenRespData>; let tokenResp: AxiosResponse<GithubTokenRespData>;
try { try {
tokenResp = await request.get<TokenRespData>("https://github.com/login/oauth/access_token", { tokenResp = await request.get<GithubTokenRespData>("https://github.com/login/oauth/access_token", {
params: { params: {
client_id: INF_APP_CONNECTION_GITHUB_RADAR_APP_CLIENT_ID, client_id: INF_APP_CONNECTION_GITHUB_RADAR_APP_CLIENT_ID,
client_secret: INF_APP_CONNECTION_GITHUB_RADAR_APP_CLIENT_SECRET, client_secret: INF_APP_CONNECTION_GITHUB_RADAR_APP_CLIENT_SECRET,
@@ -108,19 +102,27 @@ export const validateGitHubRadarConnectionCredentials = async (config: TGitHubRa
"Accept-Encoding": "application/json" "Accept-Encoding": "application/json"
} }
}); });
if (isGithubErrorResponse(tokenResp?.data)) {
throw new BadRequestError({
message: `Unable to validate credentials: GitHub responded with an error: ${tokenResp.data.error} - ${tokenResp.data.error_description}`
});
}
} catch (e: unknown) { } catch (e: unknown) {
if (e instanceof BadRequestError) {
throw e;
}
throw new BadRequestError({ throw new BadRequestError({
message: `Unable to validate connection: verify credentials` message: `Unable to validate connection: verify credentials`
}); });
} }
if (tokenResp.status !== 200) {
throw new BadRequestError({
message: `Unable to validate credentials: GitHub responded with a status code of ${tokenResp.status} (${tokenResp.statusText}). Verify credentials and try again.`
});
}
if (method === GitHubRadarConnectionMethod.App) { if (method === GitHubRadarConnectionMethod.App) {
if (!tokenResp.data.access_token) {
throw new InternalServerError({ message: `Missing access token: ${tokenResp.data.error}` });
}
const installationsResp = await request.get<{ const installationsResp = await request.get<{
installations: { installations: {
id: number; id: number;
@@ -149,10 +151,6 @@ export const validateGitHubRadarConnectionCredentials = async (config: TGitHubRa
} }
} }
if (!tokenResp.data.access_token) {
throw new InternalServerError({ message: `Missing access token: ${tokenResp.data.error}` });
}
switch (method) { switch (method) {
case GitHubRadarConnectionMethod.App: case GitHubRadarConnectionMethod.App:
return { return {
@@ -144,14 +144,14 @@ export const getGitHubEnvironments = async (appConnection: TGitHubConnection, ow
} }
}; };
type TokenRespData = { export type GithubTokenRespData = {
access_token?: string; access_token?: string;
scope: string; scope: string;
token_type: string; token_type: string;
error?: string; error?: string;
}; };
function isErrorResponse(data: TokenRespData): data is TokenRespData & { export function isGithubErrorResponse(data: GithubTokenRespData): data is GithubTokenRespData & {
error: string; error: string;
error_description: string; error_description: string;
error_uri: string; error_uri: string;
@@ -191,10 +191,10 @@ export const validateGitHubConnectionCredentials = async (config: TGitHubConnect
}); });
} }
let tokenResp: AxiosResponse<TokenRespData>; let tokenResp: AxiosResponse<GithubTokenRespData>;
try { try {
tokenResp = await request.get<TokenRespData>("https://github.com/login/oauth/access_token", { tokenResp = await request.get<GithubTokenRespData>("https://github.com/login/oauth/access_token", {
params: { params: {
client_id: clientId, client_id: clientId,
client_secret: clientSecret, client_secret: clientSecret,
@@ -207,7 +207,7 @@ export const validateGitHubConnectionCredentials = async (config: TGitHubConnect
} }
}); });
if (isErrorResponse(tokenResp?.data)) { if (isGithubErrorResponse(tokenResp?.data)) {
throw new BadRequestError({ throw new BadRequestError({
message: `Unable to validate credentials: GitHub responded with an error: ${tokenResp.data.error} - ${tokenResp.data.error_description}` message: `Unable to validate credentials: GitHub responded with an error: ${tokenResp.data.error} - ${tokenResp.data.error_description}`
}); });