wasp
wasp copied to clipboard
Discuss how we use authentication
Wasp currently handles sessions/authentication by having the client (i.e., the browser) make a request towards /auth/me:
- If the response comes back as
200 OK, it also contains the session info (username, user ID, profile picture, etc.) - If the response comes back as
403 Forbidden, the client interprets it as the user not having a session
This might be problematic because of two reasons:
- The error response
403 Forbiddenis semantically not ideal. It should instead come back as401 Unauthorized. In short,401is the status code to return when the client provides no credentials or invalid credentials.403is the status code to return when a client has valid credentials but not enough privileges to perform an action on a resource (source, another good explanation) - It is a bit unusual to return an error response code at all.
4xxstatus codes imply a client-side error (i.e., the client has done something incorrectly). In our case, calling/auth/meis the client's regular procedure for determining whether the user has a session (and is not really an error). Relying on an error response for doing this seems analogous to throwing an exception in non-exceptional scenarios. On the other hand, having two endpoints (one for checking whether we have a session and another for retrieving the session) seems fragile. The third possible solution is interpreting the endpoint as something like "try to get a session" and always return a successful response, either containing the session data or information that there is no session.
If we're keeping the current pattern, I'm sure the response should be changed to 401.
If we want to change the current pattern, I'm not sure what the best approach is (just putting the question out there :)).
Interesting discussion and nice analysis!
Session -> I wouldn't call it a session. We don't have state on the server that would represent a session, instead we deal with JWTs, so we are sessionless, to my best knowledge.
We have /login, /signup and /me routes on server.
login and signup are used to exchange credentials (username and pass) to obtain the valid JWT (I am trying hard to not say "JWT token" :D!). Then, we can use that JWT to do various requests, of which one is /me, which returns the user profile. But that route, /me is in theory not in any way different to any other route out there, for fetching the resources. It is not part of authorization flow.
You are right about 403 vs 401 -> in /me, we should use 401 instead!
Your point (2) -> after the arguments above, I believe it becomes obsolete? It makes sense to return error on /me, since it is a route that requires authenticated user -> you can't fetch your user profile if you are not authenticated!
I wouldn't call it a session. We don't have state on the server that would represent a session, instead we deal with JWTs, so we are sessionless, to my best knowledge.
Ah yes, speaking of sessions and tokens, I've made another issue talking about this very topic: #573
It makes sense to return error on /me, since it is a route that requires authenticated user -> you can't fetch your user profile if you are not authenticated!
Hm, yes. This is also something I tried to emphasize above. If the error response truly is appropriate for this endpoint (i.e., "you're getting an error because you shouldn't have even requested this without authentication"), then the client using the same endpoint for checking whether the user is authenticated seems a bit hacky. It's kind of like finding the length of an array by accessing and incrementing indexes until we get an exception (although some would probably call this "pythonic" :))
You are right about 403 vs 401 -> in /me, we should use 401 instead!
As for this, I'll create a "good first issue" right away. @shayneczyzewski Please don't solve it while I'm not looking :sweat_smile:
- Sessions vs tokens -> ok great, we can continue sessions vs tokens discussion in that other issue!
- Misusing auth/me -> you have got a point there! It is as you described - we check if we are logged in by trying to fetch the details on ourselves, our user profile. If that fails, we conclude we are not logged in. The alternative could be to have special route for just checking if we hold valid token or not, that never fails but returns smth like true or false -> but that just felt redundant to me, since if you have valid token, you almost always want to fetch a bit of information about yourself, your user profile. Or, we could repurpose
auth/meto not throw an error but instead return some kind of "falseish" data. But then that felt a bit weird to me, like server is making some kind of exception, assuming what client needs, ... .
But looking at it I don't really see any of these choices having any effect on practical usage? Is there an issue with us "hackishly" using auth/me? Is there an issue with auth/me returning falseish thing on invalid token? Not really right, it is just different tiny trade offs?
- 403 to 401 -> ok great! So only point (2) is left to discuss here in this issue.
But looking at it I don't really see any of these choices having any effect on practical usage? Is there an issue with us "hackishly" using auth/me?
The only issue is the errors popping up in the console. No usability stuff really, just aesthetics (i.e., I wouldn't expect a site functioning properly to throw a 401 error every so often).
But looking at it I don't really see any of these choices having any effect on practical usage? Is there an issue with us "hackishly" using auth/me?
The only issue is the errors popping up in the console. No usability stuff really, just aesthetics (i.e., I wouldn't expect a site functioning properly to throw a 401 error every so often).
That is a good point. Would you open a special issue for this then, focused on how to avoid this 401 hacky thing? And then we can close this one.