From 02283fe4979ad055a20131166628a32b3c152897 Mon Sep 17 00:00:00 2001 From: IN COMMON Collective Date: Fri, 26 Mar 2021 15:24:16 +0100 Subject: [DEV] WIP: explore sso login alternative --- app/controllers/application_controller.rb | 1 + app/controllers/welcome_controller.rb | 2 +- app/lib/sso/from_discourse.rb | 14 +++- config/application.rb | 1 + config/database.yml | 6 ++ config/environments/development.rb | 3 + config/environments/staging.rb | 115 ++++++++++++++++++++++++++++++ config/initializers/sso_config.rb | 7 +- config/routes.rb | 2 +- config/sso.yml | 17 +++++ config/webpacker.yml | 2 + 11 files changed, 161 insertions(+), 9 deletions(-) create mode 100644 config/environments/staging.rb create mode 100644 config/sso.yml diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 1eff1a9..25700af 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -4,6 +4,7 @@ class ApplicationController < ActionController::Base require 'sso' + SSO::FromDiscourse.config = Rails.configuration.sso before_action :current_user diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb index ad9cd95..d5f5fe9 100644 --- a/app/controllers/welcome_controller.rb +++ b/app/controllers/welcome_controller.rb @@ -6,7 +6,7 @@ class WelcomeController < ApplicationController # GET / def index @map = Map.first - @taxonomy = @map.taxonomy + @taxonomy = @map&.taxonomy @resources = Resource.order(:uuid).page params[:page] Rails.logger.info "WECLOME ///// #{@resources&.count || 0}" end diff --git a/app/lib/sso/from_discourse.rb b/app/lib/sso/from_discourse.rb index 94969c9..8c5eea7 100644 --- a/app/lib/sso/from_discourse.rb +++ b/app/lib/sso/from_discourse.rb @@ -14,12 +14,12 @@ module SSO # This is a hash: # SSO::FromDiscourse.config = { # sso_url: 'https://talk.incommon.cc/session/sso_provider', - # return_url: "#{API_ROOT_URL}/my/account", + # return_url: 'https://incommon-map.example/authenticate', # sso_secret: Rails.application.credentials.sso_secret, # } # In config/routes.rb: # ... - # get 'my/account/:token' => 'authentications#sso_login' + # get 'authenticate/(:token)' => 'authentications#sso_login' attr_accessor :config end @@ -93,5 +93,15 @@ module SSO def mac_signature(payload = b64_payload) OpenSSL::HMAC.hexdigest('SHA256', self.class.config[:sso_secret], payload) end + + def sso_secret + @sso_secret = begin + self.class.config[:sso_secret].presence || + Rails.application.credentials.sso_secret || + raise + rescue MissingConstant + raise("Missing SSO Secret! Please set `SSO::FromDiscourse.config[:sso_secret]`") + end + end end end diff --git a/config/application.rb b/config/application.rb index 8752f57..c11c5ff 100644 --- a/config/application.rb +++ b/config/application.rb @@ -31,5 +31,6 @@ module IncommonMap # # config.time_zone = "Central Time (US & Canada)" # config.eager_load_paths << Rails.root.join("extras") + config.sso = config_for(:sso) end end diff --git a/config/database.yml b/config/database.yml index 16ba3d2..9c7344e 100644 --- a/config/database.yml +++ b/config/database.yml @@ -68,6 +68,12 @@ test: <<: *default database: incommon_map_test +staging: + <<: *default + database: incommon_map_staging + username: incommon + password: <%= ENV['INCOMMON_MAP_DATABASE_PASSWORD'] %> + # As with config/credentials.yml, you never want to store sensitive information, # like your database password, in your source code. If your source code is # ever seen by anyone, they now have access to your database. diff --git a/config/environments/development.rb b/config/environments/development.rb index 7a9f6c3..03f888f 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,5 +1,8 @@ require "active_support/core_ext/integer/time" +# During development, use localhost (careful with the port!) +Rails.application.default_url_options[:host] = "localhost:3000" + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. diff --git a/config/environments/staging.rb b/config/environments/staging.rb new file mode 100644 index 0000000..8602e0b --- /dev/null +++ b/config/environments/staging.rb @@ -0,0 +1,115 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # Code is not reloaded between requests. + config.cache_classes = true + + # Eager load code on boot. This eager loads most of Rails and + # your application in memory, allowing both threaded web servers + # and those relying on copy on write to perform better. + # Rake tasks automatically ignore this option for performance. + config.eager_load = true + + # Full error reports are disabled and caching is turned on. + config.consider_all_requests_local = false + config.action_controller.perform_caching = true + + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Compress CSS using a preprocessor. + # config.assets.css_compressor = :sass + + # Do not fallback to assets pipeline if a precompiled asset is missed. + config.assets.compile = false + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.asset_host = 'http://assets.example.com' + + # Specifies the header that your server uses for sending files. + # config.action_dispatch.x_sendfile_header = 'X-Sendfile' # for Apache + # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for NGINX + + # Store uploaded files on the local file system (see config/storage.yml for options). + config.active_storage.service = :local + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Include generic and useful information about system operation, but avoid logging too much + # information to avoid inadvertent exposure of personally identifiable information (PII). + config.log_level = :info + + # Prepend all log lines with the following tags. + config.log_tags = [ :request_id ] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment). + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "incommon_map_production" + + config.action_mailer.perform_caching = false + + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Enable locale fallbacks for I18n (makes lookups for any locale fall back to + # the I18n.default_locale when a translation cannot be found). + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify + + # Log disallowed deprecations. + config.active_support.disallowed_deprecation = :log + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Use a different logger for distributed setups. + # require "syslog/logger" + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false + + # Inserts middleware to perform automatic connection switching. + # The `database_selector` hash is used to pass options to the DatabaseSelector + # middleware. The `delay` is used to determine how long to wait after a write + # to send a subsequent read to the primary. + # + # The `database_resolver` class is used by the middleware to determine which + # database is appropriate to use based on the time delay. + # + # The `database_resolver_context` class is used by the middleware to set + # timestamps for the last write to the primary. The resolver uses the context + # class timestamps to determine how long to wait before reading from the + # replica. + # + # By default Rails will store a last write timestamp in the session. The + # DatabaseSelector middleware is designed as such you can define your own + # strategy for connection switching and pass that into the middleware through + # these configuration options. + # config.active_record.database_selector = { delay: 2.seconds } + # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver + # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session +end diff --git a/config/initializers/sso_config.rb b/config/initializers/sso_config.rb index cf3bf3f..bf32648 100644 --- a/config/initializers/sso_config.rb +++ b/config/initializers/sso_config.rb @@ -15,8 +15,5 @@ require 'sso/from_discourse' -SSO::FromDiscourse.config = { - sso_url: 'https://talk.incommon.cc/session/sso_provider', - return_url: Rails.env.production? ? "https://ateliers-carto.incommon.cc/authenticate" : "http://localhost:3000/authenticate", - sso_secret: Rails.application.credentials.sso_secret, -} + + diff --git a/config/routes.rb b/config/routes.rb index 54f383e..07c7616 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -34,6 +34,6 @@ Rails.application.routes.draw do get '/by-uuid/:uuid', to: 'uuid_resolver#new', as: 'uuid_resolver' # Discourse SSO - get 'authenticate(/:token)', to: 'welcome#authenticate' + get 'authenticate(/:token)', to: 'welcome#authenticate', as: 'authenticate' get 'logout', to: 'welcome#logout' end diff --git a/config/sso.yml b/config/sso.yml new file mode 100644 index 0000000..2a64738 --- /dev/null +++ b/config/sso.yml @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2018-2021 IN COMMON Collective +# +# SPDX-License-Identifier: AGPL-3.0-or-later + +# frozen_string_literal: true + +shared: + sso_url: 'https://talk.incommon.cc/session/sso_provider' + +production: + return_url: 'https://ateliers-carto.incommon.cc/authenticate' + +staging: + return_url: 'https://ateliers-carto-staging.incommon.cc/authenticate' + +development: + return_url: 'http://localhost:3000/authenticate' diff --git a/config/webpacker.yml b/config/webpacker.yml index a4b9a7a..5f6dbfd 100644 --- a/config/webpacker.yml +++ b/config/webpacker.yml @@ -83,6 +83,8 @@ test: # Compile test packs to a separate directory public_output_path: packs-test +staging: &production + production: <<: *default -- cgit v1.2.3 From 3c6561243b5f1abfad3292347c51aa1914f63b48 Mon Sep 17 00:00:00 2001 From: IN COMMON Collective Date: Fri, 9 Apr 2021 12:22:22 +0200 Subject: [DEV] Make SSO return_url dependent on Rails environment (fixes #1) Previously the return_url was hardcoded for all environments. It would create an issue where authentication outside of development would redirect to the wrong site. With the previous commit we introduced a staging environment and an environment-specific configuration file allowing to hardcode return_url for each environment. This commit fixes the proper capture of the SSO secret in the current configuration and introduces an SSO::MissingSecretError class that is raised when there's no configured secret. https://gitlab.com/incommon.cc/incommon-map/-/issues/1 --- app/lib/sso/from_discourse.rb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/app/lib/sso/from_discourse.rb b/app/lib/sso/from_discourse.rb index 8c5eea7..7af7173 100644 --- a/app/lib/sso/from_discourse.rb +++ b/app/lib/sso/from_discourse.rb @@ -5,6 +5,8 @@ # frozen_string_literal: true module SSO + class MissingSecretError < ArgumentError; end + class FromDiscourse attr_accessor :nonce, :token attr_reader :request_uri, :user_info, :status @@ -91,17 +93,18 @@ module SSO end def mac_signature(payload = b64_payload) - OpenSSL::HMAC.hexdigest('SHA256', self.class.config[:sso_secret], payload) + OpenSSL::HMAC.hexdigest('SHA256', sso_secret, payload) end def sso_secret @sso_secret = begin - self.class.config[:sso_secret].presence || - Rails.application.credentials.sso_secret || - raise + self.class.config[:sso_secret] || + Rails.application.credentials.sso_secret rescue MissingConstant - raise("Missing SSO Secret! Please set `SSO::FromDiscourse.config[:sso_secret]`") + nil end + raise SSO::MissingSecretError if @sso_secret.nil? + self.class.config[:sso_secret] ||= @sso_secret end end end -- cgit v1.2.3 From 4375650ea0788ae6b2a390b10ca6679d67dfc7a3 Mon Sep 17 00:00:00 2001 From: IN COMMON Collective Date: Fri, 9 Apr 2021 12:28:31 +0200 Subject: [DOC] Indicate when JavaScript is disabled. --- app/views/welcome/index.html.erb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb index ca0245a..b849e13 100644 --- a/app/views/welcome/index.html.erb +++ b/app/views/welcome/index.html.erb @@ -9,6 +9,14 @@

Cette application vous permet de visualiser les données recensées par le soin de nos Agents concernant les ressources partagées notamment sur le territoire Belge. Elle permet également l'édition de ces données afin de les maintenir toujours au plus près de la situation réelle et actuelle.

Si vous désirez rejoindre un Agent ou pourquoi pas en créer un, merci de consulter la Charte IN COMMON et, s'il vous plaît, de rejoindre la conversation.

+ + + <% content_for :aside do %>
-- cgit v1.2.3