Advertisement
Guest User

Untitled

a guest
Jun 3rd, 2025
44
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 5.55 KB | Source Code | 0 0
  1. import * as jose from "jose";
  2. import {
  3.   GOOGLE_CLIENT_ID,
  4.   GOOGLE_CLIENT_SECRET,
  5.   GOOGLE_REDIRECT_URI,
  6.   COOKIE_NAME,
  7.   REFRESH_COOKIE_NAME,
  8.   COOKIE_MAX_AGE,
  9.   JWT_EXPIRATION_TIME,
  10.   JWT_SECRET,
  11.   COOKIE_OPTIONS,
  12.   REFRESH_TOKEN_EXPIRY,
  13.   REFRESH_COOKIE_OPTIONS,
  14. } from "@/utils/constants";
  15. import User from "@/lib/schemas/users";
  16. import mongoose from "mongoose";
  17.  
  18. const MONGODB_URI = process.env.MONGODB_URI!;
  19.  
  20. const connectDB = async () => {
  21.   if (mongoose.connections[0].readyState) {
  22.     console.log("🚀 Already connected to database.")
  23.     return true
  24.   }
  25.  
  26.   if (!MONGODB_URI) {
  27.     console.error("🔴 MONGODB_URI is not defined.")
  28.     return false
  29.   }
  30.  
  31.   try {
  32.     await mongoose.connect(MONGODB_URI)
  33.     console.log("🚀 Successfully connected to MongoDB.")
  34.     return true
  35.   } catch (error) {
  36.     console.log(process.env.MONGODB_URI);
  37.     console.error("🔴 Failed to connect to MongoDB:", error)
  38.     return false
  39.   }
  40. }
  41.  
  42.  
  43. export async function POST(request: Request) {
  44.   try {
  45.     console.log("=== TOKEN API CALLED ===");
  46.     console.log("Request URL:", request.url);
  47.     console.log("Request method:", request.method);
  48.  
  49.     const body = await request.formData();
  50.     const code = (body as any).get("code") as string;
  51.     const platform = ((body as any).get("platform") as string) || "native";
  52.     console.log("Received code:", code ? "[REDACTED]" : "undefined");
  53.     console.log("Platform:", platform);
  54.  
  55.     if (!code) {
  56.       console.log("No authorization code provided.");
  57.       return Response.json(
  58.         { error: "Missing authorization code" },
  59.         { status: 400 }
  60.       );
  61.     }
  62.  
  63.     const response = await fetch("https://oauth2.googleapis.com/token", {
  64.       method: "POST",
  65.       headers: { "Content-Type": "application/x-www-form-urlencoded" },
  66.       body: new URLSearchParams({
  67.         client_id: GOOGLE_CLIENT_ID,
  68.         client_secret: GOOGLE_CLIENT_SECRET,
  69.         redirect_uri: GOOGLE_REDIRECT_URI,
  70.         grant_type: "authorization_code",
  71.         code: code,
  72.       }),
  73.     });
  74.  
  75.     const data = await response.json();
  76.     console.log("Google token response:", data);
  77.  
  78.     if (!data.id_token) {
  79.       console.log("No id_token in Google response.");
  80.       return Response.json(
  81.         { error: "Missing required parameters" },
  82.         { status: 400 }
  83.       );
  84.     }
  85.  
  86.     const userInfo = jose.decodeJwt(data.id_token) as any;
  87.     console.log("Decoded userInfo:", userInfo);
  88.     const { exp, ...userInfoWithoutExp } = userInfo;
  89.     const sub = userInfo.sub;
  90.     const issuedAt = Math.floor(Date.now() / 1000);
  91.     const jti = crypto.randomUUID();
  92.  
  93.     const accessToken = await new jose.SignJWT(userInfoWithoutExp)
  94.       .setProtectedHeader({ alg: "HS256" })
  95.       .setExpirationTime(JWT_EXPIRATION_TIME)
  96.       .setSubject(sub)
  97.       .setIssuedAt(issuedAt)
  98.       .sign(new TextEncoder().encode(JWT_SECRET));
  99.  
  100.     const refreshToken = await new jose.SignJWT({
  101.       sub,
  102.       jti,
  103.       type: "refresh",
  104.       name: userInfo.name,
  105.       email: userInfo.email,
  106.       picture: userInfo.picture,
  107.       given_name: userInfo.given_name,
  108.       family_name: userInfo.family_name,
  109.       email_verified: userInfo.email_verified,
  110.     })
  111.       .setProtectedHeader({ alg: "HS256" })
  112.       .setExpirationTime(REFRESH_TOKEN_EXPIRY)
  113.       .setIssuedAt(issuedAt)
  114.       .sign(new TextEncoder().encode(JWT_SECRET));
  115.  
  116.     if (data.error) {
  117.       return Response.json(
  118.         {
  119.           error: data.error,
  120.           error_description: data.error_description,
  121.           message:
  122.             "OAuth validation error - please ensure the app complies with Google's OAuth 2.0 policy",
  123.         },
  124.         {
  125.           status: 400,
  126.         }
  127.       );
  128.     }
  129.  
  130.     await connectDB();
  131.  
  132.     const { email, name, picture } = userInfo;
  133.     let user;
  134.     let userId: string | null = null;
  135.     try {
  136.       user = await User.findOne({ email });
  137.       console.log("User found in DB:", user);
  138.       if (!user) {
  139.         user = await User.create({
  140.           email,
  141.           name,
  142.           picture,
  143.           provider: "google",
  144.           providerId: sub,
  145.         });
  146.         console.log("Created new user:", user);
  147.       }
  148.       userId = user._id.toString();
  149.       console.log("User ID:", userId);
  150.     } catch (err) {
  151.       console.error("DB error:", err);
  152.       userId = null;
  153.     }
  154.  
  155.     if (platform === "web") {
  156.       console.log("Setting cookies for web platform.");
  157.       const response = Response.json({
  158.         success: true,
  159.         issuedAt: issuedAt,
  160.         expiresAt: issuedAt + COOKIE_MAX_AGE,
  161.       });
  162.  
  163.       response.headers.set(
  164.         "Set-Cookie",
  165.         `${COOKIE_NAME}=${accessToken}; Max-Age=${COOKIE_OPTIONS.maxAge}; Path=${COOKIE_OPTIONS.path}; ${COOKIE_OPTIONS.httpOnly ? "HttpOnly;" : ""}${COOKIE_OPTIONS.secure ? "Secure;" : ""} SameSite=${COOKIE_OPTIONS.sameSite}`
  166.       );
  167.       response.headers.append(
  168.         "Set-Cookie",
  169.         `${REFRESH_COOKIE_NAME}=${refreshToken}; Max-Age=${REFRESH_COOKIE_OPTIONS.maxAge}; Path=${REFRESH_COOKIE_OPTIONS.path}; ${REFRESH_COOKIE_OPTIONS.httpOnly ? "HttpOnly;" : ""}${REFRESH_COOKIE_OPTIONS.secure ? "Secure;" : ""} SameSite=${REFRESH_COOKIE_OPTIONS.sameSite}`
  170.       );
  171.       return response;
  172.     }
  173.  
  174.     console.log("Returning tokens for native platform.");
  175.     return Response.json({
  176.       accessToken,
  177.       refreshToken,
  178.       user_id: userId || null,
  179.     });
  180.   } catch (err) {
  181.     console.error("UNHANDLED ERROR in token+api.ts:", err);
  182.     return Response.json({ error: "Internal server error" }, { status: 500 });
  183.   }
  184. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement