icn_saml_idp 0.4.1

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.
Files changed (129) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +2 -0
  3. data/LICENSE +22 -0
  4. data/README.md +238 -0
  5. data/app/controllers/saml_idp/idp_controller.rb +53 -0
  6. data/app/views/saml_idp/idp/new.html.erb +22 -0
  7. data/app/views/saml_idp/idp/saml_post.html.erb +14 -0
  8. data/lib/saml_idp.rb +92 -0
  9. data/lib/saml_idp/algorithmable.rb +19 -0
  10. data/lib/saml_idp/assertion_builder.rb +172 -0
  11. data/lib/saml_idp/attribute_decorator.rb +27 -0
  12. data/lib/saml_idp/attributeable.rb +24 -0
  13. data/lib/saml_idp/configurator.rb +48 -0
  14. data/lib/saml_idp/controller.rb +128 -0
  15. data/lib/saml_idp/default.rb +49 -0
  16. data/lib/saml_idp/encryptor.rb +86 -0
  17. data/lib/saml_idp/engine.rb +5 -0
  18. data/lib/saml_idp/hashable.rb +26 -0
  19. data/lib/saml_idp/incoming_metadata.rb +144 -0
  20. data/lib/saml_idp/logout_builder.rb +42 -0
  21. data/lib/saml_idp/logout_request_builder.rb +34 -0
  22. data/lib/saml_idp/logout_response_builder.rb +35 -0
  23. data/lib/saml_idp/metadata_builder.rb +160 -0
  24. data/lib/saml_idp/name_id_formatter.rb +68 -0
  25. data/lib/saml_idp/persisted_metadata.rb +10 -0
  26. data/lib/saml_idp/request.rb +180 -0
  27. data/lib/saml_idp/response_builder.rb +62 -0
  28. data/lib/saml_idp/saml_response.rb +79 -0
  29. data/lib/saml_idp/service_provider.rb +76 -0
  30. data/lib/saml_idp/signable.rb +131 -0
  31. data/lib/saml_idp/signature_builder.rb +42 -0
  32. data/lib/saml_idp/signed_info_builder.rb +88 -0
  33. data/lib/saml_idp/version.rb +4 -0
  34. data/lib/saml_idp/xml_security.rb +181 -0
  35. data/saml_idp.gemspec +65 -0
  36. data/spec/acceptance/acceptance_helper.rb +9 -0
  37. data/spec/acceptance/idp_controller_spec.rb +16 -0
  38. data/spec/lib/saml_idp/algorithmable_spec.rb +48 -0
  39. data/spec/lib/saml_idp/assertion_builder_spec.rb +106 -0
  40. data/spec/lib/saml_idp/attribute_decorator_spec.rb +53 -0
  41. data/spec/lib/saml_idp/configurator_spec.rb +43 -0
  42. data/spec/lib/saml_idp/controller_spec.rb +94 -0
  43. data/spec/lib/saml_idp/encryptor_spec.rb +27 -0
  44. data/spec/lib/saml_idp/logout_request_builder_spec.rb +41 -0
  45. data/spec/lib/saml_idp/logout_response_builder_spec.rb +41 -0
  46. data/spec/lib/saml_idp/metadata_builder_spec.rb +19 -0
  47. data/spec/lib/saml_idp/name_id_formatter_spec.rb +42 -0
  48. data/spec/lib/saml_idp/request_spec.rb +106 -0
  49. data/spec/lib/saml_idp/response_builder_spec.rb +42 -0
  50. data/spec/lib/saml_idp/saml_response_spec.rb +68 -0
  51. data/spec/lib/saml_idp/service_provider_spec.rb +27 -0
  52. data/spec/lib/saml_idp/signable_spec.rb +77 -0
  53. data/spec/lib/saml_idp/signature_builder_spec.rb +19 -0
  54. data/spec/lib/saml_idp/signed_info_builder_spec.rb +25 -0
  55. data/spec/rails_app/.gitignore +15 -0
  56. data/spec/rails_app/README.rdoc +261 -0
  57. data/spec/rails_app/Rakefile +7 -0
  58. data/spec/rails_app/app/assets/images/rails.png +0 -0
  59. data/spec/rails_app/app/assets/javascripts/application.js +15 -0
  60. data/spec/rails_app/app/assets/stylesheets/application.css +13 -0
  61. data/spec/rails_app/app/controllers/application_controller.rb +3 -0
  62. data/spec/rails_app/app/controllers/saml_controller.rb +8 -0
  63. data/spec/rails_app/app/controllers/saml_idp_controller.rb +11 -0
  64. data/spec/rails_app/app/helpers/application_helper.rb +2 -0
  65. data/spec/rails_app/app/mailers/.gitkeep +0 -0
  66. data/spec/rails_app/app/models/.gitkeep +0 -0
  67. data/spec/rails_app/app/views/layouts/application.html.erb +14 -0
  68. data/spec/rails_app/config.ru +4 -0
  69. data/spec/rails_app/config/application.rb +60 -0
  70. data/spec/rails_app/config/boot.rb +6 -0
  71. data/spec/rails_app/config/database.yml +25 -0
  72. data/spec/rails_app/config/environment.rb +5 -0
  73. data/spec/rails_app/config/environments/development.rb +37 -0
  74. data/spec/rails_app/config/environments/production.rb +67 -0
  75. data/spec/rails_app/config/environments/test.rb +37 -0
  76. data/spec/rails_app/config/initializers/backtrace_silencers.rb +7 -0
  77. data/spec/rails_app/config/initializers/inflections.rb +15 -0
  78. data/spec/rails_app/config/initializers/mime_types.rb +5 -0
  79. data/spec/rails_app/config/initializers/secret_token.rb +7 -0
  80. data/spec/rails_app/config/initializers/session_store.rb +8 -0
  81. data/spec/rails_app/config/initializers/wrap_parameters.rb +14 -0
  82. data/spec/rails_app/config/locales/en.yml +5 -0
  83. data/spec/rails_app/config/routes.rb +6 -0
  84. data/spec/rails_app/db/seeds.rb +7 -0
  85. data/spec/rails_app/doc/README_FOR_APP +2 -0
  86. data/spec/rails_app/lib/assets/.gitkeep +0 -0
  87. data/spec/rails_app/lib/tasks/.gitkeep +0 -0
  88. data/spec/rails_app/log/.gitkeep +0 -0
  89. data/spec/rails_app/public/404.html +26 -0
  90. data/spec/rails_app/public/422.html +26 -0
  91. data/spec/rails_app/public/500.html +25 -0
  92. data/spec/rails_app/public/favicon.ico +0 -0
  93. data/spec/rails_app/public/index.html +241 -0
  94. data/spec/rails_app/public/robots.txt +5 -0
  95. data/spec/rails_app/script/rails +6 -0
  96. data/spec/rails_app/test/fixtures/.gitkeep +0 -0
  97. data/spec/rails_app/test/functional/.gitkeep +0 -0
  98. data/spec/rails_app/test/integration/.gitkeep +0 -0
  99. data/spec/rails_app/test/performance/browsing_test.rb +12 -0
  100. data/spec/rails_app/test/test_helper.rb +13 -0
  101. data/spec/rails_app/test/unit/.gitkeep +0 -0
  102. data/spec/rails_app/vendor/assets/javascripts/.gitkeep +0 -0
  103. data/spec/rails_app/vendor/assets/stylesheets/.gitkeep +0 -0
  104. data/spec/rails_app/vendor/plugins/.gitkeep +0 -0
  105. data/spec/spec_helper.rb +49 -0
  106. data/spec/support/certificates/certificate1 +12 -0
  107. data/spec/support/certificates/r1_certificate2_base64 +1 -0
  108. data/spec/support/responses/adfs_response_sha1.xml +46 -0
  109. data/spec/support/responses/adfs_response_sha256.xml +46 -0
  110. data/spec/support/responses/adfs_response_sha384.xml +46 -0
  111. data/spec/support/responses/adfs_response_sha512.xml +46 -0
  112. data/spec/support/responses/logoutresponse_fixtures.rb +67 -0
  113. data/spec/support/responses/no_signature_ns.xml +48 -0
  114. data/spec/support/responses/open_saml_response.xml +56 -0
  115. data/spec/support/responses/r1_response6.xml.base64 +1 -0
  116. data/spec/support/responses/response1.xml.base64 +1 -0
  117. data/spec/support/responses/response2.xml.base64 +79 -0
  118. data/spec/support/responses/response3.xml.base64 +66 -0
  119. data/spec/support/responses/response4.xml.base64 +93 -0
  120. data/spec/support/responses/response5.xml.base64 +102 -0
  121. data/spec/support/responses/response_with_ampersands.xml +139 -0
  122. data/spec/support/responses/response_with_ampersands.xml.base64 +93 -0
  123. data/spec/support/responses/simple_saml_php.xml +71 -0
  124. data/spec/support/responses/starfield_response.xml.base64 +1 -0
  125. data/spec/support/responses/wrapped_response_2.xml.base64 +150 -0
  126. data/spec/support/saml_request_macros.rb +38 -0
  127. data/spec/support/security_helpers.rb +61 -0
  128. data/spec/xml_security_spec.rb +137 -0
  129. metadata +465 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ea7921102fe43bfbba0086ee40cfd65f7783e1ad
4
+ data.tar.gz: 542bc9cc6358ccb222f47a164506354afa70e0ab
5
+ SHA512:
6
+ metadata.gz: 0602eb253d25f4dac6106ff2dc1f2a8ebd2eb4cab128d4ec588ce1e528427374d7a8f44d44d888266548f3c035ecc44eb735cb6e16e83be3d3cccfdc9a2d30df
7
+ data.tar.gz: 10aa55f5cdc46f505910a8fcb1b86c4a843ec046be75d33ca29ea3baacb4cea1e3b1bb8518120fc22079a19f7365bfc86d47675bcd75927c673386c56905169a
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Sport Ngin (http://sportngin.com)
2
+ Portions Copyright (c) 2010 OneLogin, LLC
3
+ Portions Copyright (c) 2012 Lawrence Pit (http://lawrencepit.com)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,238 @@
1
+ # Ruby SAML Identity Provider (IdP)
2
+ Forked from https://github.com/lawrencepit/ruby-saml-idp
3
+
4
+ [![Build Status](https://travis-ci.org/sportngin/saml_idp.png)](https://travis-ci.org/sportngin/saml_idp)
5
+ [![Gem Version](https://badge.fury.io/rb/saml_idp.png)](http://badge.fury.io/rb/saml_idp)
6
+
7
+ The ruby SAML Identity Provider library is for implementing the server side of SAML authentication. It allows
8
+ your application to act as an IdP (Identity Provider) using the
9
+ [SAML v2.0](http://en.wikipedia.org/wiki/Security_Assertion_Markup_Language)
10
+ protocol. It provides a means for managing authentication requests and confirmation responses for SPs (Service Providers).
11
+
12
+ This was originally setup by @lawrencepit to test SAML Clients. I took it closer to a real
13
+ SAML IDP implementation.
14
+
15
+ # Installation and Usage
16
+
17
+ Add this to your Gemfile:
18
+
19
+ gem 'saml_idp'
20
+
21
+ ## Not using rails?
22
+ Include `SamlIdp::Controller` and see the examples that use rails. It should be straightforward for you.
23
+
24
+ Basically you call `decode_request(params[:SAMLRequest])` on an incoming request and then use the value
25
+ `saml_acs_url` to determine the source for which you need to authenticate a user. How you authenticate
26
+ a user is entirely up to you.
27
+
28
+ Once a user has successfully authenticated on your system send the Service Provider a SAMLReponse by
29
+ posting to `saml_acs_url` the parameter `SAMLResponse` with the return value from a call to
30
+ `encode_response(user_email)`.
31
+
32
+ ## Using rails?
33
+ Add to your `routes.rb` file, for example:
34
+
35
+ ``` ruby
36
+ get '/saml/auth' => 'saml_idp#new'
37
+ get '/saml/metadata' => 'saml_idp#show'
38
+ post '/saml/auth' => 'saml_idp#create'
39
+ match '/saml/logout' => 'saml_idp#logout', via: [:get, :post, :delete]
40
+ ```
41
+
42
+ Create a controller that looks like this, customize to your own situation:
43
+
44
+ ``` ruby
45
+ class SamlIdpController
46
+ include SamlIdp::IdpController
47
+
48
+ def idp_authenticate(email, password) # not using params intentionally
49
+ user = User.by_email(email).first
50
+ user && user.valid_password?(password) ? user : nil
51
+ end
52
+ private :idp_authenticate
53
+
54
+ def idp_make_saml_response(found_user) # not using params intentionally
55
+ # NOTE encryption is optional
56
+ encode_response found_user, encryption: {
57
+ cert: saml_request.service_provider.cert,
58
+ block_encryption: 'aes256-cbc',
59
+ key_transport: 'rsa-oaep-mgf1p'
60
+ }
61
+ end
62
+ private :idp_make_saml_response
63
+
64
+ def idp_logout
65
+ user = User.by_email(saml_request.name_id)
66
+ user.logout
67
+ end
68
+ private :idp_logout
69
+ end
70
+ ```
71
+
72
+ ## Configuration
73
+
74
+ Be sure to load a file like this during your app initialization:
75
+
76
+ ```ruby
77
+ SamlIdp.configure do |config|
78
+ base = "http://example.com"
79
+
80
+ config.x509_certificate = <<-CERT
81
+ -----BEGIN CERTIFICATE-----
82
+ CERTIFICATE DATA
83
+ -----END CERTIFICATE-----
84
+ CERT
85
+
86
+ config.secret_key = <<-CERT
87
+ -----BEGIN RSA PRIVATE KEY-----
88
+ KEY DATA
89
+ -----END RSA PRIVATE KEY-----
90
+ CERT
91
+
92
+ # config.password = "secret_key_password"
93
+ # config.algorithm = :sha256
94
+ # config.organization_name = "Your Organization"
95
+ # config.organization_url = "http://example.com"
96
+ # config.base_saml_location = "#{base}/saml"
97
+ # config.reference_id_generator # Default: -> { UUID.generate }
98
+ # config.attribute_service_location = "#{base}/saml/attributes"
99
+ # config.single_service_post_location = "#{base}/saml/auth"
100
+
101
+ # Principal (e.g. User) is passed in when you `encode_response`
102
+ #
103
+ # config.name_id.formats # =>
104
+ # { # All 2.0
105
+ # email_address: -> (principal) { principal.email_address },
106
+ # transient: -> (principal) { principal.id },
107
+ # persistent: -> (p) { p.id },
108
+ # }
109
+ # OR
110
+ #
111
+ # {
112
+ # "1.1" => {
113
+ # email_address: -> (principal) { principal.email_address },
114
+ # },
115
+ # "2.0" => {
116
+ # transient: -> (principal) { principal.email_address },
117
+ # persistent: -> (p) { p.id },
118
+ # },
119
+ # }
120
+
121
+ # If Principal responds to a method called `asserted_attributes`
122
+ # the return value of that method will be used in lieu of the
123
+ # attributes defined here in the global space. This allows for
124
+ # per-user attribute definitions.
125
+ #
126
+ ## EXAMPLE **
127
+ # class User
128
+ # def asserted_attributes
129
+ # {
130
+ # phone: { getter: :phone },
131
+ # email: {
132
+ # getter: :email,
133
+ # name_format: Saml::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS,
134
+ # name_id_format: Saml::XML::Namespaces::Formats::NameId::EMAIL_ADDRESS
135
+ # }
136
+ # }
137
+ # end
138
+ # end
139
+ #
140
+ # If you have a method called `asserted_attributes` in your Principal class,
141
+ # there is no need to define it here in the config.
142
+
143
+ # config.attributes # =>
144
+ # {
145
+ # <friendly_name> => { # required (ex "eduPersonAffiliation")
146
+ # "name" => <attrname> # required (ex "urn:oid:1.3.6.1.4.1.5923.1.1.1.1")
147
+ # "name_format" => "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", # not required
148
+ # "getter" => ->(principal) { # not required
149
+ # principal.get_eduPersonAffiliation # If no "getter" defined, will try
150
+ # } # `principal.eduPersonAffiliation`, or no values will
151
+ # } # be output
152
+ #
153
+ ## EXAMPLE ##
154
+ # config.attributes = {
155
+ # GivenName: {
156
+ # getter: :first_name,
157
+ # },
158
+ # SurName: {
159
+ # getter: :last_name,
160
+ # },
161
+ # }
162
+ ## EXAMPLE ##
163
+
164
+ # config.technical_contact.company = "Example"
165
+ # config.technical_contact.given_name = "Jonny"
166
+ # config.technical_contact.sur_name = "Support"
167
+ # config.technical_contact.telephone = "55555555555"
168
+ # config.technical_contact.email_address = "example@example.com"
169
+
170
+ service_providers = {
171
+ "some-issuer-url.com/saml" => {
172
+ fingerprint: "9E:65:2E:03:06:8D:80:F2:86:C7:6C:77:A1:D9:14:97:0A:4D:F4:4D",
173
+ metadata_url: "http://some-issuer-url.com/saml/metadata"
174
+ },
175
+ }
176
+
177
+ # `identifier` is the entity_id or issuer of the Service Provider,
178
+ # settings is an IncomingMetadata object which has a to_h method that needs to be persisted
179
+ config.service_provider.metadata_persister = ->(identifier, settings) {
180
+ fname = identifier.to_s.gsub(/\/|:/,"_")
181
+ `mkdir -p #{Rails.root.join("cache/saml/metadata")}`
182
+ File.open Rails.root.join("cache/saml/metadata/#{fname}"), "r+b" do |f|
183
+ Marshal.dump settings.to_h, f
184
+ end
185
+ }
186
+
187
+ # `identifier` is the entity_id or issuer of the Service Provider,
188
+ # `service_provider` is a ServiceProvider object. Based on the `identifier` or the
189
+ # `service_provider` you should return the settings.to_h from above
190
+ config.service_provider.persisted_metadata_getter = ->(identifier, service_provider){
191
+ fname = identifier.to_s.gsub(/\/|:/,"_")
192
+ `mkdir -p #{Rails.root.join("cache/saml/metadata")}`
193
+ full_filename = Rails.root.join("cache/saml/metadata/#{fname}")
194
+ if File.file?(full_filename)
195
+ File.open full_filename, "rb" do |f|
196
+ Marshal.load f
197
+ end
198
+ end
199
+ }
200
+
201
+ # Find ServiceProvider metadata_url and fingerprint based on our settings
202
+ config.service_provider.finder = ->(issuer_or_entity_id) do
203
+ service_providers[issuer_or_entity_id]
204
+ end
205
+ end
206
+ ```
207
+
208
+ # Keys and Secrets
209
+ To generate the SAML Response it uses a default X.509 certificate and secret key... which isn't so secret.
210
+ You can find them in `SamlIdp::Default`. The X.509 certificate is valid until year 2032.
211
+ Obviously you shouldn't use these if you intend to use this in production environments. In that case,
212
+ within the controller set the properties `x509_certificate` and `secret_key` using a `prepend_before_filter`
213
+ callback within the current request context or set them globally via the `SamlIdp.config.x509_certificate`
214
+ and `SamlIdp.config.secret_key` properties.
215
+
216
+ The fingerprint to use, if you use the default X.509 certificate of this gem, is:
217
+
218
+ ```
219
+ 9E:65:2E:03:06:8D:80:F2:86:C7:6C:77:A1:D9:14:97:0A:4D:F4:4D
220
+ ```
221
+
222
+
223
+ # Service Providers
224
+ To act as a Service Provider which generates SAML Requests and can react to SAML Responses use the
225
+ excellent [ruby-saml](https://github.com/onelogin/ruby-saml) gem.
226
+
227
+
228
+ # Author
229
+ Jon Phenow, me@jphenow.com
230
+
231
+ Lawrence Pit, lawrence.pit@gmail.com, lawrencepit.com, @lawrencepit
232
+
233
+ # Copyright
234
+ Copyright (c) 2012 Sport Ngin.
235
+ Portions Copyright (c) 2010 OneLogin, LLC
236
+ Portions Copyright (c) 2012 Lawrence Pit (http://lawrencepit.com)
237
+
238
+ See LICENSE for details.
@@ -0,0 +1,53 @@
1
+ # encoding: utf-8
2
+ module SamlIdp
3
+ class IdpController < ActionController::Base
4
+ include SamlIdp::Controller
5
+
6
+ unloadable unless Rails::VERSION::MAJOR >= 4
7
+ protect_from_forgery
8
+ before_filter :validate_saml_request, only: [:new, :create]
9
+
10
+ def new
11
+ render template: "saml_idp/idp/new"
12
+ end
13
+
14
+ def show
15
+ render xml: SamlIdp.metadata.signed
16
+ end
17
+
18
+ def create
19
+ unless params[:email].blank? && params[:password].blank?
20
+ person = idp_authenticate(params[:email], params[:password])
21
+ if person.nil?
22
+ @saml_idp_fail_msg = "Incorrect email or password."
23
+ else
24
+ @saml_response = idp_make_saml_response(person)
25
+ render :template => "saml_idp/idp/saml_post", :layout => false
26
+ return
27
+ end
28
+ end
29
+ render :template => "saml_idp/idp/new"
30
+ end
31
+
32
+ def logout
33
+ idp_logout
34
+ @saml_response = idp_make_saml_response(nil)
35
+ render :template => "saml_idp/idp/saml_post", :layout => false
36
+ end
37
+
38
+ def idp_logout
39
+ raise NotImplementedError
40
+ end
41
+ private :idp_logout
42
+
43
+ def idp_authenticate(email, password)
44
+ raise NotImplementedError
45
+ end
46
+ protected :idp_authenticate
47
+
48
+ def idp_make_saml_response(person)
49
+ raise NotImplementedError
50
+ end
51
+ protected :idp_make_saml_response
52
+ end
53
+ end
@@ -0,0 +1,22 @@
1
+ <% if @saml_idp_fail_msg %>
2
+ <div id="saml_idp_fail_msg" class="flash error"><%= @saml_idp_fail_msg %></div>
3
+ <% end %>
4
+
5
+ <%= form_tag do %>
6
+ <%= hidden_field_tag("SAMLRequest", params[:SAMLRequest]) %>
7
+ <%= hidden_field_tag("RelayState", params[:RelayState]) %>
8
+
9
+ <p>
10
+ <%= label_tag :email %>
11
+ <%= email_field_tag :email, params[:email], :autocapitalize => "off", :autocorrect => "off", :autofocus => "autofocus", :spellcheck => "false", :size => 30, :class => "email_pwd txt" %>
12
+ </p>
13
+
14
+ <p>
15
+ <%= label_tag :password %>
16
+ <%= password_field_tag :password, params[:password], :autocapitalize => "off", :autocorrect => "off", :spellcheck => "false", :size => 30, :class => "email_pwd txt" %>
17
+ </p>
18
+
19
+ <p>
20
+ <%= submit_tag "Sign in", :class => "button big blueish" %>
21
+ </p>
22
+ <% end %>
@@ -0,0 +1,14 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
6
+ </head>
7
+ <body onload="document.forms[0].submit();" style="visibility:hidden;">
8
+ <%= form_tag(saml_acs_url) do %>
9
+ <%= hidden_field_tag("SAMLResponse", @saml_response) %>
10
+ <%= hidden_field_tag("RelayState", params[:RelayState]) %>
11
+ <%= submit_tag "Submit" %>
12
+ <% end %>
13
+ </body>
14
+ </html>
@@ -0,0 +1,92 @@
1
+ # encoding: utf-8
2
+ module SamlIdp
3
+ require 'active_support/all'
4
+ require 'saml_idp/saml_response'
5
+ require 'saml_idp/xml_security'
6
+ require 'saml_idp/configurator'
7
+ require 'saml_idp/controller'
8
+ require 'saml_idp/default'
9
+ require 'saml_idp/metadata_builder'
10
+ require 'saml_idp/version'
11
+ require 'saml_idp/engine' if defined?(::Rails) && Rails::VERSION::MAJOR > 2
12
+
13
+ def self.config
14
+ @config ||= SamlIdp::Configurator.new
15
+ end
16
+
17
+ def self.configure
18
+ yield config
19
+ end
20
+
21
+ def self.metadata
22
+ @metadata ||= MetadataBuilder.new(config)
23
+ end
24
+ end
25
+
26
+ # TODO Needs extraction out
27
+ module Saml
28
+ module XML
29
+ module Namespaces
30
+ METADATA = "urn:oasis:names:tc:SAML:2.0:metadata"
31
+ ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
32
+ SIGNATURE = "http://www.w3.org/2000/09/xmldsig#"
33
+ PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
34
+
35
+ module Statuses
36
+ SUCCESS = "urn:oasis:names:tc:SAML:2.0:status:Success"
37
+ end
38
+
39
+ module Consents
40
+ UNSPECIFIED = "urn:oasis:names:tc:SAML:2.0:consent:unspecified"
41
+ end
42
+
43
+ module AuthnContext
44
+ module ClassRef
45
+ PASSWORD = "urn:oasis:names:tc:SAML:2.0:ac:classes:Password"
46
+ PASSWORD_PROTECTED = "urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"
47
+ end
48
+ end
49
+
50
+ module Methods
51
+ BEARER = "urn:oasis:names:tc:SAML:2.0:cm:bearer"
52
+ end
53
+
54
+ module Formats
55
+ module Attr
56
+ URI = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
57
+ end
58
+
59
+ module NameId
60
+ EMAIL_ADDRESS = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
61
+ TRANSIENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
62
+ PERSISTENT = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent"
63
+ end
64
+ end
65
+ end
66
+
67
+ class Document < Nokogiri::XML::Document
68
+ def signed?
69
+ !!xpath("//ds:Signature", ds: signature_namespace).first
70
+ end
71
+
72
+ def valid_signature?(fingerprint)
73
+ signed? &&
74
+ signed_document.validate(fingerprint, :soft)
75
+ end
76
+
77
+ def signed_document
78
+ SamlIdp::XMLSecurity::SignedDocument.new(to_xml)
79
+ end
80
+
81
+ def signature_namespace
82
+ Namespaces::SIGNATURE
83
+ end
84
+
85
+ def to_xml
86
+ super(
87
+ save_with: Nokogiri::XML::Node::SaveOptions::AS_XML | Nokogiri::XML::Node::SaveOptions::NO_DECLARATION
88
+ ).strip
89
+ end
90
+ end
91
+ end
92
+ end