Social OAuth with Supabase?
Answered
Common paper wasp posted this in #help-forum
Common paper waspOP
I'm trying to implement OAuth through Github with Supabase and I am missing something. If I click my button, I can see the request make its way and it returns an error getting user profile. I'm not sure what's causing this or how to fix it.
I've followed the docs from https://supabase.com/docs/guides/auth/social-login/auth-github?queryGroups=framework&framework=nextjs&queryGroups=environment&environment=client and cannot figure out what I'm missing
https://i.imgur.com/7lBQO9R.png
I've followed the docs from https://supabase.com/docs/guides/auth/social-login/auth-github?queryGroups=framework&framework=nextjs&queryGroups=environment&environment=client and cannot figure out what I'm missing
https://i.imgur.com/7lBQO9R.png
Answered by Common paper wasp
Okay I FINALLY figured this out. It took a lot lmao. Turns out we had it right the entire time and I'm an idiot.
I needed to set read only permissions in my GitHub app for user email. Once I did that, I started getting an SSL error (maybe something to do with doing this on a work laptop that has stricter permissions idk), but running
I'm now successfully able to log the user and check for a login in the layout.
I needed to set read only permissions in my GitHub app for user email. Once I did that, I started getting an SSL error (maybe something to do with doing this on a work laptop that has stricter permissions idk), but running
npm install -g npm --ca="" fixed that issue. I'm now successfully able to log the user and check for a login in the layout.
120 Replies
Common paper waspOP
GithubLoginButton.tsx
import GitHubLoginButton from "@/components/GithubLoginButton";
import GuestbookFeed from "@/components/GuestbookFeed";
export default async function GuestbookLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<section>
<h2>Sign my guestbook</h2>
<div className="flex">
<GitHubLoginButton />
</div>
<div>
{children} <GuestbookFeed />
</div>
</section>
);
} /guestbook/layout.tsximport { createClient } from "@/lib/supabase/server";
const supabase = createClient();
export default async function GuestbookPage() {
const { data: guestbook, error } = await supabase
.from("guestbook")
.select("*");
console.log(guestbook);
console.log(error);
return (
<form method="POST" className="mt-8 relative max-w-[500px] gap-2">
<span className="sr-only"> Comment </span>
<div className="flex space-x-4">
<input
type="text"
name="comment"
placeholder="Say something!"
aria-label="your comment"
id="comment"
required
aria-required="true"
className="bg-neutral-800 p-2 focus:ring-1 focus:outline-none focus:ring-lime-400 focus-visible:ring-lime-400 ring-1 ring-zinc-700 rounded-sm w-full"
/>
<button
type="submit"
className="bg-neutral-800 rounded-sm px-4 py-2 hover:bg-accent-primary hover:text-neutral-900 transition-colors duration-200"
>
Send
</button>
</div>
</form>
);
} /guestbook/page.tsxCommon paper waspOP
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
import { type CookieOptions, createServerClient } from "@supabase/ssr";
export async function GET(request: Request) {
const { searchParams, origin } = new URL(request.url);
const code = searchParams.get("code");
console.log(code);
// if "next" is in param, use it as the redirect URL
const next = searchParams.get("next") ?? "/";
if (code) {
const cookieStore = cookies();
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return cookieStore.get(name)?.value;
},
set(name: string, value: string, options: CookieOptions) {
cookieStore.set({ name, value, ...options });
},
remove(name: string, options: CookieOptions) {
cookieStore.delete({ name, ...options });
},
},
}
);
const { error } = await supabase.auth.exchangeCodeForSession(code);
if (!error) {
return NextResponse.redirect(`${origin}${next}`);
}
return NextResponse.redirect(`${origin}/guestbook`);
}
// return the user to an error page with instructions
return NextResponse.redirect(`${origin}/auth/auth-code-error`);
} /auth/callback/route.tsCommon paper waspOP
Still looking for help
Common paper waspOP
Any ideas? I'm stumped
Golden paper wasp
You have wrong redirectTo set
const { data, error } = await supabase.auth.signInWithOAuth({
provider: "github",
options: {
redirectTo: "http://localhost:3000/api/auth/callback",
scopes: "read:user",
},
});Common paper waspOP
I was struggling with this last night. No matter what I put, I kept getting an error
Do I need the URL Supabase gives me there AND in my GitHub app?
Golden paper wasp
You need the supabase url in github callback url only
In application url enter your application url
Common paper waspOP
Okay that's what I have in the GitHub app, great
Golden paper wasp
Let me know if that fixes the issue
Common paper waspOP
Will do I'll brb just gonna test
Golden paper wasp
Okay
Common paper waspOP
Alright so it "works" in that I get redirected properly according to the route
But with an error haha
/auth/callback?error=server_error&error_code=500&error_description=Error+getting+user+profile+from+external+providerGolden paper wasp
There are some github issues related to it. Firstly check the version. Also where are you getting this error?? In api/auth/callback?
Common paper waspOP
Yeah from my auth/callback
From my route.ts
Golden paper wasp
Is the version same as my repo??
Common paper waspOP
hmmmm
lol im trying to turn the signInWithGithub into an action and failing
Golden paper wasp
Then you will have to import
and have to remove the onClick and create a form
createClient from serverand have to remove the onClick and create a form
Common paper waspOP
oh then nevermind
Don't want that
Here's my Button component now:
"use client";
import { createClient } from "@/lib/supabase/client";
import { redirect } from "next/navigation";
const supabase = createClient();
async function signInWithGithub() {
const { data, error } = await supabase.auth.signInWithOAuth({
provider: "github",
options: {
redirectTo: "http://localhost:3000/auth/callback",
scopes: "read:user",
},
});
if (error) {
console.error(error);
}
if (data.url) {
redirect(data.url); // use the redirect API for your server framework
}
}
export default function GitHubLoginButton() {
return (
<button
id="login"
className="flex items-center justify-center gap-x-2 bg-black p-3 border border-zinc-700 text-neutral-200 mt-4 rounded-lg text-sm font-bold"
onClick={signInWithGithub}
>
Login with Github
</button>
);
}Golden paper wasp
Looks good. Does this work as expected??
Common paper waspOP
Nope lol
I don't see where you're using your signInWithGithub
trying to follow by example
ah I see
yeah, no it redirects to
// return the user to an error page with instructions
return NextResponse.redirect(`${origin}/auth/auth-code-error`);here's the final request before it returns the error
so, it's getting the code from Github properly
And I get this Browser Console error:
Golden paper wasp
Can you check the version
Also please try running my example in your local
"@supabase/ssr": "^0.3.0",
"@supabase/supabase-js": "^2.43.4",Also please try running my example in your local
@Golden paper wasp Can you check the version
"@supabase/ssr": "^0.3.0",
"@supabase/supabase-js": "^2.43.4",
Also please try running my example in your local
Common paper waspOP
Confirmed same version
Common paper waspOP
Is it because I'm using
use client in my Button? You split out the logic of supabase and the button componentGolden paper wasp
You can try it. Make sure callback uri is setup correctly. Match your api route and redirectTo: "http://localhost:3000/auth/callback", value
@Common paper wasp Click to see attachment
Golden paper wasp
this says /auth/v1/callback
but the url in config is different
Common paper waspOP
I updated it to nest it inside an
api folderjust as a preference
and I did update the URI
async function signInWithGithub() {
const { data, error } = await supabase.auth.signInWithOAuth({
provider: "github",
options: {
redirectTo: "http://localhost:3000/api/auth/callback",
scopes: "read:user",
},
});Golden paper wasp
and can you share path of the callback uri??
Common paper waspOP
is that the supabase one?
Golden paper wasp
route.ts?
Common paper waspOP
oh yeah its
app/api/auth/callback/route.tsGolden paper wasp
this seems correct
Common paper waspOP
ugh
Golden paper wasp
Sorry. I was unable to debug this.
If you could provide the minimal reproducible version then I can look further
If you could provide the minimal reproducible version then I can look further
Common paper waspOP
I found an error in the Supabase logs that I'm looking into
"error": "403: {"message":"Resource not accessible by integration","documentation_url":"https://docs.github.com/rest/users/emails#list-email-addresses-for-the-authenticated-user\",\"status\":\"403\"}"
Not entirely sure why it's throwing that
Common paper waspOP
Yep can't figure it out lol
Common paper waspOP
Do I need to have anything in my "Redirect URLs" part of the Auth config on Supabase?
I just put what I thought was right here
@Common paper wasp And I get this Browser Console error:
Golden paper wasp
Can you try useRouter hook instead of redirect as docs says redirect function to be used in a server component or server action only
Golden paper wasp
"use client";
import { createClient } from "@/utils/supabase/client";
import { useRouter } from "next/navigation";
export default function GitHubLoginButton() {
const router = useRouter();
async function signInWithGithub() {
const supabase = createClient();
const { data, error } = await supabase.auth.signInWithOAuth({
provider: "github",
options: {
redirectTo: process.env.NEXT_PUBLIC_SUPABASE_AUTH_CALLBACK,
scopes: "read:user",
},
});
if (error) {
router.push("/error");
}
if (data.url) {
router.push(data.url);
}
}
return (
<button
id="login"
className="flex items-center justify-center gap-x-2 bg-black p-3 border border-zinc-700 text-neutral-200 mt-4 rounded-lg text-sm font-bold"
onClick={signInWithGithub}
>
Login with Github
</button>
);
}Common paper waspOP
Can try
Common paper waspOP
I moved the function into its own file
So shouldn't it be fine?
Common paper waspOP
this is my button
"use client";
import { signInWithGithub } from "@/actions/github-login";
export default function GitHubLoginButton() {
return (
<button
id="login"
className="flex items-center justify-center gap-x-2 bg-black p-3 border border-zinc-700 text-neutral-200 mt-4 rounded-lg text-sm font-bold"
onClick={signInWithGithub}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 496 512"
className="fill-neutral-200 w-5 h-5"
>
<path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3 .3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5 .3-6.2 2.3zm44.2-1.7c-2.9 .7-4.9 2.6-4.6 4.9 .3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3 .7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3 .3 2.9 2.3 3.9 1.6 1 3.6 .7 4.3-.7 .7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3 .7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3 .7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"></path>
</svg>
Login with Github
</button>
);
}so because its using
onClick and calling my function/action and those are server components/actions, it cant use redirect in the button?@Common paper wasp so because its using `onClick` and calling my function/action and those are server components/actions, it cant use `redirect` in the button?
Golden paper wasp
Yeah. Docs mention that it should be used in server comp and server action and to use hooks at client level
Common paper waspOP
Okay so how can I do what you have there but separate out the logic to the necessary parts
Action, button
Common paper waspOP
Just split it how I have it but use useRoute?
Golden paper wasp
useRouter won't work when used in a separate file so you will have to work with combined logic.
I have updated my repo
Common paper waspOP
OK well it doesn't error but it won't log the user now 😄
nevermind, had to add an env variable
nope still not working
wont log on supabase now even
Common paper waspOP
I don't understand what im doing wrong
now I'm getting an NS_BINDING error
Common paper waspOP
I get this https://i.imgur.com/iG1fSVa.png
Common paper waspOP
I've deleted package-lock, removed Clerk (just in case), reinstalled my packages, checked everything...wtf is going on
why is this so difficult
import { cookies } from "next/headers";
import { NextResponse } from "next/server";
import { type CookieOptions, createServerClient } from "@supabase/ssr";
export async function GET(request: Request) {
const { searchParams, origin } = new URL(request.url);
const code = searchParams.get("code");
// if "next" is in param, use it as the redirect URL
const next = searchParams.get("next") ?? "/guestbook";
if (code) {
const cookieStore = cookies();
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
get(name: string) {
return cookieStore.get(name)?.value;
},
set(name: string, value: string, options: CookieOptions) {
cookieStore.set({ name, value, ...options });
},
remove(name: string, options: CookieOptions) {
cookieStore.delete({ name, ...options });
},
},
}
);
const { error } = await supabase.auth.exchangeCodeForSession(code);
if (!error) {
return NextResponse.redirect(`${origin}${next}`);
}
}
// return the user to an error page with instructions
return NextResponse.redirect(`${origin}/auth/auth-code-error`);
}It seems to always hit the last redirect
Common paper waspOP
Yeah I just confirmed that's where its failing. I made an actual error page and it goes to it
Common paper waspOP
sigh
Common paper waspOP
it's getting stuck here somehow
export async function GET(request: Request) {
const { searchParams, origin } = new URL(request.url);
const code = searchParams.get("code");
// if "next" is in param, use it as the redirect URL
const next = searchParams.get("next") ?? "/guestbook";
if (code) {If I log inside the if block anything, it doesn't log
okay if I log the searchParams and origin
URLSearchParams {
'error' => 'server_error',
'error_code' => '500',
'error_description' => 'Error getting user profile from external provider' } http://localhost:3000meaning the issue is occurring before it even gets to the callback
and idk if its on github's end or mine
probably mine lol
That's what logs if I log the response from the supabase middleware
I dont know what else to do
Common paper waspOP
Any help would be appreciated
I'm not sure what I'm doing wrong
Golden paper wasp
Hey there. Sorry for late reply.
I clone the repo and just change the GithubLoginButton and auth is working fine. I am not getting any error
I clone the repo and just change the GithubLoginButton and auth is working fine. I am not getting any error
Can you please tell me in which area are you getting error??
"use client";
import { createClient } from "@/lib/supabase/client";
import { useRouter } from "next/navigation";
export default function GitHubLoginButton() {
const router = useRouter();
async function signInWithGithub() {
const supabase = createClient();
const { data, error } = await supabase.auth.signInWithOAuth({
provider: "github",
options: {
redirectTo: process.env.NEXT_PUBLIC_SUPABASE_AUTH_CALLBACK,
scopes: "read:user",
},
});
if (error) {
router.push("/error");
}
if (data.url) {
router.push(data.url);
}
}
return (
<button
id="login"
className="flex items-center justify-center gap-x-2 bg-black p-3 border border-zinc-700 text-neutral-200 mt-4 rounded-lg text-sm font-bold"
onClick={signInWithGithub}
>
Logo
Login with Github
</button>
);
}NEXT_PUBLIC_SUPABASE_AUTH_CALLBACK="http://localhost:3000/api/auth/callback"
Common paper waspOP
I think that's what I have
I'll have to check
Common paper waspOP
I'll give this a try today
Common paper waspOP
Oh okay so this is my current button
Yes, thats right
Ive tried debugging it and from what I can tell, the issue happens in the middleware for some reason
Common paper waspOP
I can't figure it out though
Common paper waspOP
Okay I FINALLY figured this out. It took a lot lmao. Turns out we had it right the entire time and I'm an idiot.
I needed to set read only permissions in my GitHub app for user email. Once I did that, I started getting an SSL error (maybe something to do with doing this on a work laptop that has stricter permissions idk), but running
I'm now successfully able to log the user and check for a login in the layout.
I needed to set read only permissions in my GitHub app for user email. Once I did that, I started getting an SSL error (maybe something to do with doing this on a work laptop that has stricter permissions idk), but running
npm install -g npm --ca="" fixed that issue. I'm now successfully able to log the user and check for a login in the layout.
Answer