A login problem can look like a broken button, a redirect loop or a dashboard with no records. Those symptoms don't all have the same cause.
Before rewriting the frontend, I want to follow what happened between the browser, authentication service, session and database.
Did the login request actually succeed?
For Supabase password login, check the returned data and error. The click handler running doesn't tell me whether the provider accepted the request.
const { data, error } = await supabase.auth.signInWithPassword({
email,
password,
})
if (error) {
console.error(error)
return
}
This example shows where to check for an error. In an actual application, sanitise logs and don't print passwords, tokens or unnecessary private details.
I need to separate a failed authentication call from a successful call followed by the wrong reaction in the interface.
Does the app have the session it expects?
A local boolean such as isLoggedIn can make the page look signed in without proving a valid session exists. It may also disappear after a refresh.
Use the authentication client's session information for the client interface. Protected server operations still need verified identity and backend authorisation; client state alone isn't permission.
Did the route wait for the session check?
When the app first opens, a session may still be loading. Redirecting immediately because there is no user yet can send a signed-in person back to login before restoration completes.
I want to distinguish these states:
auth loading
authenticated
unauthenticated
While the check is still running, show a loading state. Then choose the appropriate screen when the result is known.
Are the redirect settings correct?
Email confirmation, recovery and OAuth can take the person outside the app and back again. Check the Site URL, allowed redirect URLs, protocol and callback route for the deployment being used.
A localhost URL left in production or a mismatch between domain variants can explain behaviour that initially looks like a routing bug.
Signing in doesn't grant access to every row
Authentication identifies the person. Authorisation decides what they may do. A signed-in user can still be blocked from database rows by Row Level Security.
For a query such as:
const { data, error } = await supabase
.from('projects')
.select('*')
Check the permissions and the relevant SELECT policy. A valid login doesn't automatically mean this user should see these records.
Don't disable RLS as a permanent fix. Work out which rows should be accessible and enforce that rule.
I compare the ownership values
Look at a failing row. Does the owner field contain the authenticated user's ID, a profile ID, an email or nothing? Check the types too.
A correctly written policy can deny access when the stored ownership data is wrong. One real record is often easier to reason about than only staring at the policy.
I check what survives sign-out
Private profile data and cached requests should reset appropriately when the identity changes. Otherwise another account may briefly see the previous user's interface or information.
The backend must still enforce permissions. Clearing the UI is also important for keeping private client state from carrying across accounts.
Is it an auth error or a network error?
The Network panel can show whether the request left the browser, what status came back and whether a preflight or origin restriction blocked it.
If the browser couldn't complete the request, I need to investigate that rather than assume the credentials were rejected.
I test with two ordinary accounts
Check what each account should see, then sign out and switch. Verify that private state clears and that neither account can read or change the other's records.
I want the system to work for the actual access model, not only for my first development account.
The order I follow
Request, session, loading state, redirects, permissions, ownership data, cached state and the actual network response. Checking those in order helps me narrow the problem before changing more code.
For the current API and setup, see Supabase password sign-in, the React Auth guide and Row Level Security. This is a debugging guide, not a claim that these examples were tested against your project.
