-
Couldn't load subscription status.
- Fork 0
Implemented complete auth system using Supabase #34
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
base: main
Are you sure you want to change the base?
Conversation
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.
Thank you for the great work @YousraElmag. I left some comments and questions and maybe you can explain to us the whole flow in the meeting. Here are more general comments:
- instead of using supabase directly in the pages, it's better to make an authService, so it become for example like this:
//resetPassword page
...
const {error} = await authService.resetPassowrd(email, "auth/resetpassword");
...
//services/authService/authService.ts
export default {
resetPassword: (email, route) => {
supabase.auth.resetPasswordForEmail(email, {
redirectTo: `${baseUrl}/${route}`,
});
}
login: ...here it's easier to mock the auth in tests, or to change something in the auth service
-
Also as a suggestion we can use react-hook-form for better form management.
-
Final question about security: our pages are "use client" and we use supabase within them, doesn't this expose its credentials?
package.json
Outdated
| ], | ||
| "dependencies": { | ||
| "@supabase/auth-helpers-nextjs": "^0.10.0", | ||
| "@supabase/auth-helpers-react": "^0.5.0" |
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.
Do you have a specific reason for placing those in the parent package? Otherwise, they should be moved to web/package.json
apps/web/src/app/page.tsx
Outdated
| export default function Home() { | ||
| return ( | ||
| <main className="min-h-screen bg-gray-50 flex flex-col items-center justify-center p-8"> | ||
| <RegisterForm /> |
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 page is the first thing rendered on the website. To organize the landing page files we have them in a hidden directory _landing/page.tsx and mapped it to here.
So I think this page should stay as it's (unmodified) and you can add temporary buttons in the _landing/page.tsx that leads to the login/register pages.
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.
I forgot to update that.
I just changed page.tsx quickly to test my stuff since the landing page isn’t ready yet.
I’ll move everything to _landing/page.tsx soon, no worries!
| import { useRouter } from "next/navigation"; | ||
| import { supabase } from "@/lib/supabase/client"; | ||
|
|
||
| export default function RoleSelection() { |
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.
In the design we made the role selection part of the register page and not an independent one to make the flow easier for the user (the user doesn't have to deal with a whole page just to select the role).
You can change this into a special component in the register page.
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.
In my current form, when users register normally, they select their role directly.
But when signing up with Google, the role doesn’t get saved in the metadata automatically, that’s why I made a separate role selection page.
If you have any other suggestions or better ways to handle role assignment for Google sign-up, I’d love to hear them!
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.
Oh! I didn't see that. Here is some suggestions.
- before the user clicks in the google button, role must be selected in the normal register form.
- since we need the role info later we can store it temporarily until we finish the auth using one of these methods:
in the client (e.g. local storage), or in the server (harder and complicate things), or in the url param of the callback (easy). Claude 4 suggested the following: state url param as a standard part of the oauth flow:
//register page
const stateData = {
userType: userType
}
// Encode state as Base64 string
const state = btoa(JSON.stringify(stateData))
await supabase.auth.signInWithOAuth({
provider: 'google',
options: {
redirectTo: `${window.location.origin}/auth/callback`,
queryParams: {
state: state // OAuth standard parameter
}
}
})
//callback after oauth
const stateData = JSON.parse(atob(state))
const userType = stateData.userType| const [message, setMessage] = useState(""); | ||
| const router = useRouter(); | ||
|
|
||
| useEffect(() => { |
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.
Nice that you added a reset-password. I think we forgot it in the design. However I didn't understand why do we have to open a session here. Could you please explain it to me?
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.
In the reset password page, the link sent to the user’s email contains tokens (access_token and refresh_token) in the URL hash. We use these tokens to open a temporary session with supabase.auth.setSession so the user can change their password without logging in again.
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.
Thank you for the explanation. I thought the reset password is done by passing the token with the new password.
| className="w-full p-3 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-[#1a8cff] focus:border-transparent" | ||
| /> | ||
| </div> | ||
| <div> |
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.
Usually I prefer to separate components so it's easier to reuse and manage. Example: a component called <EmailField /> with its validation can be reused in (login page - register page - reset password page - edit profile page)
| export default function AuthCallback() { | ||
| const router = useRouter(); | ||
|
|
||
| useEffect(() => { |
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.
can you explain to me what is happening in this page?
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 page checks if the user is signed in after Google login.
If the user has no role, it sends them to choose one.
If signed in with a role, it sends them to the home page (dashboard).
If not signed in, it sends them back to login.
After we finish building the dashboard pages, we will redirect the user to their dashboard instead of the login page.
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.
Thanks for the explanation.
You can make a placeholder pages with only one text e.g. "Dashboard for Client" , "Dashboard for Provider"
also if the user is new instead of going to the dashboard we can send them to the profile page to complete the information. and maybe we can have in supabase a field (isOnboarded?) to decide this
|
Thanks a lot for your feedback! You're totally right — using an authService makes the code cleaner and easier to test. I’ll refactor that part soon. |
|
Changes in Authentication Code: |


Added pages for:
useRegister,useForgotPassword).++++++++++++++++++++++++++++++++++++
Added RoleSelection component:
-Upon submission, the selected role is saved to the user's metadata in Supabase using
updateUser.