better_auth-sso 0.1.0 → 0.2.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.
@@ -44,18 +44,24 @@ module BetterAuth
44
44
  end
45
45
 
46
46
  attributes = response.attributes
47
- email = first_attribute(attributes, attribute_map.fetch(:email)) || response.nameid
47
+ mapping = BetterAuth::Plugins.normalize_hash(config[:mapping] || {})
48
+ email = mapped_attribute(attributes, mapping[:email]) || first_attribute(attributes, attribute_map.fetch(:email)) || response.nameid
48
49
  raise BetterAuth::APIError.new("BAD_REQUEST", message: "Invalid SAML response") if email.to_s.empty?
49
50
 
50
- given_name = first_attribute(attributes, attribute_map.fetch(:given_name))
51
- family_name = first_attribute(attributes, attribute_map.fetch(:family_name))
52
- name = first_attribute(attributes, attribute_map.fetch(:name)) || [given_name, family_name].compact.join(" ").strip
53
- {
51
+ given_name = mapped_attribute(attributes, mapping[:first_name]) || first_attribute(attributes, attribute_map.fetch(:given_name))
52
+ family_name = mapped_attribute(attributes, mapping[:last_name]) || first_attribute(attributes, attribute_map.fetch(:family_name))
53
+ name = [given_name, family_name].compact.join(" ").strip
54
+ name = mapped_attribute(attributes, mapping[:name]) || first_attribute(attributes, attribute_map.fetch(:name)) if name.empty?
55
+ extra_fields = mapped_extra_fields(attributes, mapping)
56
+ email_verified = mapping[:email_verified] ? mapped_attribute(attributes, mapping[:email_verified]) : true
57
+ extra_fields.merge(
54
58
  email: email.to_s.downcase,
55
59
  name: name.to_s.empty? ? email.to_s : name.to_s,
56
- id: assertion_identifier(response, email),
57
- email_verified: true
58
- }
60
+ id: mapped_attribute(attributes, mapping[:id]) || assertion_identifier(response, email),
61
+ name_id: response.nameid,
62
+ session_index: response.sessionindex,
63
+ email_verified: (email_verified == false) ? false : !email_verified.to_s.empty?
64
+ )
59
65
  end
60
66
  end
61
67
 
@@ -69,14 +75,26 @@ module BetterAuth
69
75
  settings.idp_sso_service_url = config[:entry_point]
70
76
  settings.idp_cert = config[:cert] unless config[:cert].to_s.empty?
71
77
  settings.name_identifier_format = config[:identifier_format] unless config[:identifier_format].to_s.empty?
72
- settings.private_key = config[:sp_private_key] unless config[:sp_private_key].to_s.empty?
73
- settings.certificate = config[:sp_certificate] unless config[:sp_certificate].to_s.empty?
78
+ private_key = config.dig(:sp_metadata, :private_key) || config[:private_key] || config[:sp_private_key]
79
+ authn_requests_signed = config.fetch(:authn_requests_signed, config[:want_authn_requests_signed])
80
+ if authn_requests_signed && private_key.to_s.empty?
81
+ raise BetterAuth::APIError.new("BAD_REQUEST", message: "SAML authnRequestsSigned requires privateKey")
82
+ end
83
+ settings.private_key = private_key unless private_key.to_s.empty?
84
+ certificate = config.dig(:sp_metadata, :certificate) || config[:sp_certificate]
85
+ certificate ||= config[:certificate] if config[:certificate].is_a?(String)
86
+ settings.certificate = certificate unless certificate.to_s.empty?
74
87
  settings.security[:want_assertions_signed] = config.fetch(:want_assertions_signed, true)
75
88
  settings.security[:want_messages_signed] = config.fetch(:want_messages_signed, false)
76
89
  settings.security[:want_assertions_encrypted] = config.fetch(:want_assertions_encrypted, false)
90
+ settings.security[:authn_requests_signed] = !!authn_requests_signed
77
91
  settings.security[:strict_audience_validation] = true
78
92
  settings.security[:digest_method] = config[:digest_algorithm] || XMLSecurity::Document::SHA256
79
- settings.security[:signature_method] = config[:signature_algorithm] || XMLSecurity::Document::RSA_SHA256
93
+ settings.security[:signature_method] = if config[:signature_algorithm]
94
+ BetterAuth::Plugins.sso_normalize_saml_signature_algorithm(config[:signature_algorithm])
95
+ else
96
+ XMLSecurity::Document::RSA_SHA256
97
+ end
80
98
  settings
81
99
  end
82
100
 
@@ -92,20 +110,41 @@ module BetterAuth
92
110
  allowed_data_encryption_algorithms: config[:allowed_data_encryption_algorithms]
93
111
  )
94
112
  rescue BetterAuth::APIError
95
- raise
113
+ raise BetterAuth::APIError.new("BAD_REQUEST", message: "Invalid SAML response")
96
114
  rescue
97
115
  raise BetterAuth::APIError.new("BAD_REQUEST", message: "Invalid SAML response")
98
116
  end
99
117
 
100
118
  def first_attribute(attributes, names)
101
119
  Array(names).each do |name|
102
- value = attributes[name]
120
+ value = attribute_value(attributes, name)
103
121
  value = value.first if value.is_a?(Array)
104
122
  return value unless value.to_s.empty?
105
123
  end
106
124
  nil
107
125
  end
108
126
 
127
+ def mapped_attribute(attributes, name)
128
+ return nil if name.to_s.empty?
129
+
130
+ value = attribute_value(attributes, name)
131
+ value = value.first if value.is_a?(Array)
132
+ value unless value.to_s.empty?
133
+ end
134
+
135
+ def mapped_extra_fields(attributes, mapping)
136
+ BetterAuth::Plugins.normalize_hash(mapping[:extra_fields] || {}).each_with_object({}) do |(target, source), result|
137
+ result[target] = mapped_attribute(attributes, source)
138
+ end
139
+ end
140
+
141
+ def attribute_value(attributes, name)
142
+ [name, name.to_s, BetterAuth::Plugins.normalize_key(name)].each do |key|
143
+ return attributes[key] if attributes.respond_to?(:key?) && attributes.key?(key)
144
+ end
145
+ attributes[name] || attributes[name.to_s] || attributes[BetterAuth::Plugins.normalize_key(name)]
146
+ end
147
+
109
148
  def assertion_identifier(response, email)
110
149
  response.assertion_id || response.nameid || response.sessionindex || email
111
150
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module BetterAuth
4
4
  module SSO
5
- VERSION = "0.1.0"
5
+ VERSION = "0.2.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: better_auth-sso
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sebastian Sala