/not-pass

Very basic and exploratory implementation of pasword-less, email-only login

Primary LanguageJavaScriptThe UnlicenseUnlicense

not-pass

This is a simple project that demonstrates how to log in with just the user's email and no password. The authorization is done by sending an e-mail to the user with an authorization link. Once followed, the session is automatically authorized.

Think about it as an 1.5FA system! Better than SFA but not fully 2FA.

Login flow

  • The client sends an email address to the server.
  • The server sends an authorization email with a unique token linked to that email address.
  • Once the server confirms the email was sent, the client opens a websocket connection to be notified when the login is authorized.
  • The user follows the authorization link in the email.
  • The server validates the token, the email address and sends the authorization message back.
  • The client receives the authorization and proceeds.

Benefits

Some benefits of this approach are:

  • Easier to use: no passwords to manage or remember!
  • Better user experience than traditional "create user/pass, verify email and login" flows.
  • Instant user onboarding: user creation and login are a single verified step.
  • Easier to implement: no passwords will be leaked/compromised ever.

Technical notes

The website is a React application that uses only functional components and hooks. It can be built and served through any static hosting mechanism.

The API is an Express server that exposes the HTTP routes to login, logout, etc. It does not serve the website to demonstrate it can opperate completely independent of the UI. That allows other login flows from CLI tools, standalone applications, not only the website.

The user's login status is stored in a server-side in-memory session. A Redis server or any other session store could be easily implemented.

The server communicates the login/authorization through a Socket.IO connection opened by the client. The server also sends emails using Nodemailer and a Gmail account.

The implementation is on purpose focused on simplicity and easy-to-follow code. There are some edge cases not conisdered, checks not implemented and many security improvements that must be done before using this approach on a real-world product.

Run it locally

The simplest way to run the example is to use Docker.

First create an api/.env file with the following variables:

Then create a web/.env file containing:

Finally, in the root folder tell Docker to start the API and website:

$ docker-compose up

The website will be available at http://localhost:3000.

Note

In order to send emails using Gmail, it is required to enable the "less secure apps" setting in your Google account:

https://myaccount.google.com/lesssecureapps

Demo deployment

There is a running demo at https://not-pass-web.now.sh deployed using Zeit Now.

To deploy your own, install now and login.

$ npm i -g now
$ now login

Then configure the required Now Secrets:

$ now secret add not-pass-email-user <your Gmail email>
$ now secret add not-pass-email-pass <your Gmail password>
$ now secret add not-pass-session-secret <secret to sign cookies>

With the secrets set, deploy the API server:

$ cd api
$ now

The last step is to set an alias so that deployment URL matches the one set in the API_URL environment variable set in api/now.json and REACT_APP_API_URL in web/now.json:

$ now alias set <the API deployment url> <the URL set in API_URL>

Then is the turn to deploy the web:

$ cd ../web
$ now

As with the API server, an alias has to be set for the website so it matches WEB_URL in api/now.json:

$ now alias set <the website deployment url> <the URL set in WEB_URL>