omniauth-wsfed 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ # Rubymine
2
+ .idea
3
+
4
+ #RVM
5
+ .rvmrc
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in omniauth-wsfed.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,43 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ omniauth-wsfed (0.1.0)
5
+ omniauth (~> 1.1.0)
6
+ typhoeus (~> 0.4.2)
7
+ xmlcanonicalizer (= 0.1.1)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ diff-lcs (1.1.3)
13
+ ffi (1.1.0)
14
+ hashie (1.2.0)
15
+ mime-types (1.19)
16
+ omniauth (1.1.0)
17
+ hashie (~> 1.2)
18
+ rack
19
+ rack (1.4.1)
20
+ rack-test (0.6.1)
21
+ rack (>= 1.0)
22
+ rake (0.9.2.2)
23
+ rspec (2.10.0)
24
+ rspec-core (~> 2.10.0)
25
+ rspec-expectations (~> 2.10.0)
26
+ rspec-mocks (~> 2.10.0)
27
+ rspec-core (2.10.1)
28
+ rspec-expectations (2.10.0)
29
+ diff-lcs (~> 1.1.3)
30
+ rspec-mocks (2.10.1)
31
+ typhoeus (0.4.2)
32
+ ffi (~> 1.0)
33
+ mime-types (~> 1.18)
34
+ xmlcanonicalizer (0.1.1)
35
+
36
+ PLATFORMS
37
+ ruby
38
+
39
+ DEPENDENCIES
40
+ omniauth-wsfed!
41
+ rack-test (~> 0.6.1)
42
+ rake (~> 0.9.2)
43
+ rspec (~> 2.10.0)
data/LICENSE ADDED
@@ -0,0 +1,24 @@
1
+ Copyright (c) 2011-2012 Keith Beckman, http://www.coding4streetcred.com/blog
2
+ All rights reserved. Released under the MIT license.
3
+
4
+ Portions Copyright (c) 2007 Sun Microsystems Inc.
5
+
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining
8
+ a copy of this software and associated documentation files (the
9
+ "Software"), to deal in the Software without restriction, including
10
+ without limitation the rights to use, copy, modify, merge, publish,
11
+ distribute, sublicense, and/or sell copies of the Software, and to
12
+ permit persons to whom the Software is furnished to do so, subject to
13
+ the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,131 @@
1
+ # OmniAuth WS-Fed #
2
+
3
+ #### This gem is currently under construction... Expect an official v1 release by the the end of July 2012. ####
4
+
5
+ The OmniAuth-WSFed authentication strategy can be used with the following technologies
6
+ under scenarios requiring the [WS-Federation protocol](http://msdn.microsoft.com/en-us/library/bb498017.aspx)
7
+ for authentication. These services are typically used for Identity Federation and Single
8
+ Sign-On across large organizations or authentication domains.
9
+
10
+ * [Windows Azure ACS](http://msdn.microsoft.com/en-us/library/windowsazure/gg429786.aspx)
11
+ * [ADFS 2.0](http://msdn.microsoft.com/en-us/magazine/ee335705.aspx)
12
+ * Corporate Secure Token Servers (STSs)
13
+
14
+
15
+ ## Installation ##
16
+
17
+ Add this line to your application's Gemfile:
18
+ ```ruby
19
+ gem 'omniauth-wsfed'
20
+ ```
21
+
22
+ And then execute:
23
+
24
+ $ bundle install
25
+
26
+ Or install it globally as:
27
+
28
+ $ gem install omniauth-wsfed
29
+
30
+
31
+ ## Configuration ##
32
+
33
+ Use the WSFed strategy as a middleware in your application:
34
+
35
+ ```ruby
36
+ require 'omniauth'
37
+
38
+ use OmniAuth::Strategies::WSFed,
39
+ :issuer_name => "http://your-azure-acs-namespace.accesscontrol.windows.net",
40
+ :issuer => "https://your-azure-acs-namespace.accesscontrol.windows.net/v2/wsfederation",
41
+ :realm => "http://my.relyingparty/realm",
42
+ :reply => "http://localhost:3000/auth/wsfed/callback",
43
+ :id_claim => "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
44
+ :idp_cert_fingerprint => "FC96D2983…"
45
+ ```
46
+
47
+ or in your Rails application:
48
+
49
+ in `Gemfile`:
50
+
51
+ ```ruby
52
+ gem 'omniauth-wsfed'
53
+ ```
54
+
55
+ and in `config/initializers/omniauth.rb`:
56
+
57
+ ```ruby
58
+ Rails.application.config.middleware.use OmniAuth::Builder do
59
+
60
+ provider :wsfed,
61
+ :issuer_name => "http://your-azure-acs-namespace.accesscontrol.windows.net",
62
+ :issuer => "https://your-azure-acs-namespace.accesscontrol.windows.net/v2/wsfederation",
63
+ :realm => "http://my.relyingparty/realm",
64
+ :reply => "http://localhost:3000/auth/wsfed/callback",
65
+ :id_claim => "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
66
+ :idp_cert_fingerprint => "FC96D2983…"
67
+
68
+ end
69
+ ```
70
+
71
+
72
+ ## Configuration Options ##
73
+
74
+ * `:issuer_name` - The name of your Identity Provider (IdP). This option is not required,
75
+ but can be a nice way to differentiate your IdP configurations if you are testing with
76
+ multiple providers in multiple enviornments. **Optional**
77
+
78
+ * `:issuer` - The IdP web endpoint (URL) to which the authentication request should be
79
+ sent. **Required**.
80
+
81
+ * `:idp_cert_fingerprint` - The SHA1 fingerprint of the IdP's signing certificate
82
+ (e.g. "90:CC:16:F0:8D:…"). This is provided by the IdP when setting up the trust
83
+ relationship. This option or `:idp_cert` must be present.
84
+
85
+ * `:idp_cert` - The IdP's certificate in PEM format. This option or
86
+ `:idp_cert_fingerprint` must be present.
87
+
88
+ * `:realm` - Your site's security realm. This is a URI defining the realm to which the
89
+ IdP must issue a secure token. **Required**
90
+
91
+ * `:reply` - The reply-to URL in your application for which a WSFed response should be
92
+ posted. **Required**
93
+
94
+ * `:id_claim` - Name of the authentication claim that you want to use as OmniAuth's
95
+ **uid** property.
96
+
97
+
98
+ ## Authors and Credits ##
99
+
100
+ Authored by [Keith Beckman](https://github.com/kbeckman).
101
+
102
+ Special thanks to the developers of the following projects from which I borrowed from for omniauth-wsfed:
103
+
104
+ * [PracticallyGreen / omniauth-saml](https://github.com/PracticallyGreen/omniauth-saml)
105
+ * [onelogin / ruby-saml](https://github.com/onelogin/ruby-saml)
106
+
107
+
108
+ ## License ##
109
+
110
+ Copyright (c) 2011-2012 Keith Beckman, [Coding4StreetCred.com](http://www.coding4streetcred.com/blog)
111
+ All rights reserved. Released under the MIT license.
112
+
113
+ Portions Copyright (c) 2007 Sun Microsystems Inc.
114
+
115
+ Permission is hereby granted, free of charge, to any person obtaining a copy
116
+ of this software and associated documentation files (the "Software"), to deal
117
+ in the Software without restriction, including without limitation the rights
118
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
119
+ copies of the Software, and to permit persons to whom the Software is
120
+ furnished to do so, subject to the following conditions:
121
+
122
+ The above copyright notice and this permission notice shall be included in
123
+ all copies or substantial portions of the Software.
124
+
125
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
126
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
127
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
128
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
129
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
130
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
131
+ THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,16 @@
1
+ module AzureACS
2
+
3
+ class IdPFeed
4
+
5
+ def initialize(idp_json_feed_url)
6
+ raise ArgumentError.new("Azure ACS JSON feed URL cannot be null.") if idp_json_feed_url.nil?
7
+ @json_feed_url = idp_json_feed_url
8
+ end
9
+
10
+ def identity_providers
11
+ @json_feed ||= Typhoeus::Request.get(@json_feed_url).body
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,32 @@
1
+ require 'erb'
2
+
3
+ module OmniAuth
4
+ module Strategies
5
+ class WSFed
6
+
7
+ class AuthRequest
8
+ include ERB::Util
9
+
10
+ SIGNIN_PARAM = 'wsignin1.0'
11
+
12
+ def create (settings, args = {})
13
+ wa = SIGNIN_PARAM
14
+ wtrealm = url_encode(settings[:realm])
15
+ wreply = url_encode(settings[:reply])
16
+ wct = url_encode(Time.now.utc)
17
+ whr = url_encode(args[:whr])
18
+
19
+ query_string = "?wa=#{wa}&wtrealm=#{wtrealm}&wreply=#{wreply}&wctx=#{}&wct=#{wct}"
20
+
21
+ unless whr.nil? or whr.empty?
22
+ query_string = "#{query_string}&whr=#{whr}"
23
+ end
24
+
25
+ settings[:issuer] + query_string
26
+ end
27
+
28
+ end
29
+
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,159 @@
1
+ require "time"
2
+ require "hashie"
3
+
4
+ module OmniAuth
5
+ module Strategies
6
+ class WSFed
7
+
8
+ class AuthResponse
9
+
10
+ ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
11
+ PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
12
+ DSIG = "http://www.w3.org/2000/09/xmldsig#"
13
+
14
+ attr_accessor :options, :response, :document, :settings
15
+
16
+ def initialize(response, settings, options = {})
17
+ raise ArgumentError.new("Response cannot be nil.") if response.nil?
18
+ raise ArgumentError.new("WSFed settings cannot be nil.") if settings.nil?
19
+
20
+ self.options = options
21
+ self.response = response
22
+ self.settings = settings
23
+ self.document = OmniAuth::Strategies::WSFed::XMLSecurity::SignedDocument.new(response)
24
+ end
25
+
26
+ def valid?
27
+ validate(soft = true)
28
+ end
29
+
30
+ def validate!
31
+ validate(soft = false)
32
+ end
33
+
34
+ # The value of the user identifier as defined by the id_claim setting...
35
+ def name_id
36
+ @name_id ||= begin
37
+ attributes.has_key?(settings[:id_claim]) ? attributes.fetch(settings[:id_claim]) : nil
38
+ end
39
+ end
40
+
41
+ # A hash of all the claims provided by the response.
42
+ def attributes
43
+ @attr_statements ||= begin
44
+ stmt_element = REXML::XPath.first(document, "//Assertion/AttributeStatement")
45
+ return {} if stmt_element.nil?
46
+
47
+ {}.tap do |result|
48
+ stmt_element.elements.each do |attr_element|
49
+ name = attr_element.attributes["Name"]
50
+
51
+ if attr_element.elements.count > 1
52
+ value = []
53
+ attr_element.elements.each { |element| value << element.text }
54
+ else
55
+ value = attr_element.elements.first.text.lstrip.rstrip
56
+ end
57
+
58
+ result[name] = value
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ # When this user session should expire at latest
65
+ def session_expires_at
66
+ @expires_at ||= begin
67
+ node = xpath("/p:Response/a:Assertion/a:AuthnStatement")
68
+ parse_time(node, "SessionNotOnOrAfter")
69
+ end
70
+ end
71
+
72
+ # Conditions (if any) for the assertion to run
73
+ def conditions
74
+ @conditions ||= begin
75
+ xpath("/p:Response/a:Assertion[@ID='#{signed_element_id}']/a:Conditions")
76
+ end
77
+ end
78
+
79
+ private
80
+
81
+ def validation_error(message)
82
+ raise OmniAuth::Strategies::WSFed::ValidationError.new(message)
83
+ end
84
+
85
+ def validate(soft = true)
86
+ validate_response_state(soft) &&
87
+ validate_conditions(soft) &&
88
+ document.validate(get_fingerprint, soft)
89
+ end
90
+
91
+ def validate_response_state(soft = true)
92
+ if response.empty?
93
+ return soft ? false : validation_error("Blank response")
94
+ end
95
+
96
+ if settings.nil?
97
+ return soft ? false : validation_error("No settings on response")
98
+ end
99
+
100
+ if settings[:idp_cert_fingerprint].nil? && settings[:idp_cert].nil?
101
+ return soft ? false : validation_error("No fingerprint or certificate on settings")
102
+ end
103
+
104
+ true
105
+ end
106
+
107
+ def get_fingerprint
108
+ if settings[:idp_cert_fingerprint]
109
+ settings[:idp_cert_fingerprint]
110
+ else
111
+ cert = OpenSSL::X509::Certificate.new(settings[:idp_cert].gsub(/^ +/, ''))
112
+ Digest::SHA1.hexdigest(cert.to_der).upcase.scan(/../).join(":")
113
+ end
114
+ end
115
+
116
+ def validate_conditions(soft = true)
117
+ return true if conditions.nil?
118
+ return true if options[:skip_conditions]
119
+
120
+ if not_before = parse_time(conditions, "NotBefore")
121
+ if Time.now.utc < not_before
122
+ return soft ? false : validation_error("Current time is earlier than NotBefore condition")
123
+ end
124
+ end
125
+
126
+ if not_on_or_after = parse_time(conditions, "NotOnOrAfter")
127
+ if Time.now.utc >= not_on_or_after
128
+ return soft ? false : validation_error("Current time is on or after NotOnOrAfter condition")
129
+ end
130
+ end
131
+
132
+ true
133
+ end
134
+
135
+ def parse_time(node, attribute)
136
+ if node && node.attributes[attribute]
137
+ Time.parse(node.attributes[attribute])
138
+ end
139
+ end
140
+
141
+ #def strip(string)
142
+ # return string unless string
143
+ # string.gsub(/^\s+/, '').gsub(/\s+$/, '')
144
+ #end
145
+
146
+ def xpath(path)
147
+ #REXML::XPath.first(document, path, { "p" => PROTOCOL, "a" => ASSERTION })
148
+ REXML::XPath.first(document, path, { "saml" => ASSERTION })
149
+ end
150
+
151
+ def signed_element_id
152
+ doc_id = document.signed_element_id
153
+ doc_id[1, doc_id.size]
154
+ end
155
+ end
156
+
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,10 @@
1
+ module OmniAuth
2
+ module Strategies
3
+ class WSFed
4
+
5
+ class ValidationError < OmniAuth::Error
6
+ end
7
+
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,149 @@
1
+ # The contents of this file are subject to the terms
2
+ # of the Common Development and Distribution License
3
+ # (the License). You may not use this file except in
4
+ # compliance with the License.
5
+ #
6
+ # You can obtain a copy of the License at
7
+ # https://opensso.dev.java.net/public/CDDLv1.0.html or
8
+ # opensso/legal/CDDLv1.0.txt
9
+ # See the License for the specific language governing
10
+ # permission and limitations under the License.
11
+ #
12
+ # When distributing Covered Code, include this CDDL
13
+ # Header Notice in each file and include the License file
14
+ # at opensso/legal/CDDLv1.0.txt.
15
+ # If applicable, add the following below the CDDL Header,
16
+ # with the fields enclosed by brackets [] replaced by
17
+ # your own identifying information:
18
+ # "Portions Copyrighted [year] [name of copyright owner]"
19
+ #
20
+ # $Id: xml_sec.rb,v 1.6 2007/10/24 00:28:41 todddd Exp $
21
+ #
22
+ # Copyright 2007 Sun Microsystems Inc. All Rights Reserved
23
+ # Portions Copyrighted 2007 Todd W Saxton.
24
+
25
+ require 'rubygems'
26
+ require "rexml/document"
27
+ require "rexml/xpath"
28
+ require "openssl"
29
+ require "xmlcanonicalizer"
30
+ require "digest/sha1"
31
+ require "digest/sha2"
32
+
33
+ module OmniAuth
34
+ module Strategies
35
+ class WSFed
36
+
37
+ module XMLSecurity
38
+
39
+ class SignedDocument < REXML::Document
40
+ DSIG = "http://www.w3.org/2000/09/xmldsig#"
41
+
42
+ attr_accessor :signed_element_id
43
+
44
+ def initialize(response)
45
+ super(response)
46
+ extract_signed_element_id
47
+ end
48
+
49
+ def validate(idp_cert_fingerprint, soft = true)
50
+ # get cert from response
51
+ base64_cert = self.elements["//ds:X509Certificate"].text
52
+ cert_text = Base64.decode64(base64_cert)
53
+ cert = OpenSSL::X509::Certificate.new(cert_text)
54
+
55
+ # check cert matches registered idp cert
56
+ fingerprint = Digest::SHA1.hexdigest(cert.to_der)
57
+
58
+ if fingerprint != idp_cert_fingerprint.gsub(/[^a-zA-Z0-9]/,"").downcase
59
+ return soft ? false : (raise OmniAuth::Strategies::WSFed::ValidationError.new("Fingerprint mismatch"))
60
+ end
61
+
62
+ validate_doc(base64_cert, soft)
63
+ end
64
+
65
+ def validate_doc(base64_cert, soft = true)
66
+ # validate references
67
+
68
+ # check for inclusive namespaces
69
+
70
+ inclusive_namespaces = []
71
+ inclusive_namespace_element = REXML::XPath.first(self, "//ec:InclusiveNamespaces")
72
+
73
+ if inclusive_namespace_element
74
+ prefix_list = inclusive_namespace_element.attributes.get_attribute('PrefixList').value
75
+ inclusive_namespaces = prefix_list.split(" ")
76
+ end
77
+
78
+ # remove signature node
79
+ sig_element = REXML::XPath.first(self, "//ds:Signature", {"ds"=>DSIG})
80
+ sig_element.remove
81
+
82
+ # check digests
83
+ REXML::XPath.each(sig_element, "//ds:Reference", {"ds"=>DSIG}) do |ref|
84
+ uri = ref.attributes.get_attribute("URI").value
85
+ hashed_element = REXML::XPath.first(self, "//[@ID='#{uri[1,uri.size]}']")
86
+ canoner = XML::Util::XmlCanonicalizer.new(false, true)
87
+ canoner.inclusive_namespaces = inclusive_namespaces if canoner.respond_to?(:inclusive_namespaces) && !inclusive_namespaces.empty?
88
+ canon_hashed_element = canoner.canonicalize(hashed_element)
89
+ digest_algorithm = algorithm(REXML::XPath.first(ref, "//ds:DigestMethod"))
90
+ hash = Base64.encode64(digest_algorithm.digest(canon_hashed_element)).chomp
91
+ digest_value = REXML::XPath.first(ref, "//ds:DigestValue", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"}).text
92
+
93
+ unless digests_match?(hash, digest_value)
94
+ return soft ? false : (raise OmniAuth::Strategies::WSFed::ValidationError.new("Digest mismatch"))
95
+ end
96
+ end
97
+
98
+ # verify signature
99
+ canoner = XML::Util::XmlCanonicalizer.new(false, true)
100
+ signed_info_element = REXML::XPath.first(sig_element, "//ds:SignedInfo", {"ds"=>DSIG})
101
+ canon_string = canoner.canonicalize(signed_info_element)
102
+
103
+ base64_signature = REXML::XPath.first(sig_element, "//ds:SignatureValue", {"ds"=>DSIG}).text
104
+ signature = Base64.decode64(base64_signature)
105
+
106
+ # get certificate object
107
+ cert_text = Base64.decode64(base64_cert)
108
+ cert = OpenSSL::X509::Certificate.new(cert_text)
109
+
110
+ # signature method
111
+ signature_algorithm = algorithm(REXML::XPath.first(signed_info_element, "//ds:SignatureMethod", {"ds"=>DSIG}))
112
+
113
+ unless cert.public_key.verify(signature_algorithm.new, signature, canon_string)
114
+ return soft ? false : (raise OmniAuth::Strategies::WSFed::ValidationError.new("Key validation error"))
115
+ end
116
+
117
+ return true
118
+ end
119
+
120
+ private
121
+
122
+ def digests_match?(hash, digest_value)
123
+ hash == digest_value
124
+ end
125
+
126
+ def extract_signed_element_id
127
+ reference_element = REXML::XPath.first(self, "//ds:Signature/ds:SignedInfo/ds:Reference", {"ds"=>DSIG})
128
+ self.signed_element_id = reference_element.attribute("URI").value unless reference_element.nil?
129
+ end
130
+
131
+ def algorithm(element)
132
+ algorithm = element.attribute("Algorithm").value if element
133
+ algorithm = algorithm && algorithm =~ /sha(.*?)$/i && $1.to_i
134
+ case algorithm
135
+ when 256 then OpenSSL::Digest::SHA256
136
+ when 384 then OpenSSL::Digest::SHA384
137
+ when 512 then OpenSSL::Digest::SHA512
138
+ else
139
+ OpenSSL::Digest::SHA1
140
+ end
141
+ end
142
+ end
143
+
144
+ end
145
+
146
+ end
147
+ end
148
+ end
149
+
@@ -0,0 +1,56 @@
1
+ require 'omniauth'
2
+
3
+ module OmniAuth
4
+ module Strategies
5
+
6
+ class WSFed
7
+ include OmniAuth::Strategy
8
+
9
+ autoload :AuthRequest, 'omniauth/strategies/wsfed/auth_request'
10
+ autoload :AuthResponse, 'omniauth/strategies/wsfed/auth_response'
11
+ autoload :ValidationError, 'omniauth/strategies/wsfed/validation_error'
12
+ autoload :XMLSecurity, 'omniauth/strategies/wsfed/xml_security'
13
+
14
+ # Issues passive WS-Federation redirect for authentication...
15
+ def request_phase
16
+ whr = @request.params['whr']
17
+
18
+ if !whr.nil?
19
+ request = OmniAuth::Strategies::WSFed::AuthRequest.new
20
+ redirect(request.create(options, :whr => whr))
21
+ elsif !options[:home_realm_discovery_path].nil?
22
+ redirect(options[:home_realm_discovery_path])
23
+ else
24
+ request = OmniAuth::Strategies::WSFed::AuthRequest.new
25
+ redirect(request.create(options))
26
+ end
27
+
28
+ end
29
+
30
+ # Parse SAML token...
31
+ def callback_phase
32
+ begin
33
+ response = OmniAuth::Strategies::WSFed::AuthResponse.new(request.params['wresult'], options)
34
+
35
+ @name_id = response.name_id
36
+ @claims = response.attributes
37
+
38
+ return fail!(:invalid_ticket, OmniAuth::Strategies::WSFed::ValidationError('Invalid SAML Token') ) if @claims.nil? || @claims.empty? || !response.valid?
39
+ super
40
+ rescue ArgumentError => e
41
+ fail!(:invalid_ticket, 'Invalid WSFed Response')
42
+ end
43
+ end
44
+
45
+ # OmniAuth DSL methods...
46
+ uid { @name_id }
47
+
48
+ info { @claims }
49
+
50
+ extra { { :wresult => request.params['wresult'] } }
51
+
52
+ end
53
+ end
54
+ end
55
+
56
+ OmniAuth.config.add_camelization 'wsfed', 'WSFed'
@@ -0,0 +1,5 @@
1
+ module OmniAuth
2
+ module WSFed
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ require 'omniauth/strategies/wsfed'
2
+ require 'azure_acs/idp_feed'
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/omniauth-wsfed/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+
6
+ gem.name = "omniauth-wsfed"
7
+ gem.version = OmniAuth::WSFed::VERSION
8
+ gem.description = %q{A WS-Federation + WS-Trust strategy for OmniAuth.}
9
+ gem.summary = %q{OmniAuth WS-Federation strategy enabling integration with Windows Azure Access Control Service (ACS), Active Directory Federation Services (ADFS) 2.0, custom Identity Providers built with Windows Identity Foundation (WIF) or any other Identity Provider supporting the WS-Federation protocol.}
10
+
11
+ gem.authors = ["Keith Beckman"]
12
+ gem.email = ["kbeckman.c4sc@gmail.com"]
13
+ gem.homepage = "https://github.com/kbeckman/omniauth-wsfed"
14
+
15
+ gem.add_runtime_dependency 'omniauth', '~> 1.1.0'
16
+ gem.add_runtime_dependency 'xmlcanonicalizer', '0.1.1'
17
+ gem.add_runtime_dependency 'typhoeus', '~> 0.4.2'
18
+
19
+ gem.add_development_dependency 'rspec', '~> 2.10.0'
20
+ gem.add_development_dependency 'rake', '~> 0.9.2'
21
+ gem.add_development_dependency 'rack-test', '~> 0.6.1'
22
+
23
+ gem.files = `git ls-files`.split($\)
24
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
25
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
26
+ gem.require_paths = ["lib"]
27
+
28
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+ require 'erb'
3
+
4
+ describe AzureACS::IdPFeed do
5
+
6
+ describe "Initialization" do
7
+
8
+ context "with Invalid Context" do
9
+
10
+ it "should raise an exception when IdP JSON feed URL is nil" do
11
+ expect { described_class.new(nil) }.to raise_error ArgumentError
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+ require 'erb'
3
+
4
+ describe OmniAuth::Strategies::WSFed::AuthRequest do
5
+
6
+ context 'Valid Request' do
7
+
8
+ let(:wsfed_settings) do
9
+ {
10
+ issuer: "https://c4sc.accesscontrol.windows.net.com/v2/wsfederation",
11
+ realm: "http://c4sc.com/security_realm",
12
+ reply: "http://rp.c4sc.com/auth/wsfed"
13
+ }
14
+ end
15
+
16
+ describe 'WsFed Auth Request URL' do
17
+
18
+ let :request do
19
+ OmniAuth::Strategies::WSFed::AuthRequest.new.create(wsfed_settings)
20
+ end
21
+
22
+ it 'should include the issuer URL followed by WsFed query string params' do
23
+ request.should start_with "#{wsfed_settings[:issuer]}?"
24
+ end
25
+
26
+ it 'should include the sign-in param [wa]' do
27
+ request.should include 'wa=wsignin1.0'
28
+ end
29
+
30
+ it 'should include the url-encoded security realm param [wtrealm]' do
31
+ request.should include "wtrealm=#{ERB::Util::url_encode(wsfed_settings[:realm])}"
32
+ end
33
+
34
+ it 'should include the url-encoded reply param [wreply]' do
35
+ request.should include "wreply=#{ERB::Util::url_encode(wsfed_settings[:reply])}"
36
+ end
37
+
38
+ it 'should include an empty context param [wctx]' do
39
+ request.should include "wctx=&"
40
+ end
41
+
42
+ it 'should include the request creation instant time param [wtc]' do
43
+ time = Time.now.utc
44
+ Time.now.stub(:utc).and_return(time)
45
+
46
+ request.should include "wct=#{ERB::Util.url_encode(time)}"
47
+ end
48
+
49
+ describe 'Url-Encoded Home Realm Parameter [whr]' do
50
+
51
+ let(:home_realm) { "http://identity.c4sc.com/trust" }
52
+
53
+ it 'should include [whr] if provided in the options' do
54
+ request = OmniAuth::Strategies::WSFed::AuthRequest.new.create(wsfed_settings, :whr => home_realm)
55
+ request.should include "whr=#{ERB::Util::url_encode(home_realm)}"
56
+ end
57
+
58
+ it 'should exclude [whr] if ignored in the options' do
59
+ request = OmniAuth::Strategies::WSFed::AuthRequest.new.create(wsfed_settings, :whr => nil)
60
+ request.should_not include "whr=#{ERB::Util::url_encode(home_realm)}"
61
+ request.should_not include "whr="
62
+ end
63
+
64
+ end
65
+
66
+ end
67
+
68
+ end
69
+
70
+ end
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe OmniAuth::Strategies::WSFed::AuthResponse do
4
+
5
+ describe "Initialization" do
6
+
7
+ context "with Invalid Context" do
8
+
9
+ it "should raise an exception when response is nil" do
10
+ expect { described_class.new(nil, {}) }.to raise_error ArgumentError
11
+ end
12
+
13
+ it "should raise an exception when settings are nil" do
14
+ expect { described_class.new({}, nil) }.to raise_error ArgumentError
15
+ end
16
+
17
+ end
18
+
19
+ end
20
+
21
+ describe "Response Parsing" do
22
+
23
+ before(:each) do
24
+ @wsfed_settings = {
25
+ issuer_name: "http://identity.c4sc.com/trust/",
26
+ issuer: "https://identity.c4sc.com/issue/wsfed",
27
+ realm: "http://rp.c4sc/security_realm",
28
+ reply: "http://rp.c4sc/callback",
29
+ }
30
+ end
31
+
32
+ context "name_id" do
33
+
34
+ it "should load the proper value from various id_claim settings" do
35
+ id_claims = [
36
+ { id_claim: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress", value: "kbeckman.c4sc@gmail.com" },
37
+ { id_claim: "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name", value: "kbeckman.c4sc" }
38
+ ]
39
+
40
+ id_claims.each do |claim_setting|
41
+ @wsfed_settings.merge!(claim_setting.select { |k,v| k == :id_claim })
42
+ response = described_class.new(load_support_xml(:acs_example), @wsfed_settings)
43
+
44
+ response.name_id.should == claim_setting[:value]
45
+ end
46
+ end
47
+
48
+ end
49
+
50
+ context "attributes" do
51
+
52
+ it "should extract the authentication claims" do
53
+ expected_claims = {
54
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" => "kbeckman.c4sc@gmail.com",
55
+ "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name" => "kbeckman.c4sc",
56
+ "http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider" => "http://identity.c4sc.com/trust/"
57
+ }
58
+ response = described_class.new(load_support_xml(:acs_example), @wsfed_settings)
59
+
60
+ response.attributes.should == expected_claims
61
+ end
62
+
63
+ end
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ # Had to split these tests into two different classes because the OmniAuth::Test::StrategyTestCase only sets up one
4
+ # instance of the strategy settings per spec description. In other words, any time you need to make changes to the
5
+ # OmniAuth initialization settings, you need a new spec description to re-initialize the test strategy.
6
+
7
+ describe OmniAuth::Strategies::WSFed, :type => :strategy do
8
+ include OmniAuth::Test::StrategyTestCase
9
+
10
+ let(:auth_hash){ last_request.env['omniauth.auth'] }
11
+ let(:wsfed_settings) do
12
+ {
13
+ issuer: "https://c4sc.accesscontrol.windows.net.com/v2/wsfederation",
14
+ realm: "http://c4sc.com/security_realm",
15
+ reply: "http://rp.c4sc.com/auth/wsfed"
16
+ }
17
+ end
18
+ let(:strategy) { [OmniAuth::Strategies::WSFed, wsfed_settings] }
19
+ let(:home_realm) { "http://identity.c4sc.com/trust" }
20
+
21
+
22
+ describe 'request_phase: GET /auth/wsfed' do
23
+
24
+ context 'no :home_realm_discovery_path' do
25
+
26
+ it 'should redirect to the IdP/FP issuer URL without [whr] param' do
27
+ get '/auth/wsfed'
28
+
29
+ last_response.should be_redirect
30
+ last_response.location.should include wsfed_settings[:issuer]
31
+ end
32
+
33
+ it 'should redirect to the IdP/FP Issuer URL and maintain [whr] param' do
34
+ get "auth/wsfed?whr=#{home_realm}"
35
+
36
+ last_response.should be_redirect
37
+ last_response.location.should include wsfed_settings[:issuer]
38
+ last_response.location.should include "whr=#{ERB::Util::url_encode(home_realm)}"
39
+ end
40
+
41
+ end
42
+
43
+ end
44
+
45
+ end
46
+
47
+ describe OmniAuth::Strategies::WSFed, :type => :strategy do
48
+ include OmniAuth::Test::StrategyTestCase
49
+
50
+ let(:home_realm_discovery) { "/auth/wsfed/home_realm_discovery" }
51
+ let(:wsfed_settings) do
52
+ {
53
+ issuer: "https://c4sc.accesscontrol.windows.net.com/v2/wsfederation",
54
+ realm: "http://c4sc.com/security_realm",
55
+ reply: "http://rp.c4sc.com/auth/wsfed",
56
+ home_realm_discovery_path: home_realm_discovery
57
+ }
58
+ end
59
+ let(:strategy) { [OmniAuth::Strategies::WSFed, wsfed_settings] }
60
+ let(:home_realm) { "http://identity.c4sc.com/trust" }
61
+
62
+ context ':home_realm_discovery_path configured' do
63
+
64
+ it 'should redirect to the local home realm discovery path without [whr] param' do
65
+ get '/auth/wsfed'
66
+
67
+ last_response.should be_redirect
68
+ last_response.location.should == home_realm_discovery
69
+ end
70
+
71
+ it 'should redirect to the IdP/FP Issuer URL and maintain [whr] param' do
72
+ get "auth/wsfed?whr=#{home_realm}"
73
+
74
+ last_response.should be_redirect
75
+ last_response.location.should include wsfed_settings[:issuer]
76
+ last_response.location.should include "whr=#{ERB::Util::url_encode(home_realm)}"
77
+ end
78
+
79
+ end
80
+ end
81
+
82
+
@@ -0,0 +1,12 @@
1
+ require 'omniauth-wsfed'
2
+ require 'rack/test'
3
+
4
+ RSpec.configure do |config|
5
+ config.include Rack::Test::Methods
6
+ end
7
+
8
+ # Loads WSFed WResult XML files located in the spec/support directory...
9
+ def load_support_xml(filename)
10
+ filename = File.expand_path(File.join('..', 'support', "#{filename.to_s}.xml"), __FILE__)
11
+ IO.read(filename)
12
+ end
@@ -0,0 +1,68 @@
1
+ <t:RequestSecurityTokenResponse xmlns:t="http://schemas.xmlsoap.org/ws/2005/02/trust">
2
+ <t:Lifetime>
3
+ <wsu:Created xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2012-06-29T21:07:14.766Z</wsu:Created>
4
+ <wsu:Expires xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">2012-06-29T21:17:14.766Z</wsu:Expires>
5
+ </t:Lifetime>
6
+ <wsp:AppliesTo xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy">
7
+ <EndpointReference xmlns="http://www.w3.org/2005/08/addressing">
8
+ <Address>http://rp.coding4streetcred.com/sample</Address>
9
+ </EndpointReference>
10
+ </wsp:AppliesTo>
11
+ <t:RequestedSecurityToken>
12
+ <Assertion ID="_fa0de02b-b5a1-49c5-a8c0-4b391295a789" IssueInstant="2012-06-29T21:07:14.782Z" Version="2.0" xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
13
+ <Issuer>https://c4sc-identity.accesscontrol.windows.net/</Issuer>
14
+ <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
15
+ <ds:SignedInfo>
16
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
17
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
18
+ <ds:Reference URI="#_fa0de02b-b5a1-49c5-a8c0-4b391295a789">
19
+ <ds:Transforms>
20
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" />
21
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
22
+ </ds:Transforms>
23
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
24
+ <ds:DigestValue>bdwpOR25Tiw03Y5gZsz/NDSrN2T1XAEUQl9/B2aDVjs=</ds:DigestValue>
25
+ </ds:Reference>
26
+ </ds:SignedInfo>
27
+ <ds:SignatureValue>O3dJ5YtFIJJHk8SKAqdI2goSJUj7/oZebGwrm5yjVz8WT9TdHfJT2e/rygKLz9MBujZoZ13oGaVq6NVJLvmvR+IrKsUIuUeXwk4X2UexYxJL9VGZD6RnXR+p0Jne+jGUIlVOb2zMr29Ew27wLfnw3za+Zf5ravQZ/bv3LoL/LFIYFb7iR4XlJ5bjlMhO41euUp/6NTntIC90utugpjqcPryxNbIto6nk3w57IrKmw9rFpRJudoXbw7BsA3t69dmzu2MQzjILbFcfmkUgtEXDQyGM/ziXqxNFEGNHkycEsO37NO4/t5Hk1zPufBbbhSm+5K6tVqZ2Nl1e5yNciBwo6g==</ds:SignatureValue>
28
+ <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
29
+ <X509Data>
30
+ <X509Certificate>MIIDHDCCAgSgAwIBAgIQXMOBsrQ1QJpNmYFiiW5+PjANBgkqhkiG9w0BAQUFADAyMTAwLgYDVQQDEydjNHNjLWlkZW50aXR5LmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwHhcNMTIwNjI5MjAzNTA2WhcNMTMwNjMwMDIzNTA2WjAyMTAwLgYDVQQDEydjNHNjLWlkZW50aXR5LmFjY2Vzc2NvbnRyb2wud2luZG93cy5uZXQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrieSwMYpW73fJtHiBw1yQFWcFZwvDbltFfdb4xzC+MuC8KU/QJzKGBzxixwmvTUKTbH4W4gKNzi7+/gGk9my1UFnDLsnJBooGjx6lCXMU9HoOQA0tXVGkyYeD11Lb2KYWoivvGFI6dun84JY1n1hbAnuyqr+8VUfKpBk3bO6s3xLf2eojAHKhUiw2E+ZBFZWqlTMtSoNupe8I4Zs5Kkp5Xe1hrDjCzHWTHRf880y8f6KOvieQuGO2a2dBSYJVY3IHr1cLlk/o9Dwks4zSjYDABE8NDKer7aq2pnXl0/0XeXeYsDsZFrwfuRtf06pqGgMuqo1aFRiQ2+gm4naZn7D3AgMBAAGjLjAsMAsGA1UdDwQEAwIE8DAdBgNVHQ4EFgQUIBxPC4SJIAWTt6Q4htDcvHDgatAwDQYJKoZIhvcNAQEFBQADggEBAB2RNPpJMNotdKMKtQkV/tEhttOOq+bXlMa42UQu6r+ikgJ6WcSecBxOs4KHw3lj7wO0l8CIOfvXy5KBePLQsUuk8tWCdKdpa+7uuGntIHdlTAvjlcVhXXAQQvyS+wUbnwj8rCN85e76EWMWCAVXzqwMURt5Rzmb+SdU40hRi+7u+HmZaQW5kDXD3CIm+1eOU7oyWpz6Ltx1DEJ88qt4xB2e6IGQUTdvq2jUnyzC1f9jdtRtZ3LiiVkA29rfRROJQb/PeEinUON0hP7/6VS9LZPL4vB1EIOBNahY1V4/75Hb+NGzb05w71hMUiJK2eu8w1WwqcRqUlu7GI921Od1oFQ=</X509Certificate>
31
+ </X509Data>
32
+ </KeyInfo>
33
+ </ds:Signature>
34
+ <Subject>
35
+ <SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer" />
36
+ </Subject>
37
+ <Conditions NotBefore="2012-06-29T21:07:14.766Z" NotOnOrAfter="2012-06-29T21:17:14.766Z">
38
+ <AudienceRestriction>
39
+ <Audience>http://rp.coding4streetcred.com/sample</Audience>
40
+ </AudienceRestriction>
41
+ </Conditions>
42
+ <AttributeStatement>
43
+ <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress">
44
+ <AttributeValue>kbeckman.c4sc@gmail.com</AttributeValue>
45
+ </Attribute>
46
+ <Attribute Name="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name">
47
+ <AttributeValue>kbeckman.c4sc</AttributeValue>
48
+ </Attribute>
49
+ <Attribute Name="http://schemas.microsoft.com/accesscontrolservice/2010/07/claims/identityprovider">
50
+ <AttributeValue>http://identity.c4sc.com/trust/</AttributeValue>
51
+ </Attribute>
52
+ </AttributeStatement>
53
+ </Assertion>
54
+ </t:RequestedSecurityToken>
55
+ <t:RequestedAttachedReference>
56
+ <SecurityTokenReference d3p1:TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0" xmlns:d3p1="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
57
+ <KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID">_fa0de02b-b5a1-49c5-a8c0-4b391295a789</KeyIdentifier>
58
+ </SecurityTokenReference>
59
+ </t:RequestedAttachedReference>
60
+ <t:RequestedUnattachedReference>
61
+ <SecurityTokenReference d3p1:TokenType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0" xmlns:d3p1="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" xmlns="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
62
+ <KeyIdentifier ValueType="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID">_fa0de02b-b5a1-49c5-a8c0-4b391295a789</KeyIdentifier>
63
+ </SecurityTokenReference>
64
+ </t:RequestedUnattachedReference>
65
+ <t:TokenType>urn:oasis:names:tc:SAML:2.0:assertion</t:TokenType>
66
+ <t:RequestType>http://schemas.xmlsoap.org/ws/2005/02/trust/Issue</t:RequestType>
67
+ <t:KeyType>http://schemas.xmlsoap.org/ws/2005/05/identity/NoProofKey</t:KeyType>
68
+ </t:RequestSecurityTokenResponse>
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: omniauth-wsfed
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Keith Beckman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-07 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: omniauth
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 1.1.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 1.1.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: xmlcanonicalizer
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - '='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.1.1
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - '='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.1.1
46
+ - !ruby/object:Gem::Dependency
47
+ name: typhoeus
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.4.2
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.4.2
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 2.10.0
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 2.10.0
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 0.9.2
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 0.9.2
94
+ - !ruby/object:Gem::Dependency
95
+ name: rack-test
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 0.6.1
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 0.6.1
110
+ description: A WS-Federation + WS-Trust strategy for OmniAuth.
111
+ email:
112
+ - kbeckman.c4sc@gmail.com
113
+ executables: []
114
+ extensions: []
115
+ extra_rdoc_files: []
116
+ files:
117
+ - .gitignore
118
+ - Gemfile
119
+ - Gemfile.lock
120
+ - LICENSE
121
+ - README.md
122
+ - Rakefile
123
+ - lib/azure_acs/idp_feed.rb
124
+ - lib/omniauth-wsfed.rb
125
+ - lib/omniauth-wsfed/version.rb
126
+ - lib/omniauth/strategies/wsfed.rb
127
+ - lib/omniauth/strategies/wsfed/auth_request.rb
128
+ - lib/omniauth/strategies/wsfed/auth_response.rb
129
+ - lib/omniauth/strategies/wsfed/validation_error.rb
130
+ - lib/omniauth/strategies/wsfed/xml_security.rb
131
+ - omniauth-wsfed.gemspec
132
+ - spec/azure_acs/idp_feed_spec.rb
133
+ - spec/omniauth/strategies/wsfed/auth_request_spec.rb
134
+ - spec/omniauth/strategies/wsfed/auth_response_spec.rb
135
+ - spec/omniauth/strategies/wsfed_spec.rb
136
+ - spec/spec_helper.rb
137
+ - spec/support/acs_example.xml
138
+ homepage: https://github.com/kbeckman/omniauth-wsfed
139
+ licenses: []
140
+ post_install_message:
141
+ rdoc_options: []
142
+ require_paths:
143
+ - lib
144
+ required_ruby_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ required_rubygems_version: !ruby/object:Gem::Requirement
151
+ none: false
152
+ requirements:
153
+ - - ! '>='
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ requirements: []
157
+ rubyforge_project:
158
+ rubygems_version: 1.8.24
159
+ signing_key:
160
+ specification_version: 3
161
+ summary: OmniAuth WS-Federation strategy enabling integration with Windows Azure Access
162
+ Control Service (ACS), Active Directory Federation Services (ADFS) 2.0, custom Identity
163
+ Providers built with Windows Identity Foundation (WIF) or any other Identity Provider
164
+ supporting the WS-Federation protocol.
165
+ test_files:
166
+ - spec/azure_acs/idp_feed_spec.rb
167
+ - spec/omniauth/strategies/wsfed/auth_request_spec.rb
168
+ - spec/omniauth/strategies/wsfed/auth_response_spec.rb
169
+ - spec/omniauth/strategies/wsfed_spec.rb
170
+ - spec/spec_helper.rb
171
+ - spec/support/acs_example.xml