hugex-gh / app /routes /auth.github.callback.tsx
drbh
feat: refactor for linking
dc06026
import { redirect } from "@remix-run/node";
import type { LoaderFunctionArgs } from "@remix-run/node";
import { githubApp } from "~/lib/github-app.server";
import { getSession, commitSession } from "~/lib/session.server";
import { accountLinkingService } from "~/lib/account-linking.server";
export async function loader({ request }: LoaderFunctionArgs) {
const url = new URL(request.url);
const code = url.searchParams.get("code");
const state = url.searchParams.get("state");
const error = url.searchParams.get("error");
const installation_id = url.searchParams.get("installation_id");
const setup_action = url.searchParams.get("setup_action");
console.log('πŸ”„ GitHub OAuth callback received');
if (error) {
console.log('- Error:', error);
}
if (installation_id) {
console.log('- Installation ID:', installation_id);
}
// Handle OAuth errors
if (error) {
console.error("GitHub OAuth error:", error);
return redirect(`/?error=oauth_failed&details=${encodeURIComponent(error)}`);
}
if (!code) {
console.error("No authorization code received");
return redirect("/?error=no_code");
}
try {
// Exchange code for access token and get user info
const userAuth = await githubApp.handleCallback(code, state || undefined);
console.log('βœ… GitHub OAuth successful for user:', userAuth.login);
// Get existing session
const session = await getSession(request.headers.get("Cookie"));
let userSession = session.get('user') || { isLinked: false };
// Add GitHub info to session
userSession.github = {
userId: userAuth.id.toString(),
login: userAuth.login,
name: userAuth.name,
email: userAuth.email,
avatar_url: userAuth.avatar_url,
};
// Check if we can link accounts (if HuggingFace auth exists)
if (userSession.huggingface) {
const linkCheck = accountLinkingService.canLink(
userAuth.id.toString(),
userSession.huggingface.username
);
if (linkCheck.canLink) {
// Create account link
const accountLink = accountLinkingService.createLink(
userAuth.id.toString(),
userAuth.login,
userSession.huggingface.username
);
userSession.isLinked = true;
userSession.linkedAt = accountLink.linkedAt;
console.log(`πŸ”— Accounts automatically linked: ${userAuth.login} ↔ ${userSession.huggingface.username}`);
} else {
console.warn('⚠️ Cannot link accounts:', linkCheck.reason);
userSession.isLinked = false;
}
} else {
console.log('ℹ️ No HuggingFace authentication found, GitHub auth saved for later linking');
userSession.isLinked = false;
}
// Save updated session
session.set('user', userSession);
const redirectUrl = installation_id ? "/install" : "/";
return redirect(redirectUrl, {
headers: {
"Set-Cookie": await commitSession(session),
},
});
} catch (error: any) {
console.error("GitHub callback error:", error);
// Provide more specific error information
let errorCode = "callback_failed";
if (error.message?.includes("bad_verification_code") || error.message?.includes("incorrect or expired")) {
errorCode = "expired_code";
} else if (error.message?.includes("client_id")) {
errorCode = "invalid_client";
}
return redirect(`/?error=${errorCode}&message=${encodeURIComponent(error.message)}`);
}
}