Closed heysailor closed 6 years ago
I believe this is what the standalone option does
(Extensively!) edited initial comment to make it clearer. As far as I can see, standalone issues a single non-expiring JWT in exchange for correct login details.
Hi @heysailor thank you for your extensive ticket. Sorry I didn't get back to you as of yet, was completely off the grid for 2 weeks.
Thank you for your help, this is now released.
Thanks for a great looking project. Reading your docs, it looks like you're oriented towards establishing a session with an API using a cookie, whether standalone or integrated, after obtaining a JWT via ooth to show authentication status.
However:
ooth
for sessionless authentication.Non expiring JWT vulnerability
Looking at the
ooth
module, a non-expiring JWT is issued in exchange for a valid login. This means you can never log out a user - if they have the JWT, they can always pass it to the API for use, and it will be valid. Unless the API tracks a JWT blacklist, it will be unable to block malicious users. Tracking a blacklist means database calls, and the point of JWTs is to prove authentication without database access.ooth/src/index.js:319:
I think it would be preferable to use short lived JWTs. This ensures that creating a session with the API can only be done for a limited amount of time. The session cookie can be as long as the API wishes.
The JWT expiry can be set as an
exp
field as observed byPassport
.Enabling sessionless JWT authentication with refresh tokens
There's a significant use case of authenticating every API request with a JWT, instead of a cookie based session. This is the typical authentication method used in mobile apps, eg React Native. For this use case, if JWTs are to have an expiry, a method must be provided to obtain new JWTs without logging in every time.
A refresh token is typically used: https://www.jaygould.co.uk/dev/2017/07/18/jwt-token-refresh-redux-react-native.html
In short, using the refresh token causes a database check to ensure:
The UI experience for the user is the same, but with more security:
It seems this would be handy for many and will increase security.
JWT size/single concern contents
A disadvantage to using the
ooth
JWT token for authenticating all requests is that theooth
use does not quite adhere to the JWT spec....they are mean to be compact.Ooth
places the user profileuniqueFields
information into the JWT. Okayish if the JWT is just used once to send to an API to establish a cookie-based session. But sending a large JWT token for every request becomes a problem when the user profile is large - eg Facebook data.For instance, when logging in with the
local
strategy, the JWT token provided on login contains:The JWT is being used to transfer user data, rather than the single concern of authentication status. This mix of concerns is reflected in the response body, which has both a user field, containing the same information as encoded in the token field.
The minimal, single-concern JWT token implementation would be to only place the user
_id
(and perhaps as a future feature authorisation data such as roles or similar) into the JWT. The fact of having a valid JWT with that user id means that authentication has occurred. If the API needs more user data, it can always access the database.This is how Meteor approaches tokens - a
resumeToken
isn't even a JWT; it's simply a random string which optionally expires, see line 589. Holding theresumeToken
signifies only that the user was authenticated; the token itself contains no data.Minimal JWT:
Naturally, it's still very handy/essential for each strategy to administer profile fields. They can still be provided in the
user
field of the response body, or accessed by an API from the database.Happy to potter along with a PR(s) to address these issues, but would be great to get thoughts before starting.