Add omniauth saml section for sign in and sign up page

Co-authored-by: Anamika Aggarwal <anamikaagg18@gmail.com>
This commit is contained in:
taitus
2022-07-11 13:06:44 +02:00
committed by Javi Martín
parent 9d216084a7
commit a4709f9da0
15 changed files with 181 additions and 2 deletions

View File

@@ -38,6 +38,7 @@ gem "omniauth", "~> 2.1.3"
gem "omniauth-facebook", "~> 10.0.0" gem "omniauth-facebook", "~> 10.0.0"
gem "omniauth-google-oauth2", "~> 1.2.1" gem "omniauth-google-oauth2", "~> 1.2.1"
gem "omniauth-rails_csrf_protection", "~> 1.0.2" gem "omniauth-rails_csrf_protection", "~> 1.0.2"
gem "omniauth-saml", "~> 2.1.0"
gem "omniauth-twitter", "~> 1.4.0" gem "omniauth-twitter", "~> 1.4.0"
gem "paranoia", "~> 3.0.1" gem "paranoia", "~> 3.0.1"
gem "pg", "~> 1.5.9" gem "pg", "~> 1.5.9"

View File

@@ -440,6 +440,9 @@ GEM
omniauth-rails_csrf_protection (1.0.2) omniauth-rails_csrf_protection (1.0.2)
actionpack (>= 4.2) actionpack (>= 4.2)
omniauth (~> 2.0) omniauth (~> 2.0)
omniauth-saml (2.1.0)
omniauth (~> 2.0)
ruby-saml (~> 1.12)
omniauth-twitter (1.4.0) omniauth-twitter (1.4.0)
omniauth-oauth (~> 1.1) omniauth-oauth (~> 1.1)
rack rack
@@ -609,6 +612,9 @@ GEM
rubocop-rspec (~> 3, >= 3.0.1) rubocop-rspec (~> 3, >= 3.0.1)
ruby-progressbar (1.13.0) ruby-progressbar (1.13.0)
ruby-rc4 (0.1.5) ruby-rc4 (0.1.5)
ruby-saml (1.15.0)
nokogiri (>= 1.13.10)
rexml
ruby-vips (2.2.3) ruby-vips (2.2.3)
ffi (~> 1.12) ffi (~> 1.12)
logger logger
@@ -797,6 +803,7 @@ DEPENDENCIES
omniauth-facebook (~> 10.0.0) omniauth-facebook (~> 10.0.0)
omniauth-google-oauth2 (~> 1.2.1) omniauth-google-oauth2 (~> 1.2.1)
omniauth-rails_csrf_protection (~> 1.0.2) omniauth-rails_csrf_protection (~> 1.0.2)
omniauth-saml (~> 2.1.0)
omniauth-twitter (~> 1.4.0) omniauth-twitter (~> 1.4.0)
paranoia (~> 3.0.1) paranoia (~> 3.0.1)
pdf-reader (~> 2.14.1) pdf-reader (~> 2.14.1)

View File

@@ -1392,7 +1392,8 @@ table {
.button.button-twitter, .button.button-twitter,
.button.button-facebook, .button.button-facebook,
.button.button-google, .button.button-google,
.button.button-wordpress { .button.button-wordpress,
.button.button-saml {
color: inherit; color: inherit;
font-weight: bold; font-weight: bold;
@@ -1442,6 +1443,17 @@ table {
} }
} }
.button.button-saml {
@include has-fa-icon(lock, solid);
background: #eafee9;
border-left: 3px solid #3b9857;
&::before {
color: #3b9857;
}
}
// 14. Verification // 14. Verification
// ---------------- // ----------------

View File

@@ -4,6 +4,7 @@ class Admin::Settings::FeaturesTabComponent < ApplicationComponent
feature.featured_proposals feature.featured_proposals
feature.facebook_login feature.facebook_login
feature.google_login feature.google_login
feature.saml_login
feature.twitter_login feature.twitter_login
feature.wordpress_login feature.wordpress_login
feature.signature_sheets feature.signature_sheets

View File

@@ -16,7 +16,8 @@ class Devise::OmniauthFormComponent < ApplicationComponent
(:twitter if feature?(:twitter_login)), (:twitter if feature?(:twitter_login)),
(:facebook if feature?(:facebook_login)), (:facebook if feature?(:facebook_login)),
(:google_oauth2 if feature?(:google_login)), (:google_oauth2 if feature?(:google_login)),
(:wordpress_oauth2 if feature?(:wordpress_login)) (:wordpress_oauth2 if feature?(:wordpress_login)),
(:saml if feature?(:saml_login))
].compact ].compact
end end
end end

View File

@@ -1,4 +1,6 @@
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
skip_before_action :verify_authenticity_token, only: :saml
def twitter def twitter
sign_in_with :twitter_login, :twitter sign_in_with :twitter_login, :twitter
end end
@@ -15,6 +17,10 @@ class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
sign_in_with :wordpress_login, :wordpress_oauth2 sign_in_with :wordpress_login, :wordpress_oauth2
end end
def saml
sign_in_with :saml_login, :saml
end
def after_sign_in_path_for(resource) def after_sign_in_path_for(resource)
if resource.registering_with_oauth if resource.registering_with_oauth
finish_signup_path finish_signup_path

View File

@@ -85,6 +85,7 @@ class Setting < ApplicationRecord
"feature.remote_census": nil, "feature.remote_census": nil,
"feature.valuation_comment_notification": true, "feature.valuation_comment_notification": true,
"feature.graphql_api": true, "feature.graphql_api": true,
"feature.saml_login": false,
"feature.sdg": true, "feature.sdg": true,
"feature.machine_learning": false, "feature.machine_learning": false,
"feature.remove_investments_supports": true, "feature.remove_investments_supports": true,

View File

@@ -286,6 +286,10 @@ Devise.setup do |config|
Rails.application.secrets.wordpress_oauth2_secret, Rails.application.secrets.wordpress_oauth2_secret,
client_options: { site: Rails.application.secrets.wordpress_oauth2_site }, client_options: { site: Rails.application.secrets.wordpress_oauth2_site },
setup: ->(env) { OmniauthTenantSetup.wordpress_oauth2(env) } setup: ->(env) { OmniauthTenantSetup.wordpress_oauth2(env) }
config.omniauth :saml,
sp_entity_id: Rails.application.secrets.saml_sp_entity_id,
idp_cert: Rails.application.secrets.saml_idp_cert,
idp_sso_service_url: Rails.application.secrets.saml_idp_sso_service_url
# ==> Warden configuration # ==> Warden configuration
# If you want to use other strategies, that are not supported by Devise, or # If you want to use other strategies, that are not supported by Devise, or

View File

@@ -278,6 +278,10 @@ en:
info: info:
sign_in: "Sign in with:" sign_in: "Sign in with:"
sign_up: "Sign up with:" sign_up: "Sign up with:"
saml:
sign_in: Sign in with SAML
sign_up: Sign up with SAML
name: SAML
or_fill: "Or fill the following form:" or_fill: "Or fill the following form:"
proposals: proposals:
create: create:

View File

@@ -91,6 +91,8 @@ en:
google_login_description: "Allow users to sign up with their Google Account" google_login_description: "Allow users to sign up with their Google Account"
wordpress_login: "Wordpress login" wordpress_login: "Wordpress login"
wordpress_login_description: "Allow users to sign up with their Wordpress Account" wordpress_login_description: "Allow users to sign up with their Wordpress Account"
saml_login: "SAML login"
saml_login_description: "Allow users to sign up with SAML"
featured_proposals: "Featured proposals" featured_proposals: "Featured proposals"
featured_proposals_description: "Shows featured proposals on index proposals page" featured_proposals_description: "Shows featured proposals on index proposals page"
signature_sheets: "Signature sheets" signature_sheets: "Signature sheets"

View File

@@ -275,6 +275,10 @@ es:
sign_in: Entra con Twitter sign_in: Entra con Twitter
sign_up: Regístrate con Twitter sign_up: Regístrate con Twitter
name: Twitter name: Twitter
saml:
sign_in: Entra con SAML
sign_up: Regístrate con SAML
name: SAML
info: info:
sign_in: "Entra con:" sign_in: "Entra con:"
sign_up: "Regístrate con:" sign_up: "Regístrate con:"

View File

@@ -91,6 +91,8 @@ es:
google_login_description: "Permitir que los usuarios se registren con su cuenta de Google" google_login_description: "Permitir que los usuarios se registren con su cuenta de Google"
wordpress_login: "Registro con Wordpress" wordpress_login: "Registro con Wordpress"
wordpress_login_description: "Permitir que los usuarios se registren con su cuenta de Wordpress" wordpress_login_description: "Permitir que los usuarios se registren con su cuenta de Wordpress"
saml_login: "Registro con SAML"
saml_login_description: "Permitir que los usuarios se registren usando SAML"
featured_proposals: "Propuestas destacadas" featured_proposals: "Propuestas destacadas"
featured_proposals_description: "Muestra propuestas destacadas en la página principal de propuestas" featured_proposals_description: "Muestra propuestas destacadas en la página principal de propuestas"
signature_sheets: "Hojas de firmas" signature_sheets: "Hojas de firmas"

View File

@@ -91,6 +91,9 @@ staging:
wordpress_oauth2_key: "" wordpress_oauth2_key: ""
wordpress_oauth2_secret: "" wordpress_oauth2_secret: ""
wordpress_oauth2_site: "" wordpress_oauth2_site: ""
saml_sp_entity_id: ""
saml_idp_cert: ""
saml_idp_sso_service_url: ""
<<: *maps <<: *maps
<<: *apis <<: *apis
@@ -147,6 +150,9 @@ preproduction:
wordpress_oauth2_key: "" wordpress_oauth2_key: ""
wordpress_oauth2_secret: "" wordpress_oauth2_secret: ""
wordpress_oauth2_site: "" wordpress_oauth2_site: ""
saml_sp_entity_id: ""
saml_idp_cert: ""
saml_idp_sso_service_url: ""
<<: *maps <<: *maps
<<: *apis <<: *apis
@@ -202,5 +208,8 @@ production:
wordpress_oauth2_key: "" wordpress_oauth2_key: ""
wordpress_oauth2_secret: "" wordpress_oauth2_secret: ""
wordpress_oauth2_site: "" wordpress_oauth2_site: ""
saml_sp_entity_id: ""
saml_idp_cert: ""
saml_idp_sso_service_url: ""
<<: *maps <<: *maps
<<: *apis <<: *apis

View File

@@ -9,6 +9,7 @@ describe Devise::OmniauthFormComponent do
Setting["feature.twitter_login"] = false Setting["feature.twitter_login"] = false
Setting["feature.google_login"] = false Setting["feature.google_login"] = false
Setting["feature.wordpress_login"] = false Setting["feature.wordpress_login"] = false
Setting["feature.saml_login"] = false
end end
it "is not rendered when all authentications are disabled" do it "is not rendered when all authentications are disabled" do
@@ -52,5 +53,14 @@ describe Devise::OmniauthFormComponent do
expect(page).to have_button "Wordpress" expect(page).to have_button "Wordpress"
expect(page).to have_button count: 1 expect(page).to have_button count: 1
end end
it "renders the SAML link when the feature is enabled" do
Setting["feature.saml_login"] = true
render_inline component
expect(page).to have_button "SAML"
expect(page).to have_button count: 1
end
end end
end end

View File

@@ -488,6 +488,121 @@ describe "Users" do
expect(page).to have_field "Email", with: "manuela@consul.dev" expect(page).to have_field "Email", with: "manuela@consul.dev"
end end
end end
context "Saml" do
before { Setting["feature.saml_login"] = true }
let(:saml_hash_with_email) do
{
provider: "saml",
uid: "ext-tester",
info: {
name: "samltester",
email: "tester@consul.dev"
}
}
end
let(:saml_hash_with_verified_email) do
{
provider: "saml",
uid: "ext-tester",
info: {
name: "samltester",
email: "tester@consul.dev",
verified: "1"
}
}
end
scenario "Sign up with a confirmed email" do
OmniAuth.config.add_mock(:saml, saml_hash_with_verified_email)
visit new_user_registration_path
click_button "Sign up with SAML"
expect(page).to have_content "Successfully identified as Saml"
expect_to_be_signed_in
within("#notice") { click_button "Close" }
click_link "My account"
expect(page).to have_field "Username", with: "samltester"
click_link "Change my login details"
expect(page).to have_field "Email", with: "tester@consul.dev"
end
scenario "Sign up with an unconfirmed email" do
OmniAuth.config.add_mock(:saml, saml_hash_with_email)
visit new_user_registration_path
click_button "Sign up with SAML"
expect(page).to have_content "To continue, please click on the confirmation " \
"link that we have sent you via email"
confirm_email
expect(page).to have_content "Your account has been confirmed"
expect(page).to have_current_path new_user_session_path
click_button "Sign in with SAML"
expect(page).to have_content "Successfully identified as Saml"
expect_to_be_signed_in
within("#notice") { click_button "Close" }
click_link "My account"
expect(page).to have_field "Username", with: "samltester"
click_link "Change my login details"
expect(page).to have_field "Email", with: "tester@consul.dev"
end
scenario "Sign in with a user with a SAML identity" do
user = create(:user, username: "samltester", email: "tester@consul.dev", password: "My123456")
create(:identity, uid: "ext-tester", provider: "saml", user: user)
OmniAuth.config.add_mock(:saml, { provider: "saml", uid: "ext-tester" })
visit new_user_session_path
click_button "Sign in with SAML"
expect(page).to have_content "Successfully identified as Saml"
expect_to_be_signed_in
within("#notice") { click_button "Close" }
click_link "My account"
expect(page).to have_field "Username", with: "samltester"
click_link "Change my login details"
expect(page).to have_field "Email", with: "tester@consul.dev"
end
scenario "Sign in with a user without a SAML identity keeps the username" do
create(:user, username: "tester", email: "tester@consul.dev", password: "My123456")
OmniAuth.config.add_mock(:saml, saml_hash_with_verified_email)
visit new_user_session_path
click_button "Sign in with SAML"
expect(page).to have_content "Successfully identified as Saml"
expect_to_be_signed_in
within("#notice") { click_button "Close" }
click_link "My account"
expect(page).to have_field "Username", with: "tester"
click_link "Change my login details"
expect(page).to have_field "Email", with: "tester@consul.dev"
end
end
end end
scenario "Sign out" do scenario "Sign out" do