Skip to content

Commit 013c892

Browse files
amrit110claude
andcommitted
Fix build errors in catalog-analytics service
- Fix TypeScript error in logout route by providing fallback redirect URI - Fix Tailwind CSS configuration (use v3 syntax instead of v4) - Add missing dependencies (tailwindcss, postcss, autoprefixer, framer-motion, lucide-react) - Fix auth callback to use GoogleOAuthClient directly for user info - Add postcss and tailwind config files Build now completes successfully with no errors. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent 64798b3 commit 013c892

File tree

7 files changed

+943
-394
lines changed

7 files changed

+943
-394
lines changed
Lines changed: 69 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,99 @@
11
import { NextRequest, NextResponse } from 'next/server';
2-
import { exchangeCodeForTokens, getUserInfo } from '@vector-institute/aieng-auth-core';
2+
import { GoogleOAuthClient } from '@vector-institute/aieng-auth-core';
33
import { authConfig } from '@/lib/auth-config';
44
import { createSession } from '@/lib/session';
5+
import { cookies } from 'next/headers';
56

67
export const dynamic = 'force-dynamic';
78

9+
function getBaseUrl(request: NextRequest): string {
10+
return process.env.NEXT_PUBLIC_APP_URL || new URL(request.url).origin;
11+
}
12+
813
export async function GET(request: NextRequest) {
14+
const baseUrl = getBaseUrl(request);
15+
916
try {
10-
const { searchParams } = request.nextUrl;
17+
const searchParams = request.nextUrl.searchParams;
1118
const code = searchParams.get('code');
1219
const state = searchParams.get('state');
20+
const error = searchParams.get('error');
21+
22+
if (error) {
23+
return NextResponse.redirect(`${baseUrl}/login?error=${encodeURIComponent(error)}`);
24+
}
1325

14-
if (!code) {
15-
return NextResponse.json({ error: 'Missing authorization code' }, { status: 400 });
26+
if (!code || !state) {
27+
return NextResponse.redirect(`${baseUrl}/login?error=invalid_callback`);
1628
}
1729

18-
// Verify state to prevent CSRF
19-
const storedState = request.cookies.get('oauth_state')?.value;
20-
if (!state || state !== storedState) {
21-
return NextResponse.json({ error: 'Invalid state parameter' }, { status: 400 });
30+
// Verify state
31+
const cookieStore = await cookies();
32+
const storedState = cookieStore.get('oauth_state')?.value;
33+
if (state !== storedState) {
34+
return NextResponse.redirect(`${baseUrl}/login?error=invalid_state`);
2235
}
2336

24-
// Get PKCE verifier from cookie
25-
const pkceVerifier = request.cookies.get('pkce_verifier')?.value;
26-
if (!pkceVerifier) {
27-
return NextResponse.json({ error: 'Missing PKCE verifier' }, { status: 400 });
37+
// Get PKCE verifier
38+
const verifier = cookieStore.get('pkce_verifier')?.value;
39+
if (!verifier) {
40+
return NextResponse.redirect(`${baseUrl}/login?error=missing_verifier`);
2841
}
2942

30-
// Exchange authorization code for tokens
31-
const tokens = await exchangeCodeForTokens(
43+
// Exchange code for tokens
44+
const body = new URLSearchParams({
45+
grant_type: 'authorization_code',
3246
code,
33-
authConfig.clientId,
34-
authConfig.clientSecret,
35-
authConfig.redirectUri,
36-
pkceVerifier
37-
);
47+
redirect_uri: authConfig.redirectUri,
48+
client_id: authConfig.clientId,
49+
client_secret: authConfig.clientSecret,
50+
code_verifier: verifier,
51+
});
52+
53+
const response = await fetch('https://oauth2.googleapis.com/token', {
54+
method: 'POST',
55+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
56+
body: body.toString(),
57+
});
58+
59+
if (!response.ok) {
60+
const errorData = await response.json().catch(() => ({}));
61+
console.error('Token exchange failed:', errorData);
62+
return NextResponse.redirect(`${baseUrl}/login?error=token_exchange_failed`);
63+
}
64+
65+
const data = await response.json();
66+
const tokens = {
67+
accessToken: data.access_token,
68+
refreshToken: data.refresh_token,
69+
tokenType: data.token_type || 'Bearer',
70+
expiresIn: data.expires_in,
71+
scope: data.scope,
72+
};
3873

39-
// Get user information
40-
const user = await getUserInfo(tokens.accessToken);
74+
// Get user info
75+
const client = new GoogleOAuthClient(authConfig);
76+
const user = await client.getUserInfo(tokens.accessToken);
4177

42-
// Check if user's email domain is allowed
78+
// Validate domain if configured
4379
if (authConfig.allowedDomains && authConfig.allowedDomains.length > 0) {
44-
const emailDomain = user.email.split('@')[1];
45-
if (!authConfig.allowedDomains.includes(emailDomain)) {
46-
return NextResponse.json(
47-
{ error: 'Access denied: Email domain not authorized' },
48-
{ status: 403 }
49-
);
80+
const domain = user.email?.split('@')[1];
81+
if (!domain || !authConfig.allowedDomains.includes(domain)) {
82+
return NextResponse.redirect(`${baseUrl}/login?error=unauthorized_domain`);
5083
}
5184
}
5285

53-
// Create authenticated session
86+
// Create session
5487
await createSession(tokens, user);
5588

56-
// Clear temporary cookies and redirect to analytics
57-
const response = NextResponse.redirect(new URL('/analytics', request.url));
58-
response.cookies.delete('pkce_verifier');
59-
response.cookies.delete('oauth_state');
89+
// Clean up temporary cookies and redirect to analytics
90+
const redirectResponse = NextResponse.redirect(`${baseUrl}/analytics`);
91+
redirectResponse.cookies.delete('pkce_verifier');
92+
redirectResponse.cookies.delete('oauth_state');
6093

61-
return response;
94+
return redirectResponse;
6295
} catch (error) {
63-
console.error('OAuth callback error:', error);
64-
return NextResponse.json(
65-
{
66-
error: 'Authentication failed',
67-
details: error instanceof Error ? error.message : 'Unknown error',
68-
},
69-
{ status: 500 }
70-
);
96+
console.error('Callback error:', error);
97+
return NextResponse.redirect(`${baseUrl}/login?error=authentication_failed`);
7198
}
7299
}

catalog-analytics/app/api/auth/logout/route.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ export async function GET(request: NextRequest) {
99
// Destroy the session
1010
await destroySession();
1111

12-
// Redirect to post-logout URI
13-
return NextResponse.redirect(authConfig.postLogoutRedirectUri);
12+
// Redirect to post-logout URI or base URL
13+
const redirectUri = authConfig.postLogoutRedirectUri || new URL(request.url).origin;
14+
return NextResponse.redirect(redirectUri);
1415
} catch (error) {
1516
console.error('Logout error:', error);
1617
return NextResponse.json({ error: 'Logout failed' }, { status: 500 });

0 commit comments

Comments
 (0)