From 35b069a4dbfa5f74db7af887d51473087fd94c52 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 1 Oct 2019 17:14:16 +0200 Subject: [PATCH 1/4] added gem omniauth-rails_csrf_protection + [ongoing] moving from GET /users/auth/... to POST --- Gemfile | 1 + Gemfile.lock | 4 ++++ app/assets/javascripts/controllers/application.js.erb | 1 + app/assets/javascripts/router.js.erb | 4 +++- app/assets/templates/shared/header.html.erb | 4 +++- app/views/users_mailer/notify_user_account_created.html.erb | 6 +++--- 6 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Gemfile b/Gemfile index 697e34052..1d55613ef 100644 --- a/Gemfile +++ b/Gemfile @@ -73,6 +73,7 @@ gem 'devise', ">= 4.6.0" gem 'omniauth', '~> 1.6.0' gem 'omniauth-oauth2' +gem 'omniauth-rails_csrf_protection', '~> 0.1' gem 'rolify' diff --git a/Gemfile.lock b/Gemfile.lock index 10cddb765..13f3c98ac 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -265,6 +265,9 @@ GEM omniauth-oauth2 (1.3.1) oauth2 (~> 1.0) omniauth (~> 1.2) + omniauth-rails_csrf_protection (0.1.2) + actionpack (>= 4.2) + omniauth (>= 1.3.1) openlab_ruby (0.0.4) httparty (~> 0.13) orm_adapter (0.5.0) @@ -511,6 +514,7 @@ DEPENDENCIES oj omniauth (~> 1.6.0) omniauth-oauth2 + omniauth-rails_csrf_protection (~> 0.1) openlab_ruby pdf-reader pg diff --git a/app/assets/javascripts/controllers/application.js.erb b/app/assets/javascripts/controllers/application.js.erb index c3bcadf2c..3bc0b452c 100644 --- a/app/assets/javascripts/controllers/application.js.erb +++ b/app/assets/javascripts/controllers/application.js.erb @@ -351,6 +351,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco var openLoginModal = function (toState, toParams, callback) { <% active_provider = AuthProvider.active %> <% if active_provider.providable_type != DatabaseProvider.name %> + $window.location.href = '<%="/users/auth/#{active_provider.strategy_name}"%>'; <% else %> return $uibModal.open({ diff --git a/app/assets/javascripts/router.js.erb b/app/assets/javascripts/router.js.erb index d9f8b1c7d..cfd27e274 100644 --- a/app/assets/javascripts/router.js.erb +++ b/app/assets/javascripts/router.js.erb @@ -38,7 +38,9 @@ angular.module('application.router', ['ui.router']) logoBlackFile: ['CustomAsset', function (CustomAsset) { return CustomAsset.get({ name: 'logo-black-file' }).$promise; }], commonTranslations: ['Translations', function (Translations) { return Translations.query(['app.public.common', 'app.shared.buttons', 'app.shared.elements']).$promise; }] }, - onEnter: ['$rootScope', 'logoFile', 'logoBlackFile', function ($rootScope, logoFile, logoBlackFile) { + onEnter: ['$rootScope', 'logoFile', 'logoBlackFile', 'CSRF', function ($rootScope, logoFile, logoBlackFile, CSRF) { + // Retrieve Anti-CSRF tokens from cookies + CSRF.setMetaTags(); // Application logo $rootScope.logo = logoFile.custom_asset; return $rootScope.logoBlack = logoBlackFile.custom_asset; diff --git a/app/assets/templates/shared/header.html.erb b/app/assets/templates/shared/header.html.erb index dbbd72be6..1c1b23575 100644 --- a/app/assets/templates/shared/header.html.erb +++ b/app/assets/templates/shared/header.html.erb @@ -55,7 +55,9 @@ <% else %>
  • " class="font-sbold label text-md"> {{ 'sign_up' | translate }}
  • - " class="font-sbold label text-md"> {{ 'sign_in' | translate }} + <%= link_to(raw(" {{ 'sign_in' | translate }}"), + "/users/auth/#{active_provider.strategy_name}", + { method: :post, class: 'font-sbold label text-md' }) %>
  • <% end %> diff --git a/app/views/users_mailer/notify_user_account_created.html.erb b/app/views/users_mailer/notify_user_account_created.html.erb index 1c3bfac6e..ed86379d1 100644 --- a/app/views/users_mailer/notify_user_account_created.html.erb +++ b/app/views/users_mailer/notify_user_account_created.html.erb @@ -38,9 +38,9 @@

    <%= t('.body.thanks_to_') %> - " target="_blank"> - <%= t('body.logon_or_login', PROVIDER: active_provider.name )%> - + <%= link_to(t('.body.logon_or_login', PROVIDER: active_provider.name ), + "#{root_url}/users/auth/#{active_provider.strategy_name}?auth_token=#{@user.auth_token}", + { method: :post, target: '_blank' }) %>

    <%= t('.body.token_if_link_problem') %>

    From 927479733bf589810dad697f2ccba2d0ea1bd4fb Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 2 Oct 2019 14:37:47 +0200 Subject: [PATCH 2/4] migrated links to /users/auth from GET to POST see https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284 for more info --- Gemfile | 4 ++- Gemfile.lock | 2 ++ .../controllers/application.js.erb | 8 ++++-- .../services/{auth.js => auth.js.erb} | 2 +- app/assets/templates/shared/header.html.erb | 18 +++--------- app/controllers/application_controller.rb | 6 ++++ app/controllers/sessions_controller.rb | 2 +- .../users/omniauth_callbacks_controller.rb | 2 +- app/mailers/notifications_mailer.rb | 19 +++++++++---- app/mailers/users_mailer.rb | 3 ++ .../api/auth_providers/active.json.jbuilder | 6 ++-- app/views/application/sso_redirect.html.erb | 21 ++++++++++++++ .../notify_user_auth_migration.html.erb | 7 +---- .../notify_user_account_created.html.erb | 10 ++++--- config/application.yml.default | 4 +-- config/environments/development.rb | 14 ++++++++-- config/environments/production.rb | 26 +++++++++++------ config/environments/staging.rb | 28 +++++++++++++------ config/environments/test.rb | 9 +++++- config/locales/mails.en.yml | 4 +-- config/locales/mails.es.yml | 4 +-- config/locales/mails.fr.yml | 4 +-- config/locales/mails.pt.yml | 4 +-- config/routes.rb | 1 + .../previews/notifications_mailer_preview.rb | 8 ++++++ test/mailers/previews/users_mailer_preview.rb | 7 +++++ 26 files changed, 153 insertions(+), 70 deletions(-) rename app/assets/javascripts/services/{auth.js => auth.js.erb} (81%) create mode 100644 app/views/application/sso_redirect.html.erb create mode 100644 test/mailers/previews/notifications_mailer_preview.rb create mode 100644 test/mailers/previews/users_mailer_preview.rb diff --git a/Gemfile b/Gemfile index 1d55613ef..109cc9cca 100644 --- a/Gemfile +++ b/Gemfile @@ -99,8 +99,8 @@ gem 'friendly_id', '~> 5.1.0' gem 'aasm' # Background job processing -gem 'sidekiq', '>= 3.4.2' gem 'redis-namespace' +gem 'sidekiq', '>= 3.4.2' gem 'sinatra', require: false # Recurring jobs for Sidekiq gem 'sidekiq-cron' @@ -150,3 +150,5 @@ gem 'rack-protection', '1.5.5' gem 'sys-filesystem' gem 'sha3' + +gem 'repost' diff --git a/Gemfile.lock b/Gemfile.lock index 13f3c98ac..18b226ff5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -345,6 +345,7 @@ GEM redis-namespace (1.6.0) redis (>= 3.0.4) ref (2.0.0) + repost (0.2.9) responders (2.1.0) railties (>= 4.2.0, < 5) rolify (4.0.0) @@ -531,6 +532,7 @@ DEPENDENCIES rb-readline recurrence redis-namespace + repost responders (~> 2.0) rolify rubocop (~> 0.61.1) diff --git a/app/assets/javascripts/controllers/application.js.erb b/app/assets/javascripts/controllers/application.js.erb index 3bc0b452c..f048af8dd 100644 --- a/app/assets/javascripts/controllers/application.js.erb +++ b/app/assets/javascripts/controllers/application.js.erb @@ -82,6 +82,10 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco */ $scope.signup = function (e) { if (e) { e.preventDefault(); } + <% active_provider = AuthProvider.active %> + <% if active_provider.providable_type != DatabaseProvider.name %> + $window.location.href = '/sso-redirect'; + <% else %> return $uibModal.open({ templateUrl: '<%= asset_path "shared/signupModal.html" %>', @@ -167,6 +171,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco // when the account was created successfully, set the session to the newly created account $scope.setCurrentUser(user); }); + <% end %> }; /** @@ -351,8 +356,7 @@ Application.Controllers.controller('ApplicationController', ['$rootScope', '$sco var openLoginModal = function (toState, toParams, callback) { <% active_provider = AuthProvider.active %> <% if active_provider.providable_type != DatabaseProvider.name %> - - $window.location.href = '<%="/users/auth/#{active_provider.strategy_name}"%>'; + $window.location.href = '/sso-redirect'; <% else %> return $uibModal.open({ templateUrl: '<%= asset_path "shared/deviseModal.html" %>', diff --git a/app/assets/javascripts/services/auth.js b/app/assets/javascripts/services/auth.js.erb similarity index 81% rename from app/assets/javascripts/services/auth.js rename to app/assets/javascripts/services/auth.js.erb index 6eee18588..041082753 100644 --- a/app/assets/javascripts/services/auth.js +++ b/app/assets/javascripts/services/auth.js.erb @@ -1,6 +1,6 @@ 'use strict'; -Application.Services.factory('AuthService', ['Session', function (Session) { +Application.Services.factory('AuthService', ['Session', 'CSRF', function (Session, CSRF) { return { isAuthenticated () { return (Session.currentUser != null) && (Session.currentUser.id != null); diff --git a/app/assets/templates/shared/header.html.erb b/app/assets/templates/shared/header.html.erb index 1c1b23575..56a480048 100644 --- a/app/assets/templates/shared/header.html.erb +++ b/app/assets/templates/shared/header.html.erb @@ -46,18 +46,8 @@
  • {{ 'sign_out' | translate }}
  • - <% active_provider = AuthProvider.active %> - <% if active_provider.providable_type == DatabaseProvider.name %> -
  • {{ 'sign_up' | translate }}
  • -
  • - {{ 'sign_in' | translate }} -
  • - <% else %> -
  • " class="font-sbold label text-md"> {{ 'sign_up' | translate }}
  • -
  • - <%= link_to(raw(" {{ 'sign_in' | translate }}"), - "/users/auth/#{active_provider.strategy_name}", - { method: :post, class: 'font-sbold label text-md' }) %> -
  • - <% end %> +
  • {{ 'sign_up' | translate }}
  • +
  • + {{ 'sign_in' | translate }} +
  • diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 82bfcd3b8..1beb5c21e 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -19,6 +19,12 @@ class ApplicationController < ActionController::Base def index; end + def sso_redirect + @authorization_token = request.query_parameters[:auth_token] + @authentication_token = form_authenticity_token + @active_provider = AuthProvider.active + end + protected def set_csrf_cookie diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb index b3489560f..05a2eb171 100644 --- a/app/controllers/sessions_controller.rb +++ b/app/controllers/sessions_controller.rb @@ -6,7 +6,7 @@ class SessionsController < Devise::SessionsController def new active_provider = AuthProvider.active if active_provider.providable_type != DatabaseProvider.name - redirect_to "/users/auth/#{active_provider.strategy_name}" + redirect_post "/users/auth/#{active_provider.strategy_name}", params: { authenticity_token: form_authenticity_token } else super end diff --git a/app/controllers/users/omniauth_callbacks_controller.rb b/app/controllers/users/omniauth_callbacks_controller.rb index 9853b857b..f0a9ba7a5 100644 --- a/app/controllers/users/omniauth_callbacks_controller.rb +++ b/app/controllers/users/omniauth_callbacks_controller.rb @@ -17,7 +17,7 @@ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController # unique random string, because: # - if it is the same user, his email will be filled from the SSO when he merge his accounts # - if it is not the same user, this will prevent the raise of PG::UniqueViolation - if active_provider.sso_fields.include?('user.email') and email_exists?(@user.email) + if active_provider.sso_fields.include?('user.email') && email_exists?(@user.email) old_mail = @user.email @user.email = "<#{old_mail}>#{Devise.friendly_token}-duplicate" flash[:alert] = t('omniauth.email_already_linked_to_another_account_please_input_your_authentication_code', OLD_MAIL: old_mail) diff --git a/app/mailers/notifications_mailer.rb b/app/mailers/notifications_mailer.rb index f30a17535..8ec5f7a89 100644 --- a/app/mailers/notifications_mailer.rb +++ b/app/mailers/notifications_mailer.rb @@ -1,5 +1,8 @@ +# frozen_string_literal: true + +# Handle most of the emails sent by the platform. Triggered by notifications class NotificationsMailer < NotifyWith::NotificationsMailer - default :from => ENV['DEFAULT_MAIL_FROM'] + default from: ENV['DEFAULT_MAIL_FROM'] layout 'notifications_mailer' helper :application @@ -9,15 +12,15 @@ class NotificationsMailer < NotifyWith::NotificationsMailer @recipient = notification.receiver @attached_object = notification.attached_object - if !respond_to?(notification.notification_type) - class_eval %Q{ + unless respond_to?(notification.notification_type) + class_eval %{ def #{notification.notification_type} mail to: @recipient.email, subject: t('notifications_mailer.#{notification.notification_type}.subject'), template_name: '#{notification.notification_type}', content_type: 'text/html' end - } + }, __FILE__, __LINE__ - 7 end send(notification.notification_type) @@ -29,11 +32,15 @@ class NotificationsMailer < NotifyWith::NotificationsMailer def notify_user_when_invoice_ready attachments[@attached_object.filename] = File.read(@attached_object.file) - mail(to: @recipient.email, subject: t('notifications_mailer.notify_member_invoice_ready.subject'), template_name: 'notify_member_invoice_ready') + mail(to: @recipient.email, + subject: t('notifications_mailer.notify_member_invoice_ready.subject'), + template_name: 'notify_member_invoice_ready') end def notify_user_when_avoir_ready attachments[@attached_object.filename] = File.read(@attached_object.file) - mail(to: @recipient.email, subject: t('notifications_mailer.notify_member_avoir_ready.subject'), template_name: 'notify_member_avoir_ready') + mail(to: @recipient.email, + subject: t('notifications_mailer.notify_member_avoir_ready.subject'), + template_name: 'notify_member_avoir_ready') end end diff --git a/app/mailers/users_mailer.rb b/app/mailers/users_mailer.rb index 1c38e2fc0..bb1fdb1ab 100644 --- a/app/mailers/users_mailer.rb +++ b/app/mailers/users_mailer.rb @@ -1,3 +1,6 @@ +# frozen_string_literal: true + +# Handle emails related to users accounts, at Devise level class UsersMailer < BaseMailer def notify_user_account_created(user, generated_password) @user = user diff --git a/app/views/api/auth_providers/active.json.jbuilder b/app/views/api/auth_providers/active.json.jbuilder index 1f35ece38..c9bade12f 100644 --- a/app/views/api/auth_providers/active.json.jbuilder +++ b/app/views/api/auth_providers/active.json.jbuilder @@ -4,9 +4,7 @@ json.link_to_sso_profile @provider.link_to_sso_profile if @provider.providable_type == DatabaseProvider.name json.link_to_sso_connect '/#' else - json.link_to_sso_connect "/users/auth/#{@provider.strategy_name}" + json.link_to_sso_connect '/sso-redirect' end -if @provider.providable_type == OAuth2Provider.name - json.domain @provider.providable.domain -end +json.domain @provider.providable.domain if @provider.providable_type == OAuth2Provider.name diff --git a/app/views/application/sso_redirect.html.erb b/app/views/application/sso_redirect.html.erb new file mode 100644 index 000000000..1d57b5c15 --- /dev/null +++ b/app/views/application/sso_redirect.html.erb @@ -0,0 +1,21 @@ + + + + + + Redirect to SSO + + + <% param = @authorization_token ? "?auth_token=#{@authorization_token}" : '' %> + <% url_path = File.join(root_url, "users/auth/#{@active_provider.strategy_name}#{param}") %> +
    + <%= hidden_field_tag :authenticity_token, @authentication_token %> + +
    + + + diff --git a/app/views/notifications_mailer/notify_user_auth_migration.html.erb b/app/views/notifications_mailer/notify_user_auth_migration.html.erb index d72a262e5..5cdca27f5 100644 --- a/app/views/notifications_mailer/notify_user_auth_migration.html.erb +++ b/app/views/notifications_mailer/notify_user_auth_migration.html.erb @@ -15,12 +15,7 @@ <% active_provider = AuthProvider.active %> <%= render 'notifications_mailer/shared/hello', recipient: @recipient %> <% - url_path = "/users/auth/#{active_provider.strategy_name}" - if url_path[0] == '/' and root_url[-1] == '/' - url_path = root_url + url_path[1..-1] - else - url_path = root_url + url_path - end + url_path = File.join(root_url, 'sso-redirect') %>

    <%= t(".body.the_platform") %> <%= Setting.find_by(name: 'fablab_name').value %> <%= t(".body.is_changing_its_auth_system_and_will_now_use") %> <%= active_provider.name %> <%= t(".body.instead_of") %> <%= AuthProvider.find_by(status: 'previous').name %>.

    diff --git a/app/views/users_mailer/notify_user_account_created.html.erb b/app/views/users_mailer/notify_user_account_created.html.erb index ed86379d1..d5f095603 100644 --- a/app/views/users_mailer/notify_user_account_created.html.erb +++ b/app/views/users_mailer/notify_user_account_created.html.erb @@ -36,11 +36,13 @@ <% else %> + <% url_path = File.join(root_url, 'sso-redirect') %> +

    - <%= t('.body.thanks_to_') %> - <%= link_to(t('.body.logon_or_login', PROVIDER: active_provider.name ), - "#{root_url}/users/auth/#{active_provider.strategy_name}?auth_token=#{@user.auth_token}", - { method: :post, target: '_blank' }) %> + <%= t('.body.to_use_platform') %> + " target="_blank"> + <%= t('.body.logon_or_login', PROVIDER: active_provider.name )%> +

    <%= t('.body.token_if_link_problem') %>

    diff --git a/config/application.yml.default b/config/application.yml.default index aad654cf9..b44a9b949 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -19,8 +19,8 @@ FABLAB_WITHOUT_INVOICES: 'false' DEFAULT_MAIL_FROM: Fab Manager Demo # For prod & staging env only -DEFAULT_HOST: fab-manager.com -DEFAULT_PROTOCOL: https +DEFAULT_HOST: 'localhost:5000' +DEFAULT_PROTOCOL: http DELIVERY_METHOD: smtp SMTP_ADDRESS: SMTP_PORT: '587' diff --git a/config/environments/development.rb b/config/environments/development.rb index 79305c1b6..0d041cbfb 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -13,6 +15,11 @@ Rails.application.configure do config.consider_all_requests_local = true config.action_controller.perform_caching = true + config.action_controller.default_url_options = { + host: Rails.application.secrets.default_host, + protocol: Rails.application.secrets.default_protocol + } + # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false @@ -41,9 +48,12 @@ Rails.application.configure do # config.action_view.raise_on_missing_translations = true config.action_mailer.delivery_method = :smtp - config.action_mailer.smtp_settings = { :address => '127.0.0.1', :port => 1025 } + config.action_mailer.smtp_settings = { address: '127.0.0.1', port: 1025 } config.action_mailer.raise_delivery_errors = false - config.action_mailer.default_url_options = { :host => 'localhost:5000' } + config.action_mailer.default_url_options = { + host: Rails.application.secrets.default_host, + protocol: Rails.application.secrets.default_protocol + } config.log_level = Rails.application.secrets.log_level || :debug end diff --git a/config/environments/production.rb b/config/environments/production.rb index 50161662a..46ccc5963 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -14,6 +16,11 @@ Rails.application.configure do config.consider_all_requests_local = false config.action_controller.perform_caching = true + config.action_controller.default_url_options = { + host: Rails.application.secrets.default_host, + protocol: Rails.application.secrets.default_protocol + } + # Enable Rack::Cache to put a simple HTTP cache in front of your application # Add `rack-cache` to your Gemfile before enabling this. # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid. @@ -81,19 +88,22 @@ Rails.application.configure do # config.serve_static_assets = true - config.action_mailer.default_url_options = { :host => Rails.application.secrets.default_host, :protocol => Rails.application.secrets.default_protocol } + config.action_mailer.default_url_options = { + host: Rails.application.secrets.default_host, + protocol: Rails.application.secrets.default_protocol + } # config.action_mailer.perform_deliveries = true # config.action_mailer.raise_delivery_errors = false # config.action_mailer.default :charset => "utf-8" config.action_mailer.smtp_settings = { - :address => Rails.application.secrets.smtp_address, - :port => Rails.application.secrets.smtp_port, - :user_name => Rails.application.secrets.smtp_user_name, - :password => Rails.application.secrets.smtp_password, - :authentication => Rails.application.secrets.smtp_authentication, - :enable_starttls_auto => Rails.application.secrets.smtp_enable_starttls_auto, - :openssl_verify_mode => Rails.application.secrets.smtp_openssl_verify_mode, + address: Rails.application.secrets.smtp_address, + port: Rails.application.secrets.smtp_port, + user_name: Rails.application.secrets.smtp_user_name, + password: Rails.application.secrets.smtp_password, + authentication: Rails.application.secrets.smtp_authentication, + enable_starttls_auto: Rails.application.secrets.smtp_enable_starttls_auto, + openssl_verify_mode: Rails.application.secrets.smtp_openssl_verify_mode, } # use :smtp for switch prod diff --git a/config/environments/staging.rb b/config/environments/staging.rb index 28f695ebc..dea7214d9 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -14,6 +16,11 @@ Rails.application.configure do config.consider_all_requests_local = false config.action_controller.perform_caching = true + config.action_controller.default_url_options = { + host: Rails.application.secrets.default_host, + protocol: Rails.application.secrets.default_protocol + } + # Enable Rack::Cache to put a simple HTTP cache in front of your application # Add `rack-cache` to your Gemfile before enabling this. # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid. @@ -83,20 +90,23 @@ Rails.application.configure do # config.serve_static_assets = true - config.action_mailer.default_url_options = { :host => Rails.application.secrets.default_host, :protocol => Rails.application.secrets.default_protocol } + config.action_mailer.default_url_options = { + host: Rails.application.secrets.default_host, + protocol: Rails.application.secrets.default_protocol + } # config.action_mailer.perform_deliveries = true # config.action_mailer.raise_delivery_errors = false # config.action_mailer.default :charset => "utf-8" config.action_mailer.smtp_settings = { - :address => Rails.application.secrets.smtp_address, - :port => Rails.application.secrets.smtp_port, - :user_name => Rails.application.secrets.smtp_user_name, - :password => Rails.application.secrets.smtp_password, - :authentication => Rails.application.secrets.smtp_authentication, - :enable_starttls_auto => Rails.application.secrets.smtp_enable_starttls_auto, - :openssl_verify_mode => Rails.application.secrets.smtp_openssl_verify_mode, - } + address: Rails.application.secrets.smtp_address, + port: Rails.application.secrets.smtp_port, + user_name: Rails.application.secrets.smtp_user_name, + password: Rails.application.secrets.smtp_password, + authentication: Rails.application.secrets.smtp_authentication, + enable_starttls_auto: Rails.application.secrets.smtp_enable_starttls_auto, + openssl_verify_mode: Rails.application.secrets.smtp_openssl_verify_mode, + } # use :smtp for switch prod config.action_mailer.delivery_method = Rails.application.secrets.delivery_method.to_sym diff --git a/config/environments/test.rb b/config/environments/test.rb index 23135c381..b8e1a562c 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. @@ -13,13 +15,18 @@ Rails.application.configure do config.eager_load = false # Configure static asset server for tests with Cache-Control for performance. - config.serve_static_files = true + config.serve_static_files = true config.static_cache_control = 'public, max-age=3600' # Show full error reports and disable caching. config.consider_all_requests_local = true config.action_controller.perform_caching = false + config.action_controller.default_url_options = { + host: Rails.application.secrets.default_host, + protocol: Rails.application.secrets.default_protocol + } + # Raise exceptions instead of rendering exception templates. config.action_dispatch.show_exceptions = false diff --git a/config/locales/mails.en.yml b/config/locales/mails.en.yml index 46e2c8b19..9aea143be 100644 --- a/config/locales/mails.en.yml +++ b/config/locales/mails.en.yml @@ -17,8 +17,8 @@ en: password: "Password:" temporary_password: "This is a temporary password, you can modify it in your «My account» screen." keep_advantages: "With this account, you keep all the advantages linked to your Fab Lab user profile (trainings, subscriptions plans)." - thanks_to_: "To use the website, please" - logon_or_login: "create a new account or log in by clicking here" + to_use_platform: "To use the website, please" + logon_or_login: "create a new account or log in by clicking here." token_if_link_problem: "If you experience issues with the link, you can enter the following code at your first connection attempt:" notifications_mailer: diff --git a/config/locales/mails.es.yml b/config/locales/mails.es.yml index a3f2c65df..98c80b22a 100644 --- a/config/locales/mails.es.yml +++ b/config/locales/mails.es.yml @@ -17,8 +17,8 @@ es: password: "Contraseña:" temporary_password: "Esta es una contraseña temporal, puede modificarla en la pantalla <>." keep_advantages: "Con esta cuenta, guarda todas las ventajas relacionadas con su perfil de usuario de Fab Lab (cursos, planes de suscripción)." - thanks_to_: "Para usar el sitio web, por favor" - logon_or_login: "crea una nueva cuenta o inicia sesión haciendo clic aquí" + to_use_platform: "Para usar el sitio web, por favor" + logon_or_login: "crea una nueva cuenta o inicia sesión haciendo clic aquí." token_if_link_problem: "Si experimenta problemas con el enlace, puede introducir el siguiente código en el primer intento de conexión:" notifications_mailer: diff --git a/config/locales/mails.fr.yml b/config/locales/mails.fr.yml index ef1f65d31..b70eaa751 100644 --- a/config/locales/mails.fr.yml +++ b/config/locales/mails.fr.yml @@ -17,8 +17,8 @@ fr: password: "Mot de passe :" temporary_password: "Ce mot de passe est temporaire, vous pourrez le modifier en accédant à l’espace « Mon compte »." keep_advantages: "Avec ce compte, vous conservez bien entendu tous les avantages liés à votre profil utilisateur Fab Lab (abonnement, formations)." - thanks_to_: "Pour pouvoir utiliser la plateforme, merci de vous" - logon_or_login: "créer un compte sur %{PROVIDER} ou utiliser un compte pré-existant en cliquant ici" + to_use_platform: "Pour pouvoir utiliser la plateforme, merci de vous" + logon_or_login: "créer un compte sur %{PROVIDER} ou utiliser un compte pré-existant en cliquant ici." token_if_link_problem: "En cas de problème avec le lien, vous pourrez saisir manuellement le code suivant lors de votre première connexion :" notifications_mailer: diff --git a/config/locales/mails.pt.yml b/config/locales/mails.pt.yml index 25359a37a..20db2994f 100755 --- a/config/locales/mails.pt.yml +++ b/config/locales/mails.pt.yml @@ -17,8 +17,8 @@ pt: password: "Senha:" temporary_password: "Essa é uma senha temporária, você pode modificar isso na página «Minha conta»." keep_advantages: "Com esta conta, você mantém todas as vantagens associadas ao seu perfil de usuário Fab Lab (treinamentos, planos de assinaturas)." - thanks_to_: "Para usar o site, por favor" - logon_or_login: "Criar uma nova conta ou fazer login clicando aqui" + to_use_platform: "Para usar o site, por favor" + logon_or_login: "criar uma nova conta ou fazer login clicando aqui." token_if_link_problem: "Se você tiver problemas com o link, você poderá inserir o código a seguir na primeira tentativa de conexão:" notifications_mailer: diff --git a/config/routes.rb b/config/routes.rb index 628586dfd..0609afaeb 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -15,6 +15,7 @@ Rails.application.routes.draw do registrations: 'registrations', sessions: 'sessions', confirmations: 'confirmations', passwords: 'passwords', omniauth_callbacks: 'users/omniauth_callbacks' } + get '/sso-redirect', to: 'application#sso_redirect', as: :sso_redirect end diff --git a/test/mailers/previews/notifications_mailer_preview.rb b/test/mailers/previews/notifications_mailer_preview.rb new file mode 100644 index 000000000..0831b8a47 --- /dev/null +++ b/test/mailers/previews/notifications_mailer_preview.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +class NotificationsMailerPreview < ActionMailer::Preview + def notify_user_auth_migration + notif = Notification.where(notification_type_id: NotificationType.find_by_name('notify_user_auth_migration')).first + NotificationsMailer.send_mail_by(notif) + end +end diff --git a/test/mailers/previews/users_mailer_preview.rb b/test/mailers/previews/users_mailer_preview.rb new file mode 100644 index 000000000..8bf6b700e --- /dev/null +++ b/test/mailers/previews/users_mailer_preview.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +class UsersMailerPreview < ActionMailer::Preview + def notify_user_account_created + UsersMailer.notify_user_account_created(User.first, 'test') + end +end From 5fcf9968cb46b677ebf6b137cad6e6b5c51db4df Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 2 Oct 2019 16:06:27 +0200 Subject: [PATCH 3/4] Updated Omniauth & Omniauth-oauth2 + fixed oauth2 callback url --- Gemfile | 4 +-- Gemfile.lock | 30 +++++++++---------- app/controllers/rss/events_controller.rb | 7 +++-- config/application.yml.default | 21 +++++++++++-- config/initializers/devise.rb | 6 ++-- .../strategies/sso_oauth2_provider.rb | 4 +++ 6 files changed, 49 insertions(+), 23 deletions(-) diff --git a/Gemfile b/Gemfile index 109cc9cca..6c9307d87 100644 --- a/Gemfile +++ b/Gemfile @@ -69,9 +69,9 @@ gem 'seed_dump' gem 'pg' -gem 'devise', ">= 4.6.0" +gem 'devise', '>= 4.6.0' -gem 'omniauth', '~> 1.6.0' +gem 'omniauth', '~> 1.9.0' gem 'omniauth-oauth2' gem 'omniauth-rails_csrf_protection', '~> 0.1' diff --git a/Gemfile.lock b/Gemfile.lock index 18b226ff5..13398dd74 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -159,7 +159,7 @@ GEM execjs (2.7.0) faker (1.4.3) i18n (~> 0.5) - faraday (0.9.2) + faraday (0.16.2) multipart-post (>= 1.2, < 3) ffi (1.9.24) figaro (1.1.0) @@ -180,7 +180,7 @@ GEM activerecord (>= 3.0) hashdiff (0.3.0) hashery (2.1.2) - hashie (3.5.7) + hashie (3.6.0) hike (1.2.3) htmlentities (4.3.4) http (3.0.0) @@ -209,7 +209,7 @@ GEM railties (>= 4.2.0) thor (>= 0.14, < 2.0) json (1.8.6) - jwt (1.5.1) + jwt (2.2.1) kaminari (0.16.3) actionpack (>= 3.0.0) activesupport (>= 3.0.0) @@ -243,8 +243,8 @@ GEM minitest (>= 5.0) ruby-progressbar multi_json (1.13.1) - multi_xml (0.5.5) - multipart-post (2.0.0) + multi_xml (0.6.0) + multipart-post (2.1.1) naught (1.1.0) nokogiri (1.10.4) mini_portile2 (~> 2.4.0) @@ -252,19 +252,19 @@ GEM jbuilder (~> 2.0) rails (>= 4.2.0) responders (~> 2.0) - oauth2 (1.0.0) - faraday (>= 0.8, < 0.10) - jwt (~> 1.0) + oauth2 (1.4.2) + faraday (>= 0.8, < 2.0) + jwt (>= 1.0, < 3.0) multi_json (~> 1.3) multi_xml (~> 0.5) - rack (~> 1.2) + rack (>= 1.2, < 3) oj (2.12.8) - omniauth (1.6.1) - hashie (>= 3.4.6, < 3.6.0) + omniauth (1.9.0) + hashie (>= 3.4.6, < 3.7.0) rack (>= 1.6.2, < 3) - omniauth-oauth2 (1.3.1) - oauth2 (~> 1.0) - omniauth (~> 1.2) + omniauth-oauth2 (1.6.0) + oauth2 (~> 1.1) + omniauth (~> 1.9) omniauth-rails_csrf_protection (0.1.2) actionpack (>= 4.2) omniauth (>= 1.3.1) @@ -513,7 +513,7 @@ DEPENDENCIES minitest-reporters notify_with oj - omniauth (~> 1.6.0) + omniauth (~> 1.9.0) omniauth-oauth2 omniauth-rails_csrf_protection (~> 0.1) openlab_ruby diff --git a/app/controllers/rss/events_controller.rb b/app/controllers/rss/events_controller.rb index 735a707ec..2b6351ef5 100644 --- a/app/controllers/rss/events_controller.rb +++ b/app/controllers/rss/events_controller.rb @@ -1,9 +1,12 @@ +# frozen_string_literal: true + +# RSS feed about 10 last events class Rss::EventsController < Rss::RssController def index @events = Event.includes(:event_image, :event_files, :availability, :category) - .where('availabilities.start_at >= ?', Time.now) - .order('availabilities.start_at ASC').references(:availabilities).limit(10) + .where('availabilities.start_at >= ?', Time.now) + .order('availabilities.start_at ASC').references(:availabilities).limit(10) @fab_name = Setting.find_by(name: 'fablab_name').value end end diff --git a/config/application.yml.default b/config/application.yml.default index b44a9b949..b8822ecd6 100644 --- a/config/application.yml.default +++ b/config/application.yml.default @@ -1,16 +1,21 @@ # Add application configuration variables here, as shown below. +# Databases POSTGRES_HOST: localhost POSTGRES_PASSWORD: REDIS_HOST: localhost ELASTICSEARCH_HOST: localhost +# Stripe SECRET_KEY_BASE: 83daf5e7b80d990f037407bab78dff9904aaf3c195a50f84fa8695a22287e707dfbd9524b403b1dcf116ae1d8c06844c3d7ed942564e5b46be6ae3ead93a9d30 STRIPE_API_KEY: STRIPE_PUBLISHABLE_KEY: STRIPE_CURRENCY: 'eur' +# Invoices INVOICE_PREFIX: Demo-FabLab-facture + +# FabLab optional modules FABLAB_WITHOUT_PLANS: 'false' FABLAB_WITHOUT_SPACES: 'true' FABLAB_WITHOUT_ONLINE_PAYMENT: 'false' @@ -18,9 +23,11 @@ FABLAB_WITHOUT_INVOICES: 'false' DEFAULT_MAIL_FROM: Fab Manager Demo -# For prod & staging env only +# Configure carefully! DEFAULT_HOST: 'localhost:5000' DEFAULT_PROTOCOL: http + +# Email config DELIVERY_METHOD: smtp SMTP_ADDRESS: SMTP_PORT: '587' @@ -29,21 +36,28 @@ SMTP_PASSWORD: SMTP_AUTHENTICATION: 'plain' SMTP_ENABLE_STARTTLS_AUTO: 'true' SMTP_OPENSSL_VERIFY_MODE: '' + +# Google analytics GA_ID: '' + +# Google recaptcha RECAPTCHA_SITE_KEY: '' RECAPTCHA_SECRET_KEY: '' -## +# Projects comments DISQUS_SHORTNAME: +# Twitter sharing & last tweet on home page TWITTER_NAME: 'FablabGrenoble' TWITTER_CONSUMER_KEY: '' TWITTER_CONSUMER_SECRET: '' TWITTER_ACCESS_TOKEN: '' TWITTER_ACCESS_TOKEN_SECRET: '' +# Facebook sharing FACEBOOK_APP_ID: '' +# I18N configuration RAILS_LOCALE: 'fr' APP_LOCALE: 'fr' MOMENT_LOCALE: 'fr' @@ -60,10 +74,13 @@ D3_DATE_FORMAT: '%d/%m/%y' UIB_DATE_FORMAT: 'dd/MM/yyyy' EXCEL_DATE_FORMAT: 'dd/mm/yyyy' +# OpenProjects OPENLAB_APP_SECRET: OPENLAB_APP_ID: +# do not change this URL OPENLAB_BASE_URI: 'https://openprojects.fab-manager.com' +# System settings LOG_LEVEL: 'debug' DISK_SPACE_MB_ALERT: '100' SUPERADMIN_EMAIL: 'admin@sleede.com' diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb index 1e82761d9..f78e2e1ba 100644 --- a/config/initializers/devise.rb +++ b/config/initializers/devise.rb @@ -1,3 +1,5 @@ +# frozen_string_literal: true + # Use this hook to configure devise mailer, warden hooks and so forth. # Many of these configuration options can be set straight in your model. Devise.setup do |config| @@ -43,12 +45,12 @@ Devise.setup do |config| # Configure which authentication keys should be case-insensitive. # These keys will be downcased upon creating or modifying a user and when used # to authenticate or find a user. Default is :email. - config.case_insensitive_keys = [ :email ] + config.case_insensitive_keys = [:email] # Configure which authentication keys should have whitespace stripped. # These keys will have whitespace before and after removed upon creating or # modifying a user and when used to authenticate or find a user. Default is :email. - config.strip_whitespace_keys = [ :email ] + config.strip_whitespace_keys = [:email] # Tell if authentication through request.params is enabled. True by default. # It can be set to an array that will enable params authentication only for the diff --git a/lib/omni_auth/strategies/sso_oauth2_provider.rb b/lib/omni_auth/strategies/sso_oauth2_provider.rb index f3ae87d76..80a45d3d3 100644 --- a/lib/omni_auth/strategies/sso_oauth2_provider.rb +++ b/lib/omni_auth/strategies/sso_oauth2_provider.rb @@ -24,6 +24,10 @@ module OmniAuth::Strategies authorize_url: active_provider.providable.authorization_endpoint, token_url: active_provider.providable.token_endpoint + def callback_url + url = Rails.application.config.action_controller.default_url_options + "#{url[:protocol]}://#{url[:host]}#{script_name}#{callback_path}" + end uid { parsed_info['user.uid'.to_sym] } From 31d7a39f49d5088979be3b490284ca2599f2cd65 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Wed, 2 Oct 2019 16:08:25 +0200 Subject: [PATCH 4/4] updated changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d12a1106c..69b563397 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Ability to configure and export the accounting data to the ACD accounting software - Compute the VAT per item in each invoices, instead of globally - Use Alpine Linux to build the Docker image (#147) +- Updated omniauth & omniauth-oauth2 gems - Ability to set project's CAO attachement maximum upload size - Ability to bulk-import members from a CSV file - Ability to disable invoices generation and interfaces @@ -12,6 +13,7 @@ - Fix a bug: in case of unexpected server error during stripe payment process, the confirm button is not unlocked - Fix a bug: create a plan does not set its name - Fix a bug: unable to dissociate the last machine from a formation +- Fix a security issue: fixed [CVE-2015-9284](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-9284) - [TODO DEPLOY] `rake db:migrate` - [TODO DEPLOY] -> (only dev) `yarn install` and `bundle install` - [TODO DEPLOY] add the `RECAPTCHA_SITE_KEY` and `RECAPTCHA_SECRET_KEY` environment variables (see [doc/environment.md](doc/environment.md) for configuration details)