I'd like to implement a password-less auth flow for my mobile app that only requires a user clicking a link in their email to log in. Similar to how Slack handles auth. I'll be using node
and jwt
for this implementation.
I think I've come up with a secure design, but I'm sure I'm missing something. I would love some critique from the community.
Here we go:
- User opens the mobile app.
- We check to see if user has a token in their local storage.
- If they do, we add that token to their headers and send to the home page of the app.
- Else, we prompt them to enter their email to get started
- When they click "Submit", we POST that
email address
to therequestMagicLink
endpoint on our server. - The server checks the database for a user with that
email address
- If we find a user with that email, we take the
id
from that user - If the user does not exist, we create a new user, and get that
id
- We use JWT to generate a token with the
id
, and oursecret
that expires after1 hour
- We send that token to the user via a link in an email.
- Upon being clicked, that link sends a GET request to our server at the
magicLogin
endpoint with thetoken
in a query param - We verify that the token is correct using JWT and our
secret
. - If it fails verification, we redirect the user to the screen where we prompt them with their email to get started.
- If it's successful, we generate a new JWT token using their
id
, and oursecret
thatdoesn't have an expiration
, then pass that back to the user in the params of a URL that redirects them to a success page in our app. - The app takes the token from the param and stores it in local storage until the user chooses to logout, and the user is redirected to the home page.
- The requests to the api all now contain the token in the headers, and the user is good to go.
EDIT (adding additional thought): Something I'm considering to make it more secure: What if we split the token into 2 pieces, and send half to the mobile device and the other half to the email. That way, only the user with access to that email AND access to that specific device will be able to authenticate.
secret
is securely and randomly generated. Also you should prevent one token being used twice to receive a permanent session. In addition, when sending the permanent token to the used, avoid putting it in the GET parameters. Lastly, make sure to invalidate sessions server-side if users log out or change their password (in the latter case, invalidate *all sessions associated with that user).