This repo contains the frontend, styling and backend code for a login page. The site uses the HTML5 Geolocation API
on modern browsers to determine the GPS of the site visitor. Since IP address can also be used to track location, it is also stored in the GPS log.
The backend writes to a log of login attempts. This GPS log is stored in Firebase (test mode
). The backend is built fully instead of being stubbed out.
The server runs on node
, the frontend uses jQuery
along with raw javascript.
The testing suite in this repo (test/
) uses puppeteer to create a headless browser instance, where the site is loaded and different user paths are tested.
- Install
node
andnpm
on your computer. (Tested to work with nodev10.15.0
and npmv6.4.1
. Try to stick to these versions if possible.) - Install the
mocha
utility on your computer (npm i -g mocha
) for runningE2E
tests. - Clone this repo and run
npm install
inside it. The installation might take a while, mostly because of the size of thepuppeteer
module. If you have trouble runningpuppeteer
, there are useful troubleshooting tools here: https://github.com/puppeteer/puppeteer/blob/master/docs/troubleshooting.md
To run the server, run npm run server
. You should be able to load the site on http://localhost:8000/
. Here is a screenshot of what the login page looks like.
Any username is accepted, but the only password that is accepted is theworkapp0$
. On successful login, the page redirects to http://localhost:8000/success
. You can successfully log in regardless of whether you block or allow the HTML5 Geolocation
popup.
The site stores a cookie in your browser that will get written over on subsequent successful login attempts.
On the backend, this login attempt will be recorded. If the Geolocation HTML5 API is allowed, the following schema is written to the Firebase DB:
{ip:'::1', latitude:23.23798, longitude:12.2342, success:true, time:'Fri 08 May 2020 12:12:06 GMT', username:'joisdjfsdf'}
On the other hand, if the Geolocation HTML5 API is blocked, the following schema is written to the DB:
{ip:'::1', success:true, time:'Fri 08 May 2020 12:12:06 GMT', username:'joisdjfsdf'}
The IP address of the login attempt is recorded because this can also be used to impute lat / long coordinates after the fact in production. The success
key represents whether or not the login attempt was successful.
To run the testing suite, run npm run test
. There are 5 total tests, stored inside the test/
directory. Here is a screenshot with the test suite in action:
- The site needs to have a valid HTTPS certificate. It is unsafe to enter passwords over an
http
connection. - The Firebase DB needs to have restricted read / write rules so that only the webserver can write to it and the testing suite can read from it.
- The login page needs to not accept only one password and many usernames. Instead, there needs to be a
register
flow so that accounts can be created. At this point, authentication will require the entering of the correct username / password pair. - The webserver should not store the correct password in plaintext in the source code. Instead, the entered password needs to be hashed and salted using a module like
bcrypt
. At that point the hashed password can be stored in a database and compared to entered one. - The testing suite needs to cover pre-HTML5 browsers where the Geolocation API is not available.
- We assume that the browser is HTML5 enabled.
- We assume a non-malicious router setup with safe WiFi (
http
assumes good intent from all parties) - We assume the reliability of the Firebase service. If this service is down, database writes may fail, which could prevent successful authentication.
- If the HTML5 Geolocation API is blocked, we assume that the IP isn't spoofed. If the API is blocked and the IP is spoofed, the login attempt may have no idea where the request came from.
- We assume that the user isn't visually impaired. There has been little focus on making the site accessible to those surfing the net with disabilities.
- We assume that this site is accessed from Earth. GPS won't work well on Mars ;)