fix: oauth token refresh for basic

This commit is contained in:
Harshith Mullapudi 2025-08-28 12:35:13 +05:30
parent d062df14aa
commit 9568b97510
7 changed files with 45 additions and 18 deletions

View File

@ -20,6 +20,27 @@ export const action = async ({ request }: ActionFunctionArgs) => {
const contentType = request.headers.get("content-type");
let body: any;
let tokenRequest: OAuth2TokenRequest;
const authHeader = request.headers.get("authorization");
let basicAuthClientId: string | undefined;
let basicAuthClientSecret: string | undefined;
if (authHeader?.startsWith("Basic ")) {
try {
const encoded = authHeader.slice(6); // Remove "Basic " prefix
const decoded = Buffer.from(encoded, "base64").toString("utf-8");
const [clientId, clientSecret] = decoded.split(":");
basicAuthClientId = clientId;
basicAuthClientSecret = clientSecret;
} catch (error) {
return json(
{
error: OAuth2Errors.INVALID_CLIENT,
error_description: "Invalid Basic authorization header",
},
{ status: 401 },
);
}
}
// Support both JSON and form-encoded data
if (contentType?.includes("application/json")) {
@ -28,8 +49,8 @@ export const action = async ({ request }: ActionFunctionArgs) => {
grant_type: body.grant_type,
code: body.code || undefined,
redirect_uri: body.redirect_uri || undefined,
client_id: body.client_id,
client_secret: body.client_secret || undefined,
client_id: basicAuthClientId || body.client_id,
client_secret: basicAuthClientSecret || body.client_secret || undefined,
code_verifier: body.code_verifier || undefined,
};
} else {
@ -41,8 +62,11 @@ export const action = async ({ request }: ActionFunctionArgs) => {
grant_type: formData.get("grant_type") as string,
code: (formData.get("code") as string) || undefined,
redirect_uri: (formData.get("redirect_uri") as string) || undefined,
client_id: formData.get("client_id") as string,
client_secret: (formData.get("client_secret") as string) || undefined,
client_id: basicAuthClientId || (formData.get("client_id") as string),
client_secret:
basicAuthClientSecret ||
(formData.get("client_secret") as string) ||
undefined,
code_verifier: (formData.get("code_verifier") as string) || undefined,
};
}
@ -70,14 +94,6 @@ export const action = async ({ request }: ActionFunctionArgs) => {
);
}
if (!tokenRequest.client_id || !tokenRequest.client_secret) {
const clientData = await oauth2Service.getClientForCode(
tokenRequest.code,
);
tokenRequest.client_id = clientData.client_id as string;
tokenRequest.client_secret = clientData.client_secret;
}
// Validate client
try {
await oauth2Service.validateClient(

View File

@ -57,13 +57,13 @@ function buildTransportOptions(): MailTransportOptions {
export async function sendMagicLinkEmail(options: any): Promise<void> {
logger.debug("Sending magic link email", {
emailAddress: options.emailAddress,
email: options.email,
});
try {
return await client.send({
email: "magic_link",
to: options.emailAddress,
to: options.email,
magicLink: options.magicLink,
});
} catch (error) {

View File

@ -14,6 +14,7 @@ import { callMemoryTool, memoryTools } from "~/utils/mcp/memory";
import { logger } from "~/services/logger.service";
import { type Response, type Request } from "express";
import { getWorkspaceByUser } from "~/models/workspace.server";
import { Workspace } from "@prisma/client";
const QueryParams = z.object({
source: z.string().optional(),

View File

@ -467,11 +467,15 @@ export class OAuth2Service {
throw new Error(OAuth2Errors.INVALID_GRANT);
}
// Validate PKCE if required
if (authCode.codeChallenge) {
// Validate PKCE if required //TODO: cursor is failing to send right pkce
if (
authCode.codeChallenge &&
params.redirectUri.includes("cursor:://anysphere")
) {
if (!params.codeVerifier) {
throw new Error(OAuth2Errors.INVALID_REQUEST);
}
if (
!this.validatePkceChallenge(
params.codeVerifier,

View File

@ -82,7 +82,6 @@ export class MCPSessionManager {
id: session.id,
source: session.source,
integrations: session.integrations,
noIntegrations: session.noIntegrations,
createdAt: session.createdAt,
deleted: session.deleted || undefined,
workspaceId: session.workspaceId || undefined,

View File

@ -21,7 +21,9 @@ async function init() {
? () => viteDevServer.ssrLoadModule("virtual:remix/server-build")
: await import("./build/server/index.js");
const module = build.entry?.module;
const module = viteDevServer
? (await build()).entry.module
: build.entry?.module;
remixHandler = createRequestHandler({ build });

View File

@ -37,6 +37,11 @@ services:
- TRIGGER_SECRET_KEY=${TRIGGER_SECRET_KEY}
- TRIGGER_API_URL=${API_ORIGIN}
- POSTGRES_DB=${POSTGRES_DB}
- EMAIL_TRANSPORT=${EMAIL_TRANSPORT}
- REPLY_TO_EMAIL=${REPLY_TO_EMAIL}
- FROM_EMAIL=${FROM_EMAIL}
- RESEND_API_KEY=${RESEND_API_KEY}
- COHERE_API_KEY=${COHERE_API_KEY}
ports:
- "3033:3000"
depends_on: