-
Notifications
You must be signed in to change notification settings - Fork 0
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
fix logout #92
Merged
jacobcoro
merged 8 commits into
main
from
jacob/v2-72-logout-user-serverside-not-clientside
Feb 15, 2023
Merged
fix logout #92
Changes from 7 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
27a27a5
fix logout
jacobcoro 5d649e3
allow id query from onboarding
jacobcoro 0b68bbc
kill persistent cookie
jacobcoro c0193d6
Merge branch 'main' into jacob/v2-72-logout-user-serverside-not-clien…
jacobcoro 312253e
note on middleware use
jacobcoro 461744e
document nicer
jacobcoro b3ae1b1
Merge branch 'main' into jacob/v2-72-logout-user-serverside-not-clien…
jacobcoro f458d95
Merge branch 'main' into jacob/v2-72-logout-user-serverside-not-clien…
jacobcoro File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { createServerSupabaseClient } from '@supabase/auth-helpers-nextjs'; | ||
import { NextApiHandler } from 'next'; | ||
import { serverLogger } from 'src/utils/logger'; | ||
|
||
const supabaseUrl = process.env.NEXT_PUBLIC_SUPABASE_URL || ''; | ||
const supabaseAnonKey = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY || ''; | ||
|
||
if (!supabaseUrl || !supabaseAnonKey) { | ||
serverLogger('NEXT_PUBLIC_SUPABASE_ANON_KEY or NEXT_PUBLIC_SUPABASE_URL not set', 'error'); | ||
} | ||
|
||
const handler: NextApiHandler = async (req, res) => { | ||
const supabaseClient = createServerSupabaseClient( | ||
{ req, res }, | ||
{ | ||
supabaseUrl, | ||
supabaseKey: supabaseAnonKey, | ||
}, | ||
); | ||
// Note: this doesn't really do much, because the jwt in the cookie will still be valid. All this `signOut` function does is invalidate the refresh token, so that the jwt can't be refreshed. The jwt will still be valid until it expires. | ||
await supabaseClient.auth.signOut(); | ||
|
||
const cookieExpiry = new Date(); | ||
|
||
// The cookie should already be deleted by the browser, but just in case, we'll delete it here as well. | ||
res.setHeader( | ||
'Set-Cookie', | ||
`supabase-auth-token=deleted; Max-Age=0; Expires=${cookieExpiry.toUTCString()};`, | ||
); | ||
return res.status(200).json({ success: true }); | ||
}; | ||
|
||
export default handler; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,14 +1,45 @@ | ||
import { NextApiHandler } from 'next'; | ||
import httpCodes from 'src/constants/httpCodes'; | ||
import { ProfileDB, ProfileInsertDB, updateProfile } from 'src/utils/api/db'; | ||
import { getProfileById, ProfileDB, ProfileInsertDB, updateProfile } from 'src/utils/api/db'; | ||
import { checkSessionIdMatchesID } from 'src/utils/auth'; | ||
import { serverLogger } from 'src/utils/logger'; | ||
|
||
export type ProfileGetQuery = { | ||
/** user id from session */ | ||
id: string; | ||
}; | ||
export type ProfileGetResponse = ProfileDB; | ||
|
||
export type ProfilePutBody = ProfileInsertDB; | ||
export type ProfilePutResponse = ProfileDB; | ||
|
||
const Handler: NextApiHandler = async (req, res) => { | ||
// Create authenticated Supabase Client | ||
if (req.method === 'GET') { | ||
const { id } = req.query as ProfileGetQuery; | ||
|
||
if (!id) { | ||
return res.status(httpCodes.BAD_REQUEST).json({ message: 'missing id' }); | ||
} | ||
try { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
const matchesSession = await checkSessionIdMatchesID(id, req, res); | ||
if (!matchesSession) { | ||
return res.status(httpCodes.UNAUTHORIZED).json({ | ||
error: 'user is unauthorized for this action', | ||
}); | ||
} | ||
const { data, error: profileGetError } = await getProfileById(id); | ||
if (profileGetError) { | ||
serverLogger(profileGetError, 'error'); | ||
return res.status(httpCodes.INTERNAL_SERVER_ERROR).json({}); | ||
} | ||
const result: ProfileGetResponse = data; | ||
return res.status(httpCodes.OK).json(result); | ||
} catch (error) { | ||
serverLogger(error, 'error'); | ||
return res.status(httpCodes.INTERNAL_SERVER_ERROR).json({}); | ||
} | ||
} | ||
|
||
if (req.method === 'PUT') { | ||
const profile = JSON.parse(req.body) as ProfilePutBody; | ||
|
||
|
@@ -24,7 +55,8 @@ const Handler: NextApiHandler = async (req, res) => { | |
serverLogger(profileUpdateError, 'error'); | ||
return res.status(httpCodes.INTERNAL_SERVER_ERROR).json({}); | ||
} | ||
return res.status(httpCodes.OK).json(data); | ||
const result: ProfilePutResponse = data; | ||
return res.status(httpCodes.OK).json(result); | ||
} catch (error) { | ||
serverLogger(error, 'error'); | ||
return res.status(httpCodes.INTERNAL_SERVER_ERROR).json({}); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { useRouter } from 'next/router'; | ||
import { useCallback, useEffect } from 'react'; | ||
import { useUser } from 'src/hooks/use-user'; | ||
|
||
export default function Logout() { | ||
const router = useRouter(); | ||
const { supabaseClient, refreshProfile, profile, user, getProfileController } = useUser(); | ||
const { email } = router.query; | ||
const signOut = useCallback(async () => { | ||
getProfileController.current?.abort(); | ||
if (!supabaseClient) return; | ||
await supabaseClient.auth.signOut(); | ||
|
||
const res = await fetch('/api/logout'); | ||
const data = await res.json(); | ||
if (data.success) { | ||
if (profile?.id || user?.id) { | ||
await refreshProfile(undefined, { | ||
revalidate: false, | ||
optimisticData: undefined, | ||
rollbackOnError: false, | ||
throwOnError: false, | ||
}); | ||
return; | ||
} | ||
window.location.href = email ? `/login?email=${email}` : '/login'; | ||
} | ||
}, [email, getProfileController, profile?.id, refreshProfile, supabaseClient, user?.id]); | ||
|
||
useEffect(() => { | ||
signOut(); | ||
}, [signOut]); | ||
|
||
return <></>; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,20 +26,9 @@ export default function Register() { | |
password: '', | ||
confirmPassword: '', | ||
}); | ||
const { signup, logout, profile, createEmployee } = useUser(); | ||
const { signup, profile, createEmployee } = useUser(); | ||
const [loading, setLoading] = useState(false); | ||
const [signupSuccess, setSignupSuccess] = useState(false); | ||
const [initialLoad, setInitialLoad] = useState(true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
useEffect(() => { | ||
const logOutOnLoad = async () => { | ||
// sometimes the cookies and signed in status still persist to this page, so call logout again | ||
// TODO: move logout logic serverside https://toil.kitemaker.co/0JhYl8-relayclub/8sxeDu-v2_project/items/72 | ||
|
||
await logout(); | ||
setInitialLoad(false); | ||
}; | ||
if (initialLoad) logOutOnLoad(); | ||
}, [logout, initialLoad]); | ||
|
||
useEffect(() => { | ||
if (signupSuccess && profile?.id) { | ||
|
@@ -49,7 +38,7 @@ export default function Register() { | |
router.push('/signup/onboarding'); | ||
} | ||
} | ||
}, [email, initialLoad, router, signupSuccess, profile]); | ||
}, [email, router, signupSuccess, profile]); | ||
|
||
const handleSubmit = async () => { | ||
setLoading(true); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,19 +8,16 @@ import { Sidebar } from 'src/components/sidebar'; | |
|
||
import { useUser } from 'src/hooks/use-user'; | ||
import useOnOutsideClick from 'src/hooks/use-on-outside-click'; | ||
import { useSupabaseClient } from '@supabase/auth-helpers-react'; | ||
|
||
export const Layout = ({ children }: any) => { | ||
const { t } = useTranslation(); | ||
const { profile, loading, refreshProfile } = useUser(); | ||
const { profile, loading, refreshProfile, logout } = useUser(); | ||
|
||
useEffect(() => { | ||
// this fixes a bug where the profile is not loaded on the first page load when coming from signup | ||
if (!loading && !profile?.id) refreshProfile(); | ||
}, [refreshProfile, profile, loading]); | ||
|
||
const supabase = useSupabaseClient(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
||
const [accountMenuOpen, setAccountMenuOpen] = useState(false); | ||
const accountMenuRef = useRef(null); | ||
const accountMenuButtonRef = useRef(null); | ||
|
@@ -75,11 +72,7 @@ export const Layout = ({ children }: any) => { | |
<Button | ||
className="px-4 py-2 text-sm hover:bg-gray-100 active:bg-gray-200" | ||
variant="neutral" | ||
onClick={async () => { | ||
await supabase.auth.signOut(); | ||
// need to trigger a page reload to get the new auth state, so don't use router.push | ||
window.location.href = '/signup'; | ||
}} | ||
onClick={logout} | ||
> | ||
{t('navbar.logout')} | ||
</Button> | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's good to see this pattern of validation after using a type assertion continuing to be applied.
◽ Compliment
Ryan B