I'm working on an authentication system for my college project and I find the available information on secure auth mechanisms to be quite limited. Most sources recommend using third-party solutions. Here's the plan I've come up with:
1. When a user logs in, I generate both a refreshToken and an accessToken.
2. The refreshToken gets stored in a session in my database (I'm using Redis) and placed in a secure HTTP-only cookie.
3. My React app will request the accessToken from the server when it loads. The server will validate the refreshToken and send back a new accessToken. This accessToken will then be used for further server requests, and I'm only keeping it in memory instead of local storage or cookies.
4. The accessToken will expire after 15 minutes, and the client app is supposed to refresh it. The refreshToken lasts for 7 days, after which the user would need to log in again.
5. Finally, on logout, the refreshToken will be deleted from Redis.
So, does this approach seem secure enough? What improvements could I make?
5 Answers
Just a thought: almost every programming language has free auth libraries available. While building your own can be a good learning exercise (which seems to be your case), it's often better not to have to reinvent the wheel!
Check out this diagram that lays out what you've described: [link](https://fusionauth.io/articles/login-authentication-workflows/spa/oauth-authorization-code-grant-jwts-refresh-tokens-cookies) (it includes about 15 different auth workflows). I also wrote an article on this topic: [link](https://fusionauth.io/blog/securing-your-api). You should also consider the OAuth security BCP [link](https://datatracker.ietf.org/doc/html/rfc9700); it’s packed with useful practices. One thing to be aware of is that your refresh token management and API requests seem to be handled by the same server. While you can use OAuth here, it might complicate things unnecessarily. If it’s a real-world application, I’d suggest using API keys instead unless you plan on splitting your server functionalities later on.
Have you looked at Lucia Auth? It's a solid resource worth checking out: [link](https://lucia-auth.com).
Overall, your approach is looking good! Just a little heads up: it's usually advised not to try creating your own authentication from scratch, since even a minor oversight can lead to big security risks. But given that this is a learning experience or proof of concept, all is well. Have you considered using JWT tokens for your access and refresh tokens? They’re securely signed, which helps prevent tampering and keeps malicious users from editing tokens easily. Also, it might be wise to make your refresh tokens single-use for extra security—when one is used, generate new access and refresh tokens to minimize risks of replay attacks if they ever leak.
I'd recommend keeping it simple. Generate a session ID when the user logs in and send that to the client. Store a serialized JSON object in Redis and reference it when checking if a user is authenticated. When they log out, just delete the session. You can look into libraries like "express-session" and "connect-redis" for practical examples. Most tech stacks have cookie-session models available, and since Redis is popular for that, you're on the right track. Honestly, session cookies can be easier to manage than dealing with access and refresh tokens for straightforward setups like yours.
That's a valid concern. Also, remember that during the creation of your React app, you can pass initial props. Often examples leave this empty, but including things like the user state can be beneficial, especially if the cookie is HttpOnly.
Aren't session cookies vulnerable to CSRF though?