I've implemented a passwordless auth system (where the users only login using a 'magic link' sent to their email) on my own. I know designing security systems without experience is really bad, so I'm asking to know if my system has any obvious holes. Here's how it works:
- User types their email & a unique username in JS client (SPA)
- The email & username is sent to my API server (in GET/query string)
- The API server consults the Users Database (see below for the design of this DB) to see if the email already exists
- If it doesn't, the email is added to the Users Database along with the username (new user)
- If it does, the API server ensures that the username matches the email, else responds with an error
- The API Server generates a high-entropy GUID (long, random string) and stores it in the Users Database (in the same row as email & username)
- The API Server emails the user with a link containing the GUID in a query string to a special '/auth/' route
- The API Server stores the exact time this email was sent in the Users Database
- If the link was not pressed within 30 minutes of that time, the GUID is removed from the Users Database (so the user has to login a again)
- If the link was pressed within time, the API Server generates a new Session GUID, stores it in Users Database & puts in a cookie that's exchanged in all upcoming requests (ie. every time a new request happens, the API Server ensures the Session GUID matches the one in the Users Database, indicating they're logged in)
- The Session GUID is removed from the Users Database if the user decides to log out
- The Session GUID is also removed every 3 days (so users have to log in every 3 days)
The Users Database has the following columns, with the username
being the primary key:
| username | email | magic_link_guid | magic_link_guid_date | session_guid | session_guid_date |
Some issues that I don't know how to fix:
- A database call is made for each request, that can't be good
- Handling user roles would be really difficult with this method
- This seems susceptible to XSS/CRSF attacks
Again, I know rolling out my own system is bad, but I can't find a ready-made passwordless system for .NET/C# :(.