migrate(docs): troubleshooting 7 (#30936)

auth
This commit is contained in:
Charis authored and GitHub committed 2025-01-17 16:49:23 -05:00
1 parent a42e17d0a9
commit 6312618932
6 files changed
+432

No files matched your search

@@ -0,0 +1,49 @@
---
title = "Google Auth fails for some users"
github_url = "https://github.com/orgs/supabase/discussions/14883"
date_created = "2023-06-07T20:38:48+00:00"
topics = ["auth"]
keywords = ["OAuth", "Google", "credential", "email"]
[api]
sdk = ["supabase.auth.signInWithOAuth"]
[[errors]]
http_status_code = 500
code = "server_error"
message = "Error getting user email from external provider"
[[errors]]
http_status_code = 401
code = "UNAUTHENTICATED"
message = "Missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential."
---
## Google Auth fails for some users
If you start facing either of these errors:
```
error=server_error&error_description=Error+getting+user+email+from+external+provider
Missing required authentication credential.
Expected OAuth 2 access token, login cookie or other valid authentication credential.
See https://developers.google.com/identity/sign-in/web/devconsole-project.\",\n \"status\": \"UNAUTHENTICATED\"
}
"level":"error","method":"GET","msg":"500: Error getting user email from external provider","path":"/callback","referer":"https://accounts.google.com/","remote_addr":"x.x.X.x","time":"2023-06-06T21:46:11Z","timestamp":"2023-06-06T21:46:11Z"}
```
It is happening because some Google Suite requires the explicit request of email Auth Scopes:
`https://www.googleapis.com/auth/userinfo.email`
```js
const { data, error } = await supabase.auth.signInWithOAuth({
provider: 'google'
options: {
scopes: 'https://www.googleapis.com/auth/userinfo.email'
}
})
```
@@ -0,0 +1,18 @@
---
title = "How do I check GoTrue/API version of a Supabase project?"
github_url = "https://github.com/orgs/supabase/discussions/14217"
date_created = "2023-05-09T04:21:49+00:00"
topics = ["auth", "platform"]
---
Make a `GET` request to the health check endpoint to retrieve this information. Below is an example using `curl`:
```
curl -X GET 'https://project-ref.supabase.co/auth/v1/health' -H 'apikey: ANON_KEY'
{
"version": "v2.60.7",
"name": "GoTrue",
"description": "GoTrue is a user registration and authentication API"
}
```
@@ -0,0 +1,9 @@
---
title = "How do I make the cookies HttpOnly?"
github_url = "https://github.com/orgs/supabase/discussions/18869"
date_created = "2023-11-10T11:49:06+00:00"
topics = ["auth"]
keywords = ["cookies", "HttpOnly"]
---
This is not necessary. Both the access token and refresh token are designed to be passed around to different components in your application. The browser-based side of your application needs access to the refresh token to properly maintain a browser session anyway.
@@ -0,0 +1,315 @@
---
title = "How to Migrate from Supabase Auth Helpers to SSR package"
github_url = "https://github.com/orgs/supabase/discussions/27849"
date_created = "2024-07-07T17:24:30+00:00"
topics = ["auth"]
keywords = ["migration", "auth", "ssr", "package"]
---
The `auth-helpers` packages are being deprecated and replaced with the `@supabase/ssr` package. We recommend migrating to the `@supabase/ssr` package as future bug fixes and feature releases are focused on the `@supabase/ssr` package.
Here are the steps for you to migrate your application from the `auth-helpers` package to `@supabase/ssr` package.
Depending on your implementation, you may ignore some parts of this documentation and use your own implementation (i.e. using API routes vs. Server Actions). What’s important is you replace the clients provided by `auth-helpers` with the utility functions created using clients provided by `@supabase/ssr`.
### 1. Uninstall Supabase Auth Helpers and install the Supabase SSR package
It’s important that you don’t use both `auth-helpers-nextjs` and `@supabase/ssr` packages in the same application to avoid running into authentication issues.
```
npm uninstall @supabase/auth-helpers-nextjs @supabase/supabase-js
npm install @supabase/ssr @supabase/supabase-js
```
### 2. Create the utility functions to create Supabase clients.
```
// utils/supabase/client.ts
import { createBrowserClient } from '@supabase/ssr';
export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);
}
// utils/supabase/server.ts
import { createServerClient, type CookieOptions } from '@supabase/ssr';
import { cookies } from 'next/headers';
export function createClient() {
const cookieStore = cookies();
return createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return cookieStore.getAll()
},
setAll(cookiesToSet) {
try {
cookiesToSet.forEach(({ name, value, options }) =>
cookieStore.set(name, value, options)
)
} catch {
// The `setAll` method was called from a Server Component.
// This can be ignored if you have middleware refreshing
// user sessions.
}
},
},
}
);
}
// utils/supabase/middleware.ts
import { createServerClient } from '@supabase/ssr';
import { NextResponse, type NextRequest } from 'next/server';
export async function updateSession(request: NextRequest) {
let supabaseResponse = NextResponse.next({
request,
});
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return request.cookies.getAll()
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))
supabaseResponse = NextResponse.next({
request,
})
cookiesToSet.forEach(({ name, value, options }) =>
supabaseResponse.cookies.set(name, value, options)
)
},
},
}
);
// IMPORTANT: Avoid writing any logic between createServerClient and
// supabase.auth.getUser(). A simple mistake could make it very hard to debug
// issues with users being randomly logged out.
const {
data: { user },
} = await supabase.auth.getUser();
if (
!user &&
!request.nextUrl.pathname.startsWith('/login') &&
!request.nextUrl.pathname.startsWith('/auth')
) {
// no user, potentially respond by redirecting the user to the login page
const url = request.nextUrl.clone();
url.pathname = '/login';
return NextResponse.redirect(url);
}
// IMPORTANT: You *must* return the supabaseResponse object as it is. If you're
// creating a new response object with NextResponse.next() make sure to:
// 1. Pass the request in it, like so:
// const myNewResponse = NextResponse.next({ request })
// 2. Copy over the cookies, like so:
// myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())
// 3. Change the myNewResponse object to fit your needs, but avoid changing
// the cookies!
// 4. Finally:
// return myNewResponse
// If this is not done, you may be causing the browser and server to go out
// of sync and terminate the user's session prematurely!
return supabaseResponse;
}
```
### 3. Replace your middleware.ts file
```
// middleware.ts
import { type NextRequest } from 'next/server';
import { updateSession } from '@/utils/supabase/middleware';
export async function middleware(request: NextRequest) {
return await updateSession(request);
}
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* Feel free to modify this pattern to include more paths.
*/
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
],
};
```
### 4. Create your Server Actions to handle Login and Sign up.
```
// app/login/actions.ts
'use server';
import { revalidatePath } from 'next/cache';
import { redirect } from 'next/navigation';
import { createClient } from '@/utils/supabase/server';
export async function login(formData: FormData) {
const supabase = createClient();
// type-casting here for convenience
// in practice, you should validate your inputs
const data = {
email: formData.get('email') as string,
password: formData.get('password') as string,
};
const { error } = await supabase.auth.signInWithPassword(data)
if (error) {
redirect('/error');
}
revalidatePath('/', 'layout');
redirect('/');
}
export async function signup(formData: FormData) {
const supabase = createClient();
// type-casting here for convenience
// in practice, you should validate your inputs
const data = {
email: formData.get('email') as string,
password: formData.get('password') as string,
};
const { error } = await supabase.auth.signUp(data);
if (error) {
redirect('/error');
}
revalidatePath('/', 'layout');
redirect('/');
}
```
### 5. Utilize the server actions in your Login page UI.
```
// app/login/page.tsx
import { login, signup } from './actions';
export default function LoginPage() {
return (
<form>
<label htmlFor="email">Email:</label>
<input id="email" name="email" type="email" required />
<label htmlFor="password">Password:</label>
<input id="password" name="password" type="password" required />
<button formAction={login}>Log in</button>
<button formAction={signup}>Sign up</button>
</form>
);
}
```
### 6. Client Components
```
'use client';
// replace this line
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs';
// with
import { createClient } from '@/utils/supabase/client';
export default async function Page() {
// replace this line
const supabase = createClientComponentClient<Database>();
// with
const supabase = createClient();
return...
}
```
### 7. Server Components
```
// replace
import { cookies } from 'next/headers';
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs';
// with
import { createClient } from '@/utils/supabase/server';
export default async function Page() {
// replace
const cookieStore = cookies();
const supabase = createServerComponentClient<Database>({
cookies: () => cookieStore
});
// with
const supabase = createClient();
return...
}
```
### 8. Route Handlers
```
// replace
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs';
import { cookies } from 'next/headers';
// with
import { createClient } from '@/utils/supabase/server';
export async function POST(request: Request) {
// replace
const supabase = createRouteHandlerClient<Database>({
cookies: () => cookieStore,
});
// with
const supabase = createClient();
return...
}
```
Likewise, you can replace the clients created with `@supabase/auth-helpers-nextjs` with utility functions you created with `@supabase/ssr`.
`createMiddlewareClient` → `createServerClient`
`createClientComponentClient` → `createBrowserClient`
`createServerComponentClient` → `createServerClient`
`createRouteHandlerClient` → `createServerClient`
You can find more clear and concise examples of creating clients in our documentation [here](https://supabase.com/docs/guides/auth/server-side/creating-a-client?queryGroups=framework&framework=nextjs&queryGroups=environment&environment=route-handler#creating-a-client).
If you have any feedback about this guide, please provide them as a comment below. If you find any issues or have feedback for the `@supabase/ssr` client, please post them as an issue in `@supabase/ssr` repo.
As always, our GitHub community and Discord channel are open for technical discussions and resolving your issues.
@@ -0,0 +1,9 @@
---
title = "I am not receiving password reset emails for Supabase dashboard"
github_url = "https://github.com/orgs/supabase/discussions/14043"
date_created = "2023-04-30T08:08:07+00:00"
topics = ["auth", "platform"]
keywords = ["email", "reset"]
---
Most likely, you signed up on Supabase using a GitHub account. Please try the GitHub login method to see if you can log in. If you still cannot log in, please write to support@supabase.com using your email with a screenshot of the error from the dashboard.
@@ -0,0 +1,32 @@
---
title = "Rotating Anon, Service, and JWT Secrets"
github_url = "https://github.com/orgs/supabase/discussions/20031"
date_created = "2023-12-27T14:54:11+00:00"
topics = ["auth", "platform"]
keywords = ["jwt", "secrets", "key", "security"]
---
Has this ever been you: "Oh no! I accidentally committed my service key to our public repo!" Or maybe rotating keys is just something you regularly do for security compliance.
Whatever the reason, here's how to rotate the keys for your Supabase project.
1. Go to the [API Settings page](https://supabase.com/dashboard/project/_/settings/api) in the Supabase Dashboard
2. Find the JWT Secrets section
<img
width="1072"
alt="Screenshot 2023-12-27 at 08 39 41"
src="https://github.com/supabase/supabase/assets/1923424/bdcab8a2-7007-496c-a845-d331ee883a0a"
/>
3. Click the `Generate new secret` button and choose either a random secret, or custom if you'd like to supply one of your own.
4. NOTE: Once regeneraged, all current API secrets will be immediately invalidated, and all connections using them will be severed. You will need to deploy the new secrets for connections to begin working again.
5. Confirm the changes in the warning that pops up by clicking `Generate New Secret` again.
<img
width="517"
alt="Screenshot 2023-12-27 at 08 39 59"
src="https://github.com/supabase/supabase/assets/1923424/1f5cf876-ff65-41f0-b92e-37826773041c"
/>
6. After confirming, the secret will be generated, and Supabase will start rolling that out across our services. Postgres will restart, the API gateways will be updated, etc. Once the process is complete, you will be able to see your new JWT secret as well as the new anon and service keys.