initial commit
This commit is contained in:
113
app/api/auth/google/callback/route.ts
Normal file
113
app/api/auth/google/callback/route.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getGoogleUser } from '@/lib/google-oauth'
|
||||
import { generateTokens } from '@/lib/jwt'
|
||||
import connectDB from '@/lib/mongodb'
|
||||
import { User } from '@/models/user'
|
||||
import { appConfig } from '@/lib/env'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const { searchParams } = new URL(request.url)
|
||||
const code = searchParams.get('code')
|
||||
const state = searchParams.get('state')
|
||||
const error = searchParams.get('error')
|
||||
|
||||
// Handle OAuth errors
|
||||
if (error) {
|
||||
return NextResponse.redirect(
|
||||
new URL(`/auth?error=${encodeURIComponent(error)}`, appConfig.appUrl)
|
||||
)
|
||||
}
|
||||
|
||||
// Validate required parameters
|
||||
if (!code || state !== 'google_oauth') {
|
||||
return NextResponse.redirect(new URL('/auth?error=invalid_oauth_callback', appConfig.appUrl))
|
||||
}
|
||||
|
||||
// Get user info from Google
|
||||
const googleUser = await getGoogleUser(code)
|
||||
|
||||
// Connect to database
|
||||
await connectDB()
|
||||
|
||||
// Check if user exists
|
||||
let user = await User.findOne({
|
||||
$or: [
|
||||
{ email: googleUser.email.toLowerCase() },
|
||||
{ providerId: googleUser.id, provider: 'google' },
|
||||
],
|
||||
})
|
||||
|
||||
if (!user) {
|
||||
// Create new user
|
||||
user = new User({
|
||||
email: googleUser.email.toLowerCase(),
|
||||
name: googleUser.name,
|
||||
provider: 'google',
|
||||
providerId: googleUser.id,
|
||||
avatar: googleUser.picture || undefined,
|
||||
isVerified: googleUser.verified_email,
|
||||
lastLogin: new Date(),
|
||||
})
|
||||
} else {
|
||||
// Update existing user with Google info (preserve original provider)
|
||||
// Only link Google if user doesn't already have a local account
|
||||
if (user.provider !== 'local') {
|
||||
user.provider = 'google'
|
||||
user.providerId = googleUser.id
|
||||
} else {
|
||||
// For local users, just add Google info without changing provider
|
||||
if (!user.providerId) {
|
||||
user.providerId = googleUser.id
|
||||
}
|
||||
}
|
||||
|
||||
// Update other info safely
|
||||
user.name = googleUser.name
|
||||
user.isVerified = googleUser.verified_email || user.isVerified
|
||||
user.lastLogin = new Date()
|
||||
|
||||
// Update avatar only if user doesn't have one
|
||||
if (googleUser.picture && !user.avatar) {
|
||||
user.avatar = googleUser.picture
|
||||
}
|
||||
}
|
||||
|
||||
// Generate tokens
|
||||
const { accessToken, refreshToken } = generateTokens({
|
||||
userId: user._id.toString(),
|
||||
email: user.email,
|
||||
role: user.role,
|
||||
})
|
||||
|
||||
// Update user's refresh token
|
||||
user.refreshToken = refreshToken
|
||||
await user.save()
|
||||
|
||||
// Create redirect response using the public app URL
|
||||
const redirectURL = new URL('/dashboard', appConfig.appUrl)
|
||||
const response = NextResponse.redirect(redirectURL)
|
||||
|
||||
// Set HTTP-only cookies
|
||||
response.cookies.set('accessToken', accessToken, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
maxAge: 15 * 60, // 15 minutes
|
||||
path: '/',
|
||||
})
|
||||
|
||||
response.cookies.set('refreshToken', refreshToken, {
|
||||
httpOnly: true,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
sameSite: 'lax',
|
||||
maxAge: 7 * 24 * 60 * 60, // 7 days
|
||||
path: '/',
|
||||
})
|
||||
|
||||
return response
|
||||
} catch (error) {
|
||||
console.error('Google OAuth callback error:', error)
|
||||
return NextResponse.redirect(new URL('/auth?error=oauth_callback_failed', appConfig.appUrl))
|
||||
}
|
||||
}
|
||||
22
app/api/auth/google/route.ts
Normal file
22
app/api/auth/google/route.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { NextRequest, NextResponse } from 'next/server'
|
||||
import { getGoogleAuthURL } from '@/lib/google-oauth'
|
||||
|
||||
export async function GET(request: NextRequest) {
|
||||
try {
|
||||
const authURL = getGoogleAuthURL()
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
data: { authURL },
|
||||
})
|
||||
} catch (error) {
|
||||
console.error('Google OAuth URL generation error:', error)
|
||||
return NextResponse.json(
|
||||
{
|
||||
success: false,
|
||||
error: { message: 'Failed to generate Google auth URL', code: 'OAUTH_ERROR' },
|
||||
},
|
||||
{ status: 500 }
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user