core/apps/webapp/app/utils/oauth2-middleware.ts
Harshith Mullapudi 8d9ddcf375
Fix: core cli to work with core repo (#26)
* Fix: core cli to work with core repo

* Fix: cli working and mcp proxy
2025-07-22 10:17:40 +05:30

112 lines
2.4 KiB
TypeScript

import { json } from "@remix-run/node";
import { oauth2Service } from "~/services/oauth2.server";
export interface OAuth2Context {
user: {
id: string;
email: string;
name: string | null;
displayName: string | null;
avatarUrl: string | null;
};
client: {
id: string;
clientId: string;
name: string;
};
token: {
id: string;
token: string;
scope: string | null;
expiresAt: Date;
};
}
export async function requireOAuth2(request: Request): Promise<OAuth2Context> {
const authHeader = request.headers.get("authorization");
if (!authHeader || !authHeader.startsWith("Bearer ")) {
throw json(
{
error: "invalid_token",
error_description: "Missing or invalid authorization header",
},
{ status: 401 },
);
}
const token = authHeader.substring(7); // Remove "Bearer " prefix
try {
const accessToken = await oauth2Service.validateAccessToken(token);
return {
user: {
id: accessToken.user.id,
email: accessToken.user.email,
name: accessToken.user.name,
displayName: accessToken.user.displayName,
avatarUrl: accessToken.user.avatarUrl,
},
client: {
id: accessToken.client.id,
clientId: accessToken.client.clientId,
name: accessToken.client.name,
},
token: {
id: accessToken.id,
token: accessToken.token,
scope: accessToken.scope,
expiresAt: accessToken.expiresAt,
},
};
} catch (error) {
throw json(
{
error: "invalid_token",
error_description: "Invalid or expired access token",
},
{ status: 401 },
);
}
}
export async function getOAuth2Context(
request: Request,
): Promise<OAuth2Context | null> {
try {
return await requireOAuth2(request);
} catch (error) {
return null;
}
}
export function hasScope(
context: OAuth2Context,
requiredScope: string,
): boolean {
if (!context.token.scope) {
return false;
}
const scopes = context.token.scope.split(" ");
return scopes.includes(requiredScope);
}
export function requireScope(
context: OAuth2Context,
requiredScope: string,
): void {
if (!hasScope(context, requiredScope)) {
throw json(
{
error: "insufficient_scope",
error_description: `Required scope: ${requiredScope}`,
},
{ status: 403 },
);
}
}
export function getEnvForCommand() {}