Skip to content

Commit

Permalink
[WIP] Omniauth SAML strategy for IMT
Browse files Browse the repository at this point in the history
  • Loading branch information
moustachu committed Apr 23, 2024
1 parent 5766d21 commit 188c1eb
Show file tree
Hide file tree
Showing 7 changed files with 103 additions and 0 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ gem "decidim-term_customizer", git: "https://github.com/OpenSourcePolitics/decid
# Omniauth gems
gem "omniauth-france_connect", git: "https://github.com/OpenSourcePolitics/omniauth-france_connect"
gem "omniauth-publik", git: "https://github.com/OpenSourcePolitics/omniauth-publik"
gem "omniauth-saml"

# Default
gem "activejob-uniqueness", require: "active_job/uniqueness/sidekiq_patch"
Expand Down
9 changes: 9 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,8 @@ GEM
nio4r (2.7.0)
nokogiri (1.13.4-arm64-darwin)
racc (~> 1.4)
nokogiri (1.13.4-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.13.4-x86_64-linux)
racc (~> 1.4)
oauth (1.1.0)
Expand Down Expand Up @@ -756,6 +758,9 @@ GEM
omniauth-rails_csrf_protection (1.0.1)
actionpack (>= 4.2)
omniauth (~> 2.0)
omniauth-saml (2.1.0)
omniauth (~> 2.0)
ruby-saml (~> 1.12)
omniauth-twitter (1.4.0)
omniauth-oauth (~> 1.1)
rack
Expand Down Expand Up @@ -933,6 +938,9 @@ GEM
rubocop-rspec (2.11.1)
rubocop (~> 1.19)
ruby-progressbar (1.13.0)
ruby-saml (1.14.0)
nokogiri (>= 1.10.5)
rexml
ruby-vips (2.2.1)
ffi (~> 1.12)
rubyXL (3.4.25)
Expand Down Expand Up @@ -1128,6 +1136,7 @@ DEPENDENCIES
omniauth-france_connect!
omniauth-publik!
omniauth-rails_csrf_protection (~> 1.0)
omniauth-saml
parallel_tests
puma (>= 5.5.1)
rack-attack (~> 6.6)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# frozen_string_literal: true

module Decidim
module Devise
class CustomOmniauthRegistrationsController < ::Decidim::Devise::OmniauthRegistrationsController
# rubocop:disable Rails/LexicallyScopedActionFilter
skip_before_action :verify_authenticity_token, only: [:imt]
skip_after_action :verify_same_origin_request, only: [:imt]
# rubocop:enable Rails/LexicallyScopedActionFilter
end
end
end
38 changes: 38 additions & 0 deletions config/initializers/omniauth_saml.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# frozen_string_literal: true

require "omniauth/strategies/imt"

if Rails.application.secrets.dig(:omniauth, :imt).present?
Rails.application.config.middleware.use OmniAuth::Builder do
OmniAuth.config.logger = Rails.logger
provider(
OmniAuth::Strategies::IMT,
setup: lambda { |env|
request = Rack::Request.new(env)
organization = Decidim::Organization.find_by(host: request.host)
provider_config = organization.enabled_omniauth_providers[:imt]
env["omniauth.strategy"].options[:issuer] = provider_config[:issuer]
env["omniauth.strategy"].options[:assertion_consumer_service_url] = provider_config[:assertion_consumer_service_url]
env["omniauth.strategy"].options[:sp_entity_id] = provider_config[:sp_entity_id]
env["omniauth.strategy"].options[:idp_sso_service_url] = provider_config[:idp_sso_service_url]
env["omniauth.strategy"].options[:idp_slo_service_url] = provider_config[:idp_slo_service_url]
env["omniauth.strategy"].options[:idp_cert] = provider_config[:idp_cert]
env["omniauth.strategy"].options[:name_identifier_format] = provider_config[:name_identifier_format]
env["omniauth.strategy"].options[:attribute_service_name] = provider_config[:attribute_service_name]
}
# ,
# request_attributes: [
# { :name => 'email', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Email address' },
# { :name => 'name', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Full name' },
# { :name => 'first_name', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Given name' },
# { :name => 'last_name', :name_format => 'urn:oasis:names:tc:SAML:2.0:attrname-format:basic', :friendly_name => 'Family name' }
# ],
# attribute_statements: {
# name: ["name"],
# email: ["email", "mail"],
# first_name: ["first_name", "firstname", "firstName"],
# last_name: ["last_name", "lastname", "lastName"]
# }
)
end
end
14 changes: 14 additions & 0 deletions config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@

mount LetterOpenerWeb::Engine, at: "/letter_opener" if Rails.env.development? || ENV.fetch("ENABLE_LETTER_OPENER", "0") == "1"

devise_for :users,
class_name: "Decidim::User",
module: :devise,
router_name: :decidim,
controllers: {
invitations: "decidim/devise/invitations",
sessions: "decidim/devise/sessions",
confirmations: "decidim/devise/confirmations",
passwords: "decidim/devise/passwords",
unlocks: "decidim/devise/unlocks",
omniauth_callbacks: "decidim/devise/custom_omniauth_registrations"
},
skip: [:registrations]

mount Decidim::Core::Engine => "/"
# mount Decidim::Map::Engine => '/map'
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
Expand Down
10 changes: 10 additions & 0 deletions config/secrets.yml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ default: &default
client_secret: <%= ENV["OMNIAUTH_FC_CLIENT_SECRET"] %>
site_url: <%= ENV["OMNIAUTH_FC_SITE_URL"] %>
scope: <%= ENV["OMNIAUTH_FC_SCOPE"] %>
imt:
enabled: <%= ENV["OMNIAUTH_IMT_CLIENT_SECRET"].present? %>
issuer: <%= ENV["OMNIAUTH_IMT_ISSUER"] %>
assertion_consumer_service_url: <%= ENV["OMNIAUTH_IMT_ASSERTION_CONSUMER_SERVICE_URL"] %>
sp_entity_id: <%= ENV.fetch("OMNIAUTH_IMT_SP_ENTITY_ID", "decidim-imt") %>
idp_sso_service_url: <%= ENV["OMNIAUTH_IMT_IDP_SSO_SERVICE_URL"] %>
idp_slo_service_url: <%= ENV["OMNIAUTH_IMT_IDP_SLO_SERVICE_URL"] %>
idp_cert: <%= ENV["OMNIAUTH_IMT_IDP_CERT"] %>
name_identifier_format: <%= ENV["OMNIAUTH_IMT_NAME_IDENTIFIER_FORMAT"] %>
attribute_service_name: <%= ENV.fetch("OMNIAUTH_IMT_ATTRIBUTE_SERVICE_NAME", "Required attributes") %>
maps:
api_key: <%= ENV["GEOCODER_LOOKUP_API_KEY"] %>
sentry:
Expand Down
19 changes: 19 additions & 0 deletions lib/omniauth/strategies/imt.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# frozen_string_literal: true

require "omniauth-saml"

module OmniAuth
module Strategies
class IMT < OmniAuth::Strategies::SAML
option :name, :imt
option :protocol_binding, "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"

option :idp_cert_fingerprint_algorithm, XMLSecurity::Document::SHA256
option :security,
digest_method: XMLSecurity::Document::SHA256,
signature_method: XMLSecurity::Document::RSA_SHA256
end
end
end

OmniAuth.config.add_camelization "imt", "IMT"

0 comments on commit 188c1eb

Please sign in to comment.