# NulogySSO [![Gem](https://img.shields.io/gem/v/nulogy_sso?label=nulogy_sso)](https://rubygems.org/gems/nulogy_sso "View this project in Rubygems") > **NOTE:** The default branch for this repository was changed to `main`. Please read [this Github blog post](https://github.blog/changelog/2020-10-01-the-default-branch-for-newly-created-repositories-is-now-main/) for more information. ## Auth0 For more information on Auth0 see the [Auth0 documentation](https://auth0.com/docs/flows/concepts/auth-code#how-it-works). ### Authentication Flow The Auth0 docs can be confusing, so we provide [a more detailed picture of the Authentication Flow](https://drive.google.com/file/d/1fbPZR6FmfetRzyQZVz16Hs2rqepY4XJZ/view?usp=sharing) implemented by this gem. ## Installation This gem is a Rails Engine. It follows best practices [documented here](https://guides.rubyonrails.org/engines.html). To begin with, add the gem to your Gemfile: ```ruby gem "nulogy_sso" ``` Install the gem: ```sh bundle ``` Routes can now be mounted into your application in `routes.rb` and served up at a specific URI prefix: ```ruby 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: ```yaml 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](lib/nulogy_sso.rb) for a list of required keys and [sso_config.yml](spec/dummy/config/sso_config.yml) for an example config file. ```ruby # 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.login_path } ``` 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](https://auth0.com/docs/jwt) stored as a browser cookie. Add this code to the `ApplicationController`: ```ruby 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 ```sh # 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`. Please consult [this documentation](docs/Testing.md) for advice on how to implement tests on an application using nulogy_sso. ### Deployment 1. Ensure that all tests are passing on the project 1. Increment the library version in [version.rb](./lib/nulogy_sso/version.rb), adhering to semver principles 1. Add a entry to [the Changelog](./CHANGELOG.md). 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. 1. Run these commands to complete the deployment. Rubygem push rights on this gem is required. Obviously, replace `X.Y.Z` with the version being deployed. ```sh # Commit changes to the files listed above git commit -m "Cuts version X.Y.Z" git push # Push the gem to Rubygems gem build nulogy_sso.gemspec gem push nulogy_sso-X.Y.Z.gem # Cut a release on GitHub git tag vX.Y.Z git push --tags ``` ### 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](https://semver.org/). Please add an entry into [CHANGELOG.md](./CHANGELOG.md) in your PR. Deployments are done manually on an as-needed basis.