NulogySSO

Gem

Auth0

For more information on Auth0 see the Auth0 documentation.

Installation

This gem is a Rails Engine. It follows best practices documented here.

To begin with, add the gem to your Gemfile:

gem "nulogy_sso"

Install the gem:

bundle

Routes can now be mounted into your application in routes.rb and served up at a specific URI prefix:

mount NulogySSO::Engine, at: "/sso"

# Optional redirects
get "login", to: redirect("sso/login")
get "logout", to: redirect("sso/logout")

The engine now needs to be configured. First create a YAML config file, perhaps named config/auth_sso.yml, to configure your app's Auth0 settings. This assumes that the necessary Auth0 applications have been created in the correct Auth0 tenants. An example configuration for local development would look like:

default: &default
  audience: <%= ENV.fetch("SSO_AUDIENCE", "auth.nulogy.net") %>
  client_id: <%= ENV.fetch("SSO_CLIENT_ID", "SSO CLIENT ID FROM AUTH0") %>
  client_secret: <%= ENV.fetch("SSO_CLIENT_SECRET", "SSO CLIENT SECRET FROM AUTH0") %>
  base_uri: <%= ENV.fetch("SSO_BASE_URI", "") %>
  cookie_prefix: <%= ENV.fetch("SSO_COOKIE_PREFIX", "") %>
  login_uri: <%= ENV.fetch("SSO_LOGIN_URI", "") %>
  redirect_uri: <%= ENV.fetch("SSO_REDIRECT_URI", "") %>

development:
  <<: *default
  base_uri: <%= ENV.fetch("SSO_BASE_URI", "https://auth-dev.nulogy.net") %>
  cookie_prefix: <%= ENV.fetch("SSO_COOKIE_PREFIX", "dev") %>
  login_uri: <%= ENV.fetch("SSO_LOGIN_URI", "http://localhost:3000/sso/verify_authentication_code") %>
  redirect_uri: <%= ENV.fetch("SSO_REDIRECT_URI", "http://localhost:3000") %>

test:
  <<: *default

production:
  <<: *default

With that available, you can configure the engine with an initializer file. This is where NulogySSO can be customized according to your application's needs. Put the below code into config/initializers/nulogy_sso.rb, with the appropriate modifications implemented. For sso_config, refer to nulogy_sso.rb for a list of required keys and sso_config.yml for an example config file.

# Compiles config/auth_sso.yml into a Ruby object. An error is thrown if required keys are missing.
# See lib/nulogy_sso.rb for required keys.
NulogySSO.sso_config = Rails::Application.config_for(:sso)

# Return the user matching the provided email, or nil if not found.
NulogySSO.find_user_by_email = ->(email) { nil }

# Handle errors from the SSO authentication flow, according to the app's design.
# This includes internal errors from the Auth0 gem (ie, token signature mismatch) and no user from the app DB matching the email from the JWT.
# The controller is passed as an argument to give the handler access to the "controller context", which is useful for tasks such as rendering a view.
NulogySSO.handle_sso_error = ->(controller: , error:) { }

# Handle how unauthenticated requests should be responded to. The default is to redirect to the defined login page.
# For API based applications this should be overriden to provide a meaningful error as per your API's contract (i.e. an HTTP 401 error code)
# Additionally, this could be overriden if an application should bypass SSO when running tests.
NulogySSO.handle_unauthenticated_request = ->(controller) { controller.redirect_to sso_engine. }

The app is now ready to authenticate a user with Auth0! With NulogySSO and Auth0, the user's identity is maintained across requests (and apps!) via a JWT stored as a browser cookie. Add this code to the ApplicationController:

class ApplicationController < ActionController::Base
  include NulogySSO::ControllerHelper
  before_action :authenticate_sso_user
  # ...
end

As an added bonus, NulogySSO also emulates the common Devise pattern of making the current User's user model object available via current_user. This is made available through including ControllerHelper.

Development

Setup

# Setup Ruby
rvm install $(cat .ruby-version)
bundle

# Setup project files
cp .env.sample .env
rake app:db:test:prepare

# Launch Docker containers, required for testing
docker-compose up -d

Testing

Tests must be run manually before submitting a PR. This can be done using rspec spec.

There are multiple helpers made available via the NulogySSO::TestUtilities module. These are helpful for doing things such as grabbing test JWT values and interacting with a Mockserver mock of the Auth0 API.

It is a common use case for a Rails app to switch from Devise-powered authentication to Auth0. This would also require updates to test helper code, similar to functionality that Devise provides out of the box. See this example of how a test helper could be written for an app using a feature flag (e.g. environment variable) to switch between Devise and NulogySSO authentication.

  1. Ensure that all tests are passing on the project
  2. Increment the library version in version.rb, adhering to semver principles
  3. Add a entry to the Changelog. Move all entries in the Unreleased section into the new version's section. Now is also a good chance to add in any addition bullet points that may have been forgotten in the Unreleased section. Append today's date to the new version.
  4. Run these commands to complete the deployment. Rubygem push rights on this gem is required. sh gem build

Contributing

Feel free to create a PR if you wish to add new functionality to this Engine or detect a bug. A developer on CN1 will review and merge.

This project follows Semver Versioning. Please add an entry into CHANGELOG.md in your PR. Deployments are done manually on an as-needed basis.