Skip to content

Rails personal project with user management & authentication to proxy serve a private, single-page app.

License

Notifications You must be signed in to change notification settings

jfroom/jfmk-auth

Repository files navigation

JFMK-Auth Build Status

Rails personal project with user management & authentication to proxy serve a private, single-page app.

See blog post "JFMK-Auth Walkthrough' for commentary on the technolgoies.

Technologies

  • Rails 5, Postgres, Selenium, AWS S3, HAML, CoffeeScript, Bootstrap, SCSS
  • Docker Compose for development & test; Travis for CI/CD; Heroku Pipelines for production
  • 'Simple' has_secure_password Rails API for authentication & cookie sessions. User is locked out after X failed attempts.
  • Authenticated users are served single-page app with a proxied index page, and expiring pre-signed URLs for sensitive S3 hosted content are parsed/injected. Demo content is instance of jfroom/portfolio-web.
  • 'Auto-login' feature can be enabled for a user, which creates a simple and aesthetic url: https://example.com/username. Be aware that using this lowers security threshold. Can implement has_secure_token in future if this becomes a concern.
  • Tests with MiniTest for models & integration, and Capybara Selenium acceptance tests running in a docker service with Chrome standalone.
  • VNC locally into the Selenium session to interact and debug.
  • Let's Encrypt SSL certificates auto bound to the custom Heroku domain with letsencrypt-rails-heroku.
  • Notify admin by email when user has logged in; sent with SES
  • Mailer job runs async in background job with Sucker Punch
  • Project initially seeded with nickjj/orats Rails template which was very helpful figuring out the docker-compose setup.
  • HoundCI & Rubocop help keep styles consistent

Demo

https://jfmk-auth-demo.herokuapp.com

Credentials:

  • admin:Admin123
  • user:User123

Note:

  • In demo mode, new users will not be saved, and existing users will not be updated, or deleted. Users will also not be locked out after repeat fails. This is done in order to keep the users active for future visitors to demo, and to prevent system abuse.
  • Demo instance runs on a 'free' dyno server so it is probably sleeping, and may be a little sluggish starting up.

Getting started

Required

  1. Install Docker 17.03.0-ce+. This should also install Docker Compose 1.11.2+.
  2. Verify versions: docker -v; docker-compose -v;

Recommended

  1. Install some docker-compose aliases. I use docker-compose.plugin.zsh for oh-my-zsh. (Ex. alias dcup='docker-compose up)
  2. Install pgAdmin for a SQL gui client.
  3. Install VNC Viewer to view & interact with selenium sessions that would otherwise be headless.

Build

First run

docker-compose up --build Build the docker images, install dependencies, and start the services.

Once the docker services are build and running, the web service will occupy the current terminal with the running puma server log. Open a new terminal instance to issue any additional commands.

docker-compose exec web rails db:setup Set up the database.

docker-compose exec web rails db:seed Seed the database with two users: admin:Admin123 and user:User123. Use the admin login to change those immediately.

Development

docker-compose up Stand up all services. Also installs any new gems if necessary (after switching branches, or pulling from a repo).

open http://localhost:3000/ Visit the web app service.

docker-compose exec web bin/update Install a new gem, or to run a database migration.

docker-compose down; docker-compose up -d; docker attach jfmkauth_web_1 A common call chain during development to stop any existing/hung containers, stand up all services in detached mode, connect to view web service only (to view running log and interact with byebug). Be aware 'exec' bypasses the entrypoint script which ensures gems are up to date (use docker-compose run --rm ... instead of docker-compose exec ... if that is a concern - had to do this for the CI override file).

docker-compose build If there are changes to the Dockerfile or the docker-compose files, the containers may need to be rebuilt.

These docker shortcuts to clean up old docker images/containers/volumes is very handy.

Database

  • Launch pgAdmin and configure a connection to: Host: 0.0.0.0, Port: 5432, User: jfmk_auth, Password: yourpassword.
  • Quick tip: To find User table with the seed users: Schemas > Public > Tables, or use the SQL panel.

Test

docker-compose exec web rails test Run tests (also importantly sets Rails.env = 'test').

vnc://localhost:5900 password:secret To interactive with and debug Selenium sessions, use VNC to connect to the Selenium service. VNC Viewer works well, and on OS X Screen Sharing app is built-in.

To visit the test app on local machine: open http://localhost:3001/. To visit in the VNC session visit: http://web:3001.

Commits to master are automatically tested by Travis CI.

Tests use:

Deploy

Environment

Deploys to a Heroku pipeline with three different apps: staging, demo and production. Currently, releases are infrequent, so just using the Heroku Pipelines GUI to promote staging to demo & prod.

Ultimately would prefer to deploy a Docker image to Heroku — but currently that features is in beta and support for pipelines is spotty.

So for now, Docker and Heroku environments are aligned as closely as possible. Biggest exception being the Dockerfile runs Debian Jessie, and Heroku uses Cedar-14 (Ubuntu 14.04 trusty).

Manual

  1. Install Heroku CLI.
  2. Use Rails 5 Getting Started guide for first deployment.
  3. source bin/deploy.sh for iterative deploys.

Continuous Deployment

If the Travis build passes, it will automatically deploy to staging. See .travis.yml.

SSL

On the production app's custom domain, Let's Encrypt handles the free SSL certificate with Pixielab's pixielabs/letsencrypt-rails-heroku gem.

Certificate is good for 90 days. To renew, run or schedule a variation of heroku run -a jfmk-auth rake letsencrypt:renew.

Noteworthy

Docker's Bundler Cache

Bundler installs and keeps track of all the gem libraries. Keeping docker container build times low is not trivial when bundler is involved. It took some time & research to optimize bundler's cache, so is worth an explanation. Credit to the unboxed team for this bundler cache technique.

The web service uses the Dockerfile to build itself. It defines an ENTRYPOINT ["/docker-entrypoint.sh"] bash script which will run the initial bundle install. Gems are stored in a docker volume called bundle_cache (see docker-compose.yml). When any gems are added to the Gemfile, this entrypoint script will notice and install them into the cache volume. Because of the entrypoint, there is no need to call a special command to do this other than docker-compose up. This technique is unique because the cache volume will persist across docker image changes, which reduces build times (and increases sanity) during local development.

Alternatives and Caveats

  • S3Auth.com If you want a quick way to just password protect a static S3 website with Basic HTTP Auth, check out S3Auth, and this related article.
  • S3 auth proxy. There are a few other project that handle S3 proxy with authentication. But one drawback is the app server becomes a bottleneck — which becomes more obvious for large files like video. A mix of pre-signed S3 expiring private content URLs, and publicly served S3 non-sensitive files (e.g. JS, CSS, some content) alleviates this. Admittedly, the proxy/injection I've cooked up is a little brittle — which leads to my next point.
  • Simple content views. app/controllers/proxy_controller which parses/proxies/pre-signs S3 content is tightly coupled to my personal needs. If you choose to clone/fork this project for the user management aspect, you'll probably want to yank that controller, related tests, and environment vars. You could just replace it with simple HTML/HAML views.
  • Devise. In future projects I will use Devise for authentication. Just wanted to write my own first to better understand the auth and user management process.

License

Copyright © JFMK, LLC Released under the MIT License.

About

Rails personal project with user management & authentication to proxy serve a private, single-page app.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published