Google oauth redirecting to /api/auth

Hi, I'm setting up Google oauth in my app but when I login through google I get redirected to /api/auth (which 404s) and I can't figure out why its redirecting here. These are my network requests when logging in:
POST /api/auth/sign-in/social 200 in 514ms
GET /api/auth/callback/google?state=blGZzt7ykTo8iY1RAmeXfAKb9Yf6h6-u&code=XXXXXXXXXXXXXXXXXXXXXXXX&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&authuser=0&prompt=none 302 in 1235ms
GET /api/auth 404 in 228ms
POST /api/auth/sign-in/social 200 in 514ms
GET /api/auth/callback/google?state=blGZzt7ykTo8iY1RAmeXfAKb9Yf6h6-u&code=XXXXXXXXXXXXXXXXXXXXXXXX&scope=email+profile+openid+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.email+https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fuserinfo.profile&authuser=0&prompt=none 302 in 1235ms
GET /api/auth 404 in 228ms
My setup is:
// lib/auth.ts
import { betterAuth } from 'better-auth'
import { db } from './db'
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { nextCookies } from 'better-auth/next-js';

export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg"
}),
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
}
},
plugins: [nextCookies()]
})
// lib/auth.ts
import { betterAuth } from 'better-auth'
import { db } from './db'
import { drizzleAdapter } from "better-auth/adapters/drizzle";
import { nextCookies } from 'better-auth/next-js';

export const auth = betterAuth({
database: drizzleAdapter(db, {
provider: "pg"
}),
socialProviders: {
google: {
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
}
},
plugins: [nextCookies()]
})
// lib/auth-client.ts
import { createAuthClient } from "better-auth/react"

export function getBaseURL() {
const baseURL =
process.env.SITE_URL || // Production
process.env.VERCEL_URL || // Preview (Vercel)
"http://localhost:3000"; // Development

return baseURL.includes("http") ? baseURL : `https://${baseURL}`;
}

export const authClient = createAuthClient({
baseURL: getBaseURL()
});
// lib/auth-client.ts
import { createAuthClient } from "better-auth/react"

export function getBaseURL() {
const baseURL =
process.env.SITE_URL || // Production
process.env.VERCEL_URL || // Preview (Vercel)
"http://localhost:3000"; // Development

return baseURL.includes("http") ? baseURL : `https://${baseURL}`;
}

export const authClient = createAuthClient({
baseURL: getBaseURL()
});
And for my login onClick I'm doing
"use client";

import Link from "next/link";
import { Icons } from "@/components/icons";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { cn } from "@/lib/utils";
import { authClient } from "@/lib/auth-client";

export function LoginComponent({ className }: { className?: string }) {
return (
<Card
className={cn(
"w-full grid md:grid-cols-3 overflow-hidden place-items-center text-center",
className
)}
>
<video
src="https://assets.clip.studio/reddit_preview.webm"
autoPlay
muted
loop
playsInline
className="col-span-1 hidden md:block w-full h-full object-cover"
/>

<div className="md:col-span-2">
<CardHeader className="flex flex-col items-center">
<Avatar className="size-24">
<AvatarImage src="/logo.svg" />
<AvatarFallback>CS</AvatarFallback>
</Avatar>
<CardTitle className="text-2xl font-medium">
Get Started with Refract
</CardTitle>
<CardDescription>
Sign in or create an account to get started
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid gap-4">
<Button
variant="secondary"
className="w-full"
onClick={async () => {
await authClient.signIn.social({
provider: "google",
});
}}
>
<Icons.google className="mr-2 h-4 w-4 dark:invert" />
Login with Google
</Button>
</div>

<div className="text-[11px] text-center mt-6">
<span>By signing up, you agree to our</span>{" "}
<Link href="/terms" className="underline">
Terms
</Link>{" "}
<span>and</span>{" "}
<Link href="/privacy" className="underline">
Privacy Policy
</Link>
.
</div>
</CardContent>
</div>
</Card>
);
}
"use client";

import Link from "next/link";
import { Icons } from "@/components/icons";
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from "@/components/ui/card";
import { cn } from "@/lib/utils";
import { authClient } from "@/lib/auth-client";

export function LoginComponent({ className }: { className?: string }) {
return (
<Card
className={cn(
"w-full grid md:grid-cols-3 overflow-hidden place-items-center text-center",
className
)}
>
<video
src="https://assets.clip.studio/reddit_preview.webm"
autoPlay
muted
loop
playsInline
className="col-span-1 hidden md:block w-full h-full object-cover"
/>

<div className="md:col-span-2">
<CardHeader className="flex flex-col items-center">
<Avatar className="size-24">
<AvatarImage src="/logo.svg" />
<AvatarFallback>CS</AvatarFallback>
</Avatar>
<CardTitle className="text-2xl font-medium">
Get Started with Refract
</CardTitle>
<CardDescription>
Sign in or create an account to get started
</CardDescription>
</CardHeader>
<CardContent>
<div className="grid gap-4">
<Button
variant="secondary"
className="w-full"
onClick={async () => {
await authClient.signIn.social({
provider: "google",
});
}}
>
<Icons.google className="mr-2 h-4 w-4 dark:invert" />
Login with Google
</Button>
</div>

<div className="text-[11px] text-center mt-6">
<span>By signing up, you agree to our</span>{" "}
<Link href="/terms" className="underline">
Terms
</Link>{" "}
<span>and</span>{" "}
<Link href="/privacy" className="underline">
Privacy Policy
</Link>
.
</div>
</CardContent>
</div>
</Card>
);
}
4 Replies
Ho-kage
Ho-kage6d ago
Did you configure the redirect URL in your google console?
No description
gursheys
gursheysOP6d ago
Ye i have it under here
No description
gursheys
gursheysOP6d ago
Figured out auth flow was working but still dont know why it was redirecting there after, updated my callback url to an actual page and seems to work fine 🤷‍♀️
Ho-kage
Ho-kage6d ago
I was actually just about to say because I looked at my implementation Glad you got that sorted

Did you find this page helpful?