Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refresh token bugfix #27

Merged
merged 2 commits into from
Mar 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion app/sign-in/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ export default async function SignInPage({
searchParams: { [key: string]: string | string[] | undefined }
}) {
const cookieStore = cookies()
let session = await auth({ cookieStore })
// let session = await auth({ cookieStore })
let session = await auth({cookieStore})

// legacy code
// // // const user_id = searchParams?.user_id
Expand Down
20 changes: 20 additions & 0 deletions auth.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'server-only'
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs'
import { createClient } from '@/utils/supabase/server'
import { cookies } from 'next/headers'

export const auth = async ({
Expand All @@ -15,3 +16,22 @@ export const auth = async ({
if (error) throw error
return data.session
}

export const authUser = async ({
cookieStore
}: {
cookieStore: ReturnType<typeof cookies>
}) => {
// Create a Supabase client configured to use cookies
// const supabase = createServerComponentClient({
// cookies: () => cookieStore
// })
const supabase = createClient()
const { data, error } = await supabase.auth.getSession()

// const supabase = createClient()
// const { data:data, error:error } = await supabase.auth.getUser()

if (error) throw error
return data.session
}
42 changes: 24 additions & 18 deletions components/login-form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ import { toast } from 'react-hot-toast'
import { useRouter } from 'next/navigation'

import GlobalConfig from '@/app/app.config.js'
import { createBrowserClient } from '@/utils/supabase/client'

import {signInServer} from '@/utils/login'


interface LoginFormProps extends React.ComponentPropsWithoutRef<'div'> {
action: 'sign-in' | 'sign-up'
Expand All @@ -27,7 +31,7 @@ export function LoginForm({
const [isLoading, setIsLoading] = React.useState(false)
const router = useRouter()
// Create a Supabase client configured to use cookies
const supabase = createClientComponentClient()


const [formState, setFormState] = React.useState<{
email: string
Expand All @@ -38,26 +42,28 @@ export function LoginForm({
})

const signIn = async () => {
const { email, password } = formState
const { error } = await supabase.auth.signInWithPassword({
email,
password
})
// const { email, password } = formState
// const { error } = await supabase.auth.signInWithPassword({
// email,
// password
// })
// return error
const error = await signInServer(formState)
return error
}

const signUp = async () => {
const { email, password } = formState
const { error, data } = await supabase.auth.signUp({
email,
password,
options: { emailRedirectTo: `${location.origin}/api/auth/callback` }
})

if (!error && !data.session)
toast.success('Check your inbox to confirm your email address!')
return error
}
// const signUp = async () => {
// const { email, password } = formState
// const { error, data } = await supabase.auth.signUp({
// email,
// password,
// options: { emailRedirectTo: `${location.origin}/api/auth/callback` }
// })

// if (!error && !data.session)
// toast.success('Check your inbox to confirm your email address!')
// return error
// }

const handleOnSubmit: React.FormEventHandler<HTMLFormElement> = async e => {
e.preventDefault()
Expand Down
133 changes: 97 additions & 36 deletions middleware.ts
Original file line number Diff line number Diff line change
@@ -1,80 +1,134 @@
import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs'
import { NextResponse, NextRequest } from 'next/server'

export async function middleware(req: NextRequest) {
const res = NextResponse.next()
import { createServerClient, type CookieOptions } from '@supabase/ssr'

import { cookies } from 'next/headers'

export async function middleware(request: NextRequest) {
// const res = NextResponse.next()
let response = NextResponse.next({
request: {
headers: request.headers,
},
})
// Added CSP code
// directly from https://nextjs.org/docs/app/building-your-application/configuring/content-security-policy
const nonce = Buffer.from(crypto.randomUUID()).toString('base64')
const cspHeader = `
default-src 'self';
script-src 'self' 'nonce-${nonce}' 'strict-dynamic';
style-src 'self' 'nonce-${nonce}';
img-src 'self' blob: data:;
font-src 'self';
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
block-all-mixed-content;
upgrade-insecure-requests;
const cspHeader = process.env.DEBUG_MODE ? `` : `
default-src 'self' 'unsafe-inline';
script-src 'self' 'nonce-${nonce}' 'strict-dynamic' 'unsafe-inline';
style-src 'self' 'nonce-${nonce}' 'unsafe-inline';
img-src 'self' blob: data:;
font-src 'self';
object-src 'none';
base-uri 'self';
form-action 'self';
frame-ancestors 'none';
block-all-mixed-content;
upgrade-insecure-requests;
`
// Replace newline characters and spaces
// // Replace newline characters and spaces
const contentSecurityPolicyHeaderValue = cspHeader
.replace(/\s{2,}/g, ' ')
.trim()

const requestHeaders = new Headers(req.headers)
const requestHeaders = new Headers(request.headers)
requestHeaders.set('x-nonce', nonce)

requestHeaders.set(
'Content-Security-Policy',
contentSecurityPolicyHeaderValue
)

const response = NextResponse.next({
request: {
headers: requestHeaders,
},
})
response.headers.set(
'Content-Security-Policy',
contentSecurityPolicyHeaderValue
)

// Create a Supabase client configured to use cookies
const supabase = createMiddlewareClient({ req, res })
// const supabase = createMiddlewareClient({ req, res })

// Refresh session if expired - required for Server Components
// https://supabase.com/docs/guides/auth/auth-helpers/nextjs#managing-session-with-middleware
const {
data: { session }
} = await supabase.auth.getSession()
// const {
// data: { session }
// } = await supabase.auth.getSession()

const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookieOptions: {domain: '', secure: 'false', maxAge: 604800, path: '', sameSite: 'None'},
cookies: {
get(name: string) {
return request.cookies.get(name)?.value
},
set(name: string, value: string, options: CookieOptions) {
request.cookies.set({
name,
value,
...options,
})
response = NextResponse.next({
request: {
headers: request.headers,
},
})
response.cookies.set({
name,
value,
...options,
})
},
remove(name: string, options: CookieOptions) {
request.cookies.set({
name,
value: '',
...options,
})
response = NextResponse.next({
request: {
headers: request.headers,
},
})
response.cookies.set({
name,
value: '',
...options,
})
},
},
}
)
// console.log(await supabase.auth.getUser())
let {data: session} = await supabase.auth.getSession()
await supabase.auth.getUser()
const cookieStore = cookies()

// OPTIONAL: this forces users to be logged in to use the chatbot.
// If you want to allow anonymous users, simply remove the check below.
const user_id = req.nextUrl.searchParams.get('user_id')
const user_id = request.nextUrl.searchParams.get('user_id')
if (
!session &&
!req.url.includes('/sign-in') &&
!req.url.includes('/sign-up') &&
!req.url.includes('/reset-password')
!session.session &&
!request.url.includes('/sign-in') &&
!request.url.includes('/sign-up') &&
!request.url.includes('/reset-password')
) {
const redirectUrl = req.nextUrl.clone()
const redirectUrl = request.nextUrl.clone()
redirectUrl.pathname = '/sign-in'
redirectUrl.searchParams.set(`redirectedFrom`, req.nextUrl.pathname)
redirectUrl.searchParams.set(`redirectedFrom`, request.nextUrl.pathname)
user_id ? redirectUrl.searchParams.set(`user_id`, user_id) : undefined
return NextResponse.redirect(redirectUrl)
}
else if (session && req.url.includes('/reset-password') && req.url.includes('/sign-up') && req.url.includes('/sign-in')){
const redirectUrl = req.nextUrl.clone()
else if (session.session && request.url.includes('/reset-password') && request.url.includes('/sign-up') && request.url.includes('/sign-in')){
const redirectUrl = request.nextUrl.clone()
redirectUrl.pathname = '/'
user_id ? redirectUrl.searchParams.set(`user_id`, user_id) : undefined
return NextResponse.redirect(redirectUrl)
}

return res
return response
}

export const config = {
Expand All @@ -87,6 +141,13 @@ export const config = {
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
*/
'/((?!share|api|_next/static|_next/image|favicon.ico).*)'
// '/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
{
source: '/((?!api|_next/static|_next/image|favicon.ico).*)',
missing: [
{ type: 'header', key: 'next-router-prefetch' },
{ type: 'header', key: 'purpose', value: 'prefetch' },
],
},
]
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"@radix-ui/react-toast": "^1.1.5",
"@radix-ui/react-tooltip": "^1.0.6",
"@supabase/auth-helpers-nextjs": "^0.7.2",
"@supabase/ssr": "^0.1.0",
"@supabase/supabase-js": "^2.26.0",
"@tanstack/react-table": "^8.10.7",
"@vercel/analytics": "^1.0.1",
Expand Down
22 changes: 22 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions utils/login.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { createClient } from '@/utils/supabase/client'


const supabase = createClient()

type formStateType = {
email: string,
password: string
}

export const signInServer = async (formState: formStateType) => {
const { email, password } = formState
const { error } = await supabase.auth.signInWithPassword({
email,
password
})
return error
}

export const signUpServer = async (formState: formStateType) => {
const { email, password } = formState
const { error, data } = await supabase.auth.signUp({
email,
password,
options: { emailRedirectTo: `${location.origin}/api/auth/callback` }
})
}
8 changes: 8 additions & 0 deletions utils/supabase/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { createBrowserClient } from '@supabase/ssr'

export function createClient() {
return createBrowserClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
}
Loading
Loading