From 2f800f6d090176c4735f22b68e1f6df363d022e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thor=20=E9=9B=B7=E7=A5=9E=20Schaeff?= <5748289+thorwebdev@users.noreply.github.com> Date: Wed, 9 Mar 2022 11:34:43 +0800 Subject: [PATCH] fix: merge cookieOptions correctly. (#33) * fix: merge cookieOptions correctly. * chore: update changelog. --- CHANGELOG.md | 4 ++++ examples/nextjs/pages/api/auth/[...supabase].ts | 5 ++++- src/nextjs/handlers/auth.ts | 3 ++- src/nextjs/handlers/callback.ts | 2 +- src/nextjs/handlers/logout.ts | 2 +- src/nextjs/handlers/user.ts | 6 +++--- src/nextjs/utils/getAccessToken.ts | 12 ++++++++---- src/nextjs/utils/getUser.ts | 7 ++++++- src/nextjs/utils/withAuthRequired.ts | 15 ++++++++++----- 9 files changed, 39 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8699f1d7..cef7ec2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # CHANGELOG +## 1.2.1 - 2022-03-09 + +- [#33](https://github.com/supabase-community/supabase-auth-helpers/pull/33): fix: merge cookieOptions correctly. + ## 1.2.0 - 2022-03-01 - [BREAKING CHANGE][#32](https://github.com/supabase-community/supabase-auth-helpers/pull/32): feat: add logout api route. Note that this includes a breaking change to the options parameter for `handleAuth(options: HandleAuthOptions)` See [the docs](./src/nextjs/README.md#basic-setup) for more details. diff --git a/examples/nextjs/pages/api/auth/[...supabase].ts b/examples/nextjs/pages/api/auth/[...supabase].ts index 4a31cf2c..2c03c57e 100644 --- a/examples/nextjs/pages/api/auth/[...supabase].ts +++ b/examples/nextjs/pages/api/auth/[...supabase].ts @@ -1,3 +1,6 @@ import { handleAuth } from '@supabase/supabase-auth-helpers/nextjs'; -export default handleAuth({ logout: { returnTo: '/' } }); +export default handleAuth({ + logout: { returnTo: '/signin' }, + cookieOptions: { lifetime: 1 * 365 * 24 * 60 * 60 } // Keep the user logged in for a year. +}); diff --git a/src/nextjs/handlers/auth.ts b/src/nextjs/handlers/auth.ts index 7b0a4191..a53660df 100644 --- a/src/nextjs/handlers/auth.ts +++ b/src/nextjs/handlers/auth.ts @@ -12,7 +12,8 @@ export interface HandleAuthOptions { export default function handleAuth(options: HandleAuthOptions = {}) { return async (req: NextApiRequest, res: NextApiResponse): Promise => { - const { cookieOptions = COOKIE_OPTIONS, logout } = options; + const { logout } = options; + const cookieOptions = { ...COOKIE_OPTIONS, ...options.cookieOptions }; let { query: { supabase: route } } = req; diff --git a/src/nextjs/handlers/callback.ts b/src/nextjs/handlers/callback.ts index 41f81a41..13cc9ee1 100644 --- a/src/nextjs/handlers/callback.ts +++ b/src/nextjs/handlers/callback.ts @@ -20,7 +20,7 @@ export default function handelCallback( res.setHeader('Allow', 'POST'); res.status(405).end('Method Not Allowed'); } - const { cookieOptions = COOKIE_OPTIONS } = options; + const cookieOptions = { ...COOKIE_OPTIONS, ...options.cookieOptions }; const { event, session } = req.body; if (!event) throw new Error('Auth event missing!'); diff --git a/src/nextjs/handlers/logout.ts b/src/nextjs/handlers/logout.ts index 1e378de9..b20761cb 100644 --- a/src/nextjs/handlers/logout.ts +++ b/src/nextjs/handlers/logout.ts @@ -22,7 +22,7 @@ export default function handleLogout( if (!returnTo) returnTo = options?.returnTo ?? '/'; returnTo = Array.isArray(returnTo) ? returnTo[0] : returnTo; returnTo = returnTo.charAt(0) === '/' ? returnTo : `/${returnTo}`; - const { cookieOptions = COOKIE_OPTIONS } = options; + const cookieOptions = { ...COOKIE_OPTIONS, ...options.cookieOptions }; // Logout request to Gotrue const access_token = req.cookies[`${cookieOptions.name}-access-token`]; diff --git a/src/nextjs/handlers/user.ts b/src/nextjs/handlers/user.ts index 95bba7cc..cbb3a846 100644 --- a/src/nextjs/handlers/user.ts +++ b/src/nextjs/handlers/user.ts @@ -17,7 +17,7 @@ export default async function handleUser( if (!req.cookies) { throw new Error('Not able to parse cookies!'); } - const { cookieOptions = COOKIE_OPTIONS } = options; + const cookieOptions = { ...COOKIE_OPTIONS, ...options.cookieOptions }; const access_token = req.cookies[`${cookieOptions.name}-access-token`]; if (!access_token) { @@ -32,7 +32,7 @@ export default async function handleUser( const timeNow = Math.round(Date.now() / 1000); if (jwtUser.exp < timeNow) { // JWT is expired, let's refresh from Gotrue - const response = await getUser({ req, res }, cookieOptions); + const response = await getUser({ req, res }, { cookieOptions }); res.status(200).json(response); } else { // Transform JWT and add note that it ise cached from JWT. @@ -59,7 +59,7 @@ export default async function handleUser( } catch (e) { const error = e as ApiError; res - .status(400) + .status(200) .json({ user: null, accessToken: null, error: error.message }); } } diff --git a/src/nextjs/utils/getAccessToken.ts b/src/nextjs/utils/getAccessToken.ts index dbb0ba86..fdcbb839 100644 --- a/src/nextjs/utils/getAccessToken.ts +++ b/src/nextjs/utils/getAccessToken.ts @@ -6,18 +6,22 @@ import { import getUser from './getUser'; import { jwtDecoder } from '../../shared/utils/jwt'; import { CookieOptions } from '../types'; +import { COOKIE_OPTIONS } from '../../shared/utils/constants'; + +export interface GetAccessTokenOptions { + cookieOptions?: CookieOptions; +} export default async function getAccessToken( context: | GetServerSidePropsContext | { req: NextApiRequest; res: NextApiResponse }, - cookieOptions: CookieOptions = { - name: 'sb' - } + options: GetAccessTokenOptions = {} ): Promise { if (!context.req.cookies) { throw new Error('Not able to parse cookies!'); } + const cookieOptions = { ...COOKIE_OPTIONS, ...options.cookieOptions }; const access_token = context.req.cookies[`${cookieOptions.name}-access-token`]; @@ -33,7 +37,7 @@ export default async function getAccessToken( const timeNow = Math.round(Date.now() / 1000); if (jwtUser.exp < timeNow) { // JWT is expired, let's refresh from Gotrue - const { accessToken } = await getUser(context, cookieOptions); + const { accessToken } = await getUser(context, { cookieOptions }); return accessToken; } else { return access_token; diff --git a/src/nextjs/utils/getUser.ts b/src/nextjs/utils/getUser.ts index 83a02f94..1ca78a24 100644 --- a/src/nextjs/utils/getUser.ts +++ b/src/nextjs/utils/getUser.ts @@ -13,11 +13,15 @@ import { NextResponseAdapter } from '../../shared/adapters/NextAdapter'; +export interface GetUserOptions { + cookieOptions?: CookieOptions; +} + export default async function getUser( context: | GetServerSidePropsContext | { req: NextApiRequest; res: NextApiResponse }, - cookieOptions: CookieOptions = COOKIE_OPTIONS + options: GetUserOptions = {} ): Promise<{ user: User | null; accessToken: string | null }> { try { if ( @@ -35,6 +39,7 @@ export default async function getUser( process.env.NEXT_PUBLIC_SUPABASE_URL, process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY ); + const cookieOptions = { ...COOKIE_OPTIONS, ...options.cookieOptions }; const access_token = context.req.cookies[`${cookieOptions.name}-access-token`]; const refresh_token = diff --git a/src/nextjs/utils/withAuthRequired.ts b/src/nextjs/utils/withAuthRequired.ts index f954ba30..d571db52 100644 --- a/src/nextjs/utils/withAuthRequired.ts +++ b/src/nextjs/utils/withAuthRequired.ts @@ -80,12 +80,16 @@ export type WithAuthRequiredArg = export default function withAuthRequired( arg?: WithAuthRequiredArg, - cookieOptions = COOKIE_OPTIONS + options: { cookieOptions?: CookieOptions } = {} ) { if (typeof arg === 'function') { return async (req: NextApiRequest, res: NextApiResponse): Promise => { try { - const accessToken = await getAccessToken({ req, res }, cookieOptions); + const cookieOptions = { ...COOKIE_OPTIONS, ...options.cookieOptions }; + const accessToken = await getAccessToken( + { req, res }, + { cookieOptions } + ); if (!accessToken) throw new Error('No access token!'); await arg(req, res); } catch (error) { @@ -98,16 +102,17 @@ export default function withAuthRequired( } }; } else { - const { + let { getServerSideProps = undefined, redirectTo = '/', - cookieOptions = COOKIE_OPTIONS + cookieOptions = {} } = arg ? arg : {}; return async (context: GetServerSidePropsContext) => { try { if (!context.req.cookies) { throw new Error('Not able to parse cookies!'); } + cookieOptions = { ...COOKIE_OPTIONS, ...cookieOptions }; const access_token = context.req.cookies[`${cookieOptions.name}-access-token`]; if (!access_token) { @@ -123,7 +128,7 @@ export default function withAuthRequired( const timeNow = Math.round(Date.now() / 1000); if (jwtUser.exp < timeNow) { // JWT is expired, let's refresh from Gotrue - const response = await getUser(context, cookieOptions); + const response = await getUser(context, { cookieOptions }); user = response.user; accessToken = response.accessToken; } else {