-
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
fix logout #92
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
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.
✅ This pull request was sent to the PullRequest network.
Check the status or cancel PullRequest code review here.
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.
PullRequest Breakdown
Reviewable lines of change
+ 193
- 72
55% TSX
45% TypeScript
Type of change
Fix - These changes are likely to be fixing a bug or issue.
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.
These changes—primarily related to logout—look good to me. I had a few questions and comments inline.
Reviewers will be notified any time you reply to their comments or commit new changes.
You can also request a full follow-up review from your PullRequest dashboard.
middleware.ts
Outdated
*/ | ||
'/((?!_next/static|_next/image|favicon.ico|assets/*|api/company/accept-invite*|api/company/create-employee*).*)', | ||
'/((?!_next/static|_next/image|favicon.ico|assets/*|api/company/accept-invite*|api/company/create-employee*|logout/*).*)', |
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.
This is a bit unfortunate, since it likely won't be the last bug that gets created due to this approach. It's too bad Next doesn't seem to give many other options if you want to do the config approach, and it can't be from dynamic values.
If this list continues to grow, it might be worth handling these routes in the middleware function. As part of that, something should be done about the fact that this is tribal knowledge.
Meaning—other developers working on this code base have nothing telling them that adding a new "public / unauthed" route will break unless they know to come and add a regex to this line hiding at the bottom of the middleware file. How that gets addressed depends on the project conventions, but a comment in a well-placed location would at least help a little.
🔸 Reduce Future Bugs (Important)
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.
good point. I made a note in the middleware jsdoc, although it isnt ideal, someone new will definitely have to have a glance at this file during onboarding
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.
if (req.method === 'GET') { | ||
const { id } = req.query as ProfileGetQuery; | ||
|
||
if (!id) { |
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.
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 comment
The reason will be displayed to describe this comment to others. Learn more.
pages/logout/[email].tsx
Outdated
@@ -0,0 +1,14 @@ | |||
import { GetServerSidePropsContext } from 'next'; | |||
import { logoutRedirect } from 'src/utils/auth'; |
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.
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.
redirecting to the login page with the old email pre-filled
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 comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
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 comment
The reason will be displayed to describe this comment to others. Learn more.
src/utils/auth.ts
Outdated
@@ -27,3 +48,23 @@ export const isCompanyOwnerOrRelayEmployee = async (req: NextApiRequest, res: Ne | |||
|
|||
return isAdmin(profile?.role); | |||
}; | |||
|
|||
export const logoutRedirect = async (ctx: GetServerSidePropsContext, email?: string) => { |
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.
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.
The reason this works is that window.location.href will cancel in-flight requests, whereas router.push() in next.js will not.
This is expected, since the router is just for client-side routing within the same document, whereas window.location.href
is an actual navigation event in which a new document is loaded.
Reviewers will be notified any time you reply to their comments or commit new changes.
You can also request a full follow-up review from your PullRequest dashboard.
await supabaseClient.auth.signOut(); | ||
setProfile(null); | ||
const email = session?.user?.email; | ||
// cannot use router.push() here because it won't cancel in-flight requests which wil re-set the cookie |
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.
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.
Hey @jacobcoro,
Was the feedback from PullRequest helpful? Yes | No
#41 (comment)
What's happening:
When we click 'logout' new requests from SWR (like to subscriptions) get sent out, and the cookie that just got deleted resets again.
Also, if we redirect the use to the login page right after signing out, the browser still somehow has the cookie, and our middleware detects that the user is still logged in and redirects right back to the dashboard.
I tried calling supabase.auth.logOut on the server side but that doesn't actually work. because supabase uses jwt tokens, all the serverside logout does it say 'I wont accept refresh tokens' but doesn't invalidate the current token.
Why the swr calls still have a token after it was just deleted is a mystery to me.
references:
https://stackoverflow.com/questions/72972086/cannot-log-out-user-on-the-server-side-next-js-and-supabase
signOut not deleting cookie
Closedsupabase/gotrue-js · #46 · Issue opened by gomflo on Jan 17 2021
I then tried manually setting the cookie from the backend during the 'logout' call. That also did not work. (in the screenshot above, notice deleted and expires are set.
So it turns out doing a fully server-side log out is not possible with supabase as far as I can tell.
But if we do the logout page redirect, at least we should be able to redirect to the login page and not have it immediately sign back in
Tomorrow I will try redirecting the user to a logout page, that then redirects to login after signing out. We should probably still call the server logOut function even though it really doesnt do much.
Using a logout redirect page seemed to work, after fixing up some of the logic around 'profile' fetching. I think that the profile not getting set to null properly before logout might have been the culprit for the lingering fetch calls that re-validated the cookie.
I updated to use SWR for the profile fetching, which might fix some of the other bugs we've been seeing around signin status.
Solution
The way I finally solved the the 'inflight requests are resetting cookie' issue is:
calling
window.location.href= "/logout"
Then inside an emptypages/logout.tsx
page, I call theauth.signOut
function again and then finally redirect back to "/login" or "/signup"The reason this works is that window.location.href will cancel in-flight requests, whereas router.push() in next.js will not.
also had to add an abort controller on one fetch request that I couldn't stop because its called from the top level _app.tsx
https://frontend-digest.com/cancelling-fetch-requests-in-react-applications-58a52a048e8e