decidim-msad 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE-AGPLv3.txt +661 -0
- data/README.md +476 -0
- data/Rakefile +17 -0
- data/app/controllers/decidim/msad/omniauth_callbacks_controller.rb +178 -0
- data/app/controllers/decidim/msad/sessions_controller.rb +58 -0
- data/app/controllers/decidim/msad/verification/authorizations_controller.rb +19 -0
- data/config/locales/en.yml +27 -0
- data/config/locales/fi.yml +26 -0
- data/config/locales/sv.yml +26 -0
- data/lib/decidim/msad.rb +198 -0
- data/lib/decidim/msad/authentication.rb +4 -0
- data/lib/decidim/msad/authentication/authenticator.rb +229 -0
- data/lib/decidim/msad/authentication/errors.rb +21 -0
- data/lib/decidim/msad/engine.rb +112 -0
- data/lib/decidim/msad/mail_interceptors.rb +9 -0
- data/lib/decidim/msad/mail_interceptors/generated_recipients_interceptor.rb +25 -0
- data/lib/decidim/msad/test/runtime.rb +38 -0
- data/lib/decidim/msad/verification.rb +5 -0
- data/lib/decidim/msad/verification/engine.rb +43 -0
- data/lib/decidim/msad/verification/manager.rb +17 -0
- data/lib/decidim/msad/verification/metadata_collector.rb +39 -0
- data/lib/decidim/msad/version.rb +8 -0
- data/lib/generators/decidim/msad/install_generator.rb +126 -0
- data/lib/generators/templates/msad_initializer.rb +74 -0
- data/lib/generators/templates/msad_initializer_test.rb +5 -0
- data/lib/omniauth/msad/metadata.rb +46 -0
- data/lib/omniauth/msad/settings.rb +9 -0
- data/lib/omniauth/msad/test.rb +10 -0
- data/lib/omniauth/msad/test/certificate_generator.rb +51 -0
- data/lib/omniauth/strategies/msad.rb +187 -0
- metadata +116 -0
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "decidim/dev/common_rake"
|
4
|
+
|
5
|
+
desc "Generates a dummy app for testing"
|
6
|
+
task test_app: "decidim:generate_external_test_app" do
|
7
|
+
Dir.chdir("spec/decidim_dummy_app") do
|
8
|
+
system("bundle exec rails generate decidim:msad:install --test-initializer true")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Generates a development app."
|
13
|
+
task development_app: "decidim:generate_external_development_app" do
|
14
|
+
Dir.chdir("development_app") do
|
15
|
+
system("bundle exec rails generate decidim:msad:install")
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Msad
|
5
|
+
class OmniauthCallbacksController < ::Decidim::Devise::OmniauthRegistrationsController
|
6
|
+
# Make the view helpers available needed in the views
|
7
|
+
helper Decidim::Msad::Engine.routes.url_helpers
|
8
|
+
helper_method :omniauth_registrations_path
|
9
|
+
|
10
|
+
skip_before_action :verify_authenticity_token, only: [:msad, :failure]
|
11
|
+
skip_after_action :verify_same_origin_request, only: [:msad, :failure]
|
12
|
+
|
13
|
+
# This is called always after the user returns from the authentication
|
14
|
+
# flow from the Active Directory identity provider.
|
15
|
+
def msad
|
16
|
+
session["decidim-msad.signed_in"] = true
|
17
|
+
|
18
|
+
authenticator.validate!
|
19
|
+
|
20
|
+
if user_signed_in?
|
21
|
+
# The user is most likely returning from an authorization request
|
22
|
+
# because they are already signed in. In this case, add the
|
23
|
+
# authorization and redirect the user back to the authorizations view.
|
24
|
+
|
25
|
+
# Make sure the user has an identity created in order to aid future
|
26
|
+
# Active Directory sign ins. In case this fails, it will raise a
|
27
|
+
# Decidim::Msad::Authentication::IdentityBoundToOtherUserError
|
28
|
+
# which is handled below.
|
29
|
+
authenticator.identify_user!(current_user)
|
30
|
+
|
31
|
+
# Add the authorization for the user
|
32
|
+
return fail_authorize unless authorize_user(current_user)
|
33
|
+
|
34
|
+
# Make sure the user details are up to date
|
35
|
+
authenticator.update_user!(current_user)
|
36
|
+
|
37
|
+
# Show the success message and redirect back to the authorizations
|
38
|
+
flash[:notice] = t(
|
39
|
+
"authorizations.create.success",
|
40
|
+
scope: "decidim.msad.verification"
|
41
|
+
)
|
42
|
+
return redirect_to(
|
43
|
+
stored_location_for(resource || :user) ||
|
44
|
+
decidim_verifications.authorizations_path
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Normal authentication request, proceed with Decidim's internal logic.
|
49
|
+
send(:create)
|
50
|
+
rescue Decidim::Msad::Authentication::ValidationError => e
|
51
|
+
fail_authorize(e.validation_key)
|
52
|
+
rescue Decidim::Msad::Authentication::IdentityBoundToOtherUserError
|
53
|
+
fail_authorize(:identity_bound_to_other_user)
|
54
|
+
end
|
55
|
+
|
56
|
+
def failure
|
57
|
+
strategy = failed_strategy
|
58
|
+
saml_response = strategy.response_object if strategy
|
59
|
+
return super unless saml_response
|
60
|
+
|
61
|
+
# In case we want more info about the returned status codes, use the
|
62
|
+
# code below.
|
63
|
+
#
|
64
|
+
# Status codes:
|
65
|
+
# Requester = A problem with the request OR the user cancelled the
|
66
|
+
# request at the identity provider.
|
67
|
+
# Responder = The handling of the request failed.
|
68
|
+
# VersionMismatch = Wrong version in the request.
|
69
|
+
#
|
70
|
+
# Additional state codes:
|
71
|
+
# AuthnFailed = The authentication failed OR the user cancelled
|
72
|
+
# the process at the identity provider.
|
73
|
+
# RequestDenied = The authenticating endpoint (which the
|
74
|
+
# identity provider redirects to) rejected the
|
75
|
+
# authentication.
|
76
|
+
# if !saml_response.send(:validate_success_status) && !saml_response.status_code.nil?
|
77
|
+
# codes = saml_response.status_code.split(" | ").map do |full_code|
|
78
|
+
# full_code.split(":").last
|
79
|
+
# end
|
80
|
+
# end
|
81
|
+
|
82
|
+
# Some extra validation checks
|
83
|
+
validations = [
|
84
|
+
# The success status validation fails in case the response status
|
85
|
+
# code is something else than "Success". This is most likely because
|
86
|
+
# of one the reasons explained above. In general there are few
|
87
|
+
# possible explanations for this:
|
88
|
+
# 1. The user cancelled the request and returned to the service.
|
89
|
+
# 2. The underlying identity service the IdP redirects to rejected
|
90
|
+
# the request for one reason or another. E.g. the user cancelled
|
91
|
+
# the request at the identity service.
|
92
|
+
# 3. There is some technical problem with the identity provider
|
93
|
+
# service or the XML request sent to there is malformed.
|
94
|
+
:success_status,
|
95
|
+
# Checks if the local session should be expired, i.e. if the user
|
96
|
+
# took too long time to go through the authorization endpoint.
|
97
|
+
:session_expiration,
|
98
|
+
# The NotBefore and NotOnOrAfter conditions failed, i.e. whether the
|
99
|
+
# request is handled within the allowed timeframe by the IdP.
|
100
|
+
:conditions
|
101
|
+
]
|
102
|
+
validations.each do |key|
|
103
|
+
next if saml_response.send("validate_#{key}")
|
104
|
+
|
105
|
+
flash[:alert] = t(".#{key}")
|
106
|
+
return redirect_to after_omniauth_failure_path_for(resource_name)
|
107
|
+
end
|
108
|
+
|
109
|
+
super
|
110
|
+
end
|
111
|
+
|
112
|
+
# This is overridden method from the Devise controller helpers
|
113
|
+
# This is called when the user is successfully authenticated which means
|
114
|
+
# that we also need to add the authorization for the user automatically
|
115
|
+
# because a succesful Active Directory authentication means the user has
|
116
|
+
# been successfully authorized as well.
|
117
|
+
def sign_in_and_redirect(resource_or_scope, *args)
|
118
|
+
# Add authorization for the user
|
119
|
+
if resource_or_scope.is_a?(::Decidim::User)
|
120
|
+
return fail_authorize unless authorize_user(resource_or_scope)
|
121
|
+
|
122
|
+
# Make sure the user details are up to date
|
123
|
+
authenticator.update_user!(resource_or_scope)
|
124
|
+
end
|
125
|
+
|
126
|
+
super
|
127
|
+
end
|
128
|
+
|
129
|
+
private
|
130
|
+
|
131
|
+
def authorize_user(user)
|
132
|
+
authenticator.authorize_user!(user)
|
133
|
+
rescue Decidim::Msad::Authentication::AuthorizationBoundToOtherUserError
|
134
|
+
nil
|
135
|
+
end
|
136
|
+
|
137
|
+
def fail_authorize(failure_message_key = :already_authorized)
|
138
|
+
flash[:alert] = t(
|
139
|
+
"failure.#{failure_message_key}",
|
140
|
+
scope: "decidim.msad.omniauth_callbacks"
|
141
|
+
)
|
142
|
+
|
143
|
+
redirect_path = stored_location_for(resource || :user) || decidim.root_path
|
144
|
+
if session.delete("decidim-msad.signed_in")
|
145
|
+
params = "?RelayState=#{CGI.escape(redirect_path)}"
|
146
|
+
|
147
|
+
return redirect_to user_msad_omniauth_spslo_path + params
|
148
|
+
end
|
149
|
+
|
150
|
+
redirect_to redirect_path
|
151
|
+
end
|
152
|
+
|
153
|
+
# Needs to be specifically defined because the core engine routes are not
|
154
|
+
# all properly loaded for the view and this helper method is needed for
|
155
|
+
# defining the omniauth registration form's submit path.
|
156
|
+
def omniauth_registrations_path(resource)
|
157
|
+
Decidim::Core::Engine.routes.url_helpers.omniauth_registrations_path(resource)
|
158
|
+
end
|
159
|
+
|
160
|
+
# Private: Create form params from omniauth hash
|
161
|
+
# Since we are using trusted omniauth data we are generating a valid signature.
|
162
|
+
def user_params_from_oauth_hash
|
163
|
+
authenticator.user_params_from_oauth_hash
|
164
|
+
end
|
165
|
+
|
166
|
+
def authenticator
|
167
|
+
@authenticator ||= Decidim::Msad.authenticator_for(
|
168
|
+
current_organization,
|
169
|
+
oauth_hash
|
170
|
+
)
|
171
|
+
end
|
172
|
+
|
173
|
+
def verified_email
|
174
|
+
authenticator.verified_email
|
175
|
+
end
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Msad
|
5
|
+
class SessionsController < ::Decidim::Devise::SessionsController
|
6
|
+
def destroy
|
7
|
+
# In case the user is signed in through the AD federation server,
|
8
|
+
# redirect them through the SPSLO flow.
|
9
|
+
if session.delete("decidim-msad.signed_in")
|
10
|
+
# These session variables get destroyed along with the user's active
|
11
|
+
# session. They are needed for the SLO request.
|
12
|
+
saml_uid = session["saml_uid"]
|
13
|
+
saml_session_index = session["saml_session_index"]
|
14
|
+
stored_location = stored_location_for(resource_name)
|
15
|
+
|
16
|
+
# End the local user session.
|
17
|
+
signed_out = (::Devise.sign_out_all_scopes ? sign_out : sign_out(resource_name))
|
18
|
+
|
19
|
+
# Store the SAML parameters for the SLO request utilized by
|
20
|
+
# omniauth-saml. These are used to generate a valid SLO request.
|
21
|
+
session["saml_uid"] = saml_uid
|
22
|
+
session["saml_session_index"] = saml_session_index
|
23
|
+
store_location_for(resource_name, stored_location) if stored_location
|
24
|
+
|
25
|
+
# Generate the SLO redirect path and parameters.
|
26
|
+
relay = slo_callback_user_session_path
|
27
|
+
relay += "?success=1" if signed_out
|
28
|
+
params = "?RelayState=#{CGI.escape(relay)}"
|
29
|
+
|
30
|
+
return redirect_to user_msad_omniauth_spslo_path + params
|
31
|
+
end
|
32
|
+
|
33
|
+
# Otherwise, continue normally
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
def slo
|
38
|
+
# This is handled already by omniauth
|
39
|
+
redirect_to decidim.root_path
|
40
|
+
end
|
41
|
+
|
42
|
+
def spslo
|
43
|
+
# This is handled already by omniauth
|
44
|
+
redirect_to decidim.root_path
|
45
|
+
end
|
46
|
+
|
47
|
+
def slo_callback
|
48
|
+
set_flash_message! :notice, :signed_out if params[:success] == "1"
|
49
|
+
|
50
|
+
# Redirect to the root path when the organization forces users to
|
51
|
+
# authenticate before accessing the organization.
|
52
|
+
return redirect_to(decidim.new_user_session_path) if current_organization.force_users_to_authenticate_before_access_organization
|
53
|
+
|
54
|
+
redirect_to stored_location_for(resource_name) || decidim.root_path
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Decidim
|
4
|
+
module Msad
|
5
|
+
module Verification
|
6
|
+
class AuthorizationsController < ::Decidim::ApplicationController
|
7
|
+
skip_before_action :store_current_location
|
8
|
+
|
9
|
+
def new
|
10
|
+
# Do not enforce the permission here because it would cause
|
11
|
+
# re-authorizations not to work as the authorization already exists.
|
12
|
+
# In case the user wants to re-authorize themselves, they can just
|
13
|
+
# hit this endpoint again.
|
14
|
+
redirect_to decidim.user_msad_omniauth_authorize_path
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
---
|
2
|
+
en:
|
3
|
+
decidim:
|
4
|
+
authorization_handlers:
|
5
|
+
msad_identity:
|
6
|
+
explanation: Identify yourself using the Active Directory identity service.
|
7
|
+
name: Active Directory identity
|
8
|
+
msad:
|
9
|
+
omniauth_callbacks:
|
10
|
+
failure:
|
11
|
+
already_authorized: Another user has already authorized themselves with the same identity.
|
12
|
+
conditions: The authentication request was not handled within an allowed timeframe. Please try again.
|
13
|
+
identity_bound_to_other_user: Another user has already been identified using this identity. Please sign out and sign in again directly using Active Directory.
|
14
|
+
invalid_data: You cannot be authenticated through Active Directory.
|
15
|
+
session_expiration: Authentication session expired. Please try again.
|
16
|
+
success_status: Authentication failed or cancelled. Please try again.
|
17
|
+
verification:
|
18
|
+
authorizations:
|
19
|
+
create:
|
20
|
+
success: You have been successfully authorized through Active Directory
|
21
|
+
destroy:
|
22
|
+
success: Authorization sucessfully reset.
|
23
|
+
system:
|
24
|
+
organizations:
|
25
|
+
omniauth_settings:
|
26
|
+
msad:
|
27
|
+
metadata_url: Metadata URL
|
@@ -0,0 +1,26 @@
|
|
1
|
+
fi:
|
2
|
+
decidim:
|
3
|
+
authorization_handlers:
|
4
|
+
msad_identity:
|
5
|
+
explanation: Tunnista itsesi Active Directory -tunnistuspalvelun avulla.
|
6
|
+
name: Active Directory tunnistus
|
7
|
+
msad:
|
8
|
+
omniauth_callbacks:
|
9
|
+
failure:
|
10
|
+
already_authorized: Toinen käyttäjä on tunnistanut itsensä jo samalla henkilöllisyydellä.
|
11
|
+
conditions: Tunnistuspyyntöä ei käsitelty sallitun aikarajan sisällä. Yritä uudestaan.
|
12
|
+
identity_bound_to_other_user: Toinen käyttäjä on jo tunnistanut itsensä tällä henkilöllisyydellä. Kirjaudu ulos ja kirjaudu uudestaan sisään käyttäen suoraan Active Directory -tunnistusta.
|
13
|
+
invalid_data: Sinua ei voida tunnistaa Active Directoryn kautta.
|
14
|
+
session_expiration: Tunnistusistunto vanhentui. Yritä uudestaan.
|
15
|
+
success_status: Tunnistus epäonnistui tai peruutettiin. Yritä uudestaan.
|
16
|
+
verification:
|
17
|
+
authorizations:
|
18
|
+
create:
|
19
|
+
success: Sinut on onnistuneesti tunnistettu Active Directory -palvelun avulla
|
20
|
+
destroy:
|
21
|
+
success: Varmennus tyhjennetty onnistuneesti.
|
22
|
+
system:
|
23
|
+
organizations:
|
24
|
+
omniauth_settings:
|
25
|
+
msad:
|
26
|
+
metadata_url: Metadatan osoite (URL)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
sv:
|
2
|
+
decidim:
|
3
|
+
authorization_handlers:
|
4
|
+
msad_identity:
|
5
|
+
explanation: Identifiera dig själv med Active Directory -identifikation.
|
6
|
+
name: Active Directory -identifikation
|
7
|
+
msad:
|
8
|
+
omniauth_callbacks:
|
9
|
+
failure:
|
10
|
+
already_authorized: En annan användare har redan godkänt sig med samma identitet.
|
11
|
+
conditions: Autentiseringsbegäran hanterades inte inom en tillåten tidsram. Var god försök igen.
|
12
|
+
identity_bound_to_other_user: En annan användare har redan identifierats med denna identitet. Logga ut och logga in igen direkt med Active Directory.
|
13
|
+
invalid_data: Du kan inte verifieras via Active Directory.
|
14
|
+
session_expiration: Autentiseringssessionen har gått ut. Var god försök igen.
|
15
|
+
success_status: Autentiseringen misslyckades eller avbröts. Var god försök igen.
|
16
|
+
verification:
|
17
|
+
authorizations:
|
18
|
+
create:
|
19
|
+
success: Du har godkänts med Active Directory
|
20
|
+
destroy:
|
21
|
+
success: Tillståndet återställs efterhand.
|
22
|
+
system:
|
23
|
+
organizations:
|
24
|
+
omniauth_settings:
|
25
|
+
msad:
|
26
|
+
metadata_url: Metadata URL
|
data/lib/decidim/msad.rb
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "omniauth"
|
4
|
+
require "omniauth/strategies/msad"
|
5
|
+
|
6
|
+
require_relative "msad/version"
|
7
|
+
require_relative "msad/engine"
|
8
|
+
require_relative "msad/authentication"
|
9
|
+
require_relative "msad/verification"
|
10
|
+
require_relative "msad/mail_interceptors"
|
11
|
+
|
12
|
+
module Decidim
|
13
|
+
module Msad
|
14
|
+
include ActiveSupport::Configurable
|
15
|
+
|
16
|
+
@configured = false
|
17
|
+
|
18
|
+
# Defines the auto email domain to generate verified email addresses upon
|
19
|
+
# the user's registration automatically that have format similar to
|
20
|
+
# "msad-identifier@auto-email-domain.fi".
|
21
|
+
#
|
22
|
+
# In case this is not defined, the default is the organization's domain.
|
23
|
+
config_accessor :auto_email_domain
|
24
|
+
|
25
|
+
config_accessor :idp_metadata_url
|
26
|
+
config_accessor :sp_entity_id, instance_reader: false
|
27
|
+
|
28
|
+
# The certificate string for the application
|
29
|
+
config_accessor :certificate, instance_reader: false
|
30
|
+
|
31
|
+
# The private key string for the application
|
32
|
+
config_accessor :private_key, instance_reader: false
|
33
|
+
|
34
|
+
# The certificate file for the application
|
35
|
+
config_accessor :certificate_file
|
36
|
+
|
37
|
+
# The private key file for the application
|
38
|
+
config_accessor :private_key_file
|
39
|
+
|
40
|
+
# Defines how the session gets cleared when the OmniAuth strategy logs the
|
41
|
+
# user out. This has been customized to preserve the flash messages and the
|
42
|
+
# stored redirect location in the session after the session is destroyed.
|
43
|
+
config_accessor :idp_slo_session_destroy do
|
44
|
+
proc do |_env, session|
|
45
|
+
flash = session["flash"]
|
46
|
+
return_to = session["user_return_to"]
|
47
|
+
result = session.clear
|
48
|
+
session["flash"] = flash if flash
|
49
|
+
session["user_return_to"] = return_to if return_to
|
50
|
+
result
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# These are extra attributes that can be stored for the authorization
|
55
|
+
# metadata. Define these as follows:
|
56
|
+
#
|
57
|
+
# Decidim::Msad.configure do |config|
|
58
|
+
# # ...
|
59
|
+
# config.metadata_attributes = {
|
60
|
+
# primary_group_sid: "http://schemas.microsoft.com/ws/2008/06/identity/claims/primarygroupsid",
|
61
|
+
# groups: { name: "http://schemas.xmlsoap.org/claims/Group", type: :multi }
|
62
|
+
# }
|
63
|
+
# end
|
64
|
+
config_accessor :metadata_attributes do
|
65
|
+
{}
|
66
|
+
end
|
67
|
+
|
68
|
+
# Extra metadata to be included in the service provider metadata. Define as
|
69
|
+
# follows:
|
70
|
+
#
|
71
|
+
# Decidim::Msad.configure do |config|
|
72
|
+
# # ...
|
73
|
+
# config.sp_metadata = [
|
74
|
+
# {
|
75
|
+
# name: "Organization",
|
76
|
+
# children: [
|
77
|
+
# {
|
78
|
+
# name: "OrganizationName",
|
79
|
+
# attributes: { "xml:lang" => "en-US" },
|
80
|
+
# content: "Acme"
|
81
|
+
# }
|
82
|
+
# ]
|
83
|
+
# }
|
84
|
+
# ]
|
85
|
+
# end
|
86
|
+
config_accessor :sp_metadata do
|
87
|
+
[]
|
88
|
+
end
|
89
|
+
|
90
|
+
# Extra configuration for the omniauth strategy
|
91
|
+
config_accessor :extra do
|
92
|
+
{}
|
93
|
+
end
|
94
|
+
|
95
|
+
# Defines whether registered users are automatically subscribed to the
|
96
|
+
# newsletters during the OmniAuth registration flow. This is only updated
|
97
|
+
# during the first login, so users can still unsubscribe if they later
|
98
|
+
# decide they don't want to receive the newsletter and later logins will not
|
99
|
+
# change the subscription state.
|
100
|
+
config_accessor :registration_newsletter_subscriptions do
|
101
|
+
false
|
102
|
+
end
|
103
|
+
|
104
|
+
# Allows customizing the authorization workflow e.g. for adding custom
|
105
|
+
# workflow options or configuring an action authorizer for the
|
106
|
+
# particular needs.
|
107
|
+
config_accessor :workflow_configurator do
|
108
|
+
lambda do |workflow|
|
109
|
+
# By default, expiration is set to 0 minutes which means it will
|
110
|
+
# never expire.
|
111
|
+
workflow.expires_in = 0.minutes
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# Allows customizing parts of the authentication flow such as validating
|
116
|
+
# the authorization data before allowing the user to be authenticated.
|
117
|
+
config_accessor :authenticator_class do
|
118
|
+
Decidim::Msad::Authentication::Authenticator
|
119
|
+
end
|
120
|
+
|
121
|
+
# Allows customizing how the authorization metadata gets collected from
|
122
|
+
# the SAML attributes passed from the authorization endpoint.
|
123
|
+
config_accessor :metadata_collector_class do
|
124
|
+
Decidim::Msad::Verification::MetadataCollector
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.configured?
|
128
|
+
@configured
|
129
|
+
end
|
130
|
+
|
131
|
+
def self.configure
|
132
|
+
@configured = true
|
133
|
+
super
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.authenticator_for(organization, oauth_hash)
|
137
|
+
authenticator_class.new(organization, oauth_hash)
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.sp_entity_id
|
141
|
+
return config.sp_entity_id if config.sp_entity_id
|
142
|
+
|
143
|
+
"#{application_host}/users/auth/msad/metadata"
|
144
|
+
end
|
145
|
+
|
146
|
+
def self.certificate
|
147
|
+
return File.read(certificate_file) if certificate_file
|
148
|
+
|
149
|
+
config.certificate
|
150
|
+
end
|
151
|
+
|
152
|
+
def self.private_key
|
153
|
+
return File.read(private_key_file) if private_key_file
|
154
|
+
|
155
|
+
config.private_key
|
156
|
+
end
|
157
|
+
|
158
|
+
def self.omniauth_settings
|
159
|
+
{
|
160
|
+
idp_metadata_url: idp_metadata_url,
|
161
|
+
sp_entity_id: sp_entity_id,
|
162
|
+
sp_name_qualifier: sp_entity_id,
|
163
|
+
idp_slo_session_destroy: idp_slo_session_destroy,
|
164
|
+
sp_metadata: sp_metadata,
|
165
|
+
certificate: certificate,
|
166
|
+
private_key: private_key,
|
167
|
+
# Define the assertion and SLO URLs for the metadata.
|
168
|
+
assertion_consumer_service_url: "#{application_host}/users/auth/msad/callback",
|
169
|
+
single_logout_service_url: "#{application_host}/users/auth/msad/slo"
|
170
|
+
}.merge(extra)
|
171
|
+
end
|
172
|
+
|
173
|
+
# Used to determine the default service provider entity ID in case not
|
174
|
+
# specifically set by the `sp_entity_id` configuration option.
|
175
|
+
def self.application_host
|
176
|
+
conf = Rails.application.config
|
177
|
+
url_options = conf.action_controller.default_url_options
|
178
|
+
url_options = conf.action_mailer.default_url_options if !url_options || !url_options[:host]
|
179
|
+
url_options ||= {}
|
180
|
+
|
181
|
+
# Note that at least Azure AD requires all callback URLs to be HTTPS, so
|
182
|
+
# we'll default to that.
|
183
|
+
host = url_options[:host]
|
184
|
+
port = url_options[:port]
|
185
|
+
protocol = url_options[:protocol]
|
186
|
+
protocol = port.to_i == 80 ? "http" : "https" if protocol.blank?
|
187
|
+
if host.blank?
|
188
|
+
# Default to local development environment.
|
189
|
+
host = "localhost"
|
190
|
+
port ||= 3000
|
191
|
+
end
|
192
|
+
|
193
|
+
return "#{protocol}://#{host}:#{port}" if port && ![80, 443].include?(port.to_i)
|
194
|
+
|
195
|
+
"#{protocol}://#{host}"
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|