saml 0.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.
- data/.travis.yml +6 -0
 - data/README.md +71 -0
 - data/lib/saml.rb +30 -0
 - data/lib/saml/bindings.rb +17 -0
 - data/lib/saml/bindings/http_post.rb +18 -0
 - data/lib/saml/bindings/http_redirect.rb +72 -0
 - data/lib/saml/core/assertion.rb +45 -0
 - data/lib/saml/core/attribute.rb +25 -0
 - data/lib/saml/core/attribute_statement.rb +20 -0
 - data/lib/saml/core/authn_request.rb +15 -0
 - data/lib/saml/core/authn_statement.rb +23 -0
 - data/lib/saml/core/document.rb +25 -0
 - data/lib/saml/core/logout_request.rb +24 -0
 - data/lib/saml/core/request_abstract.rb +42 -0
 - data/lib/saml/core/response.rb +28 -0
 - data/lib/saml/core/status.rb +26 -0
 - data/lib/saml/core/status_response.rb +24 -0
 - data/lib/saml/core/subject.rb +13 -0
 - data/lib/saml/core/xml_namespaces.rb +21 -0
 - data/lib/saml/metadata/document.rb +14 -0
 - data/lib/saml/metadata/endpoint.rb +22 -0
 - data/lib/saml/metadata/entities_descriptor.rb +32 -0
 - data/lib/saml/metadata/entity_descriptor.rb +40 -0
 - data/lib/saml/metadata/idp_sso_descriptor.rb +25 -0
 - data/lib/saml/metadata/indexed_endpoint.rb +19 -0
 - data/lib/saml/metadata/key_descriptor.rb +21 -0
 - data/lib/saml/metadata/role_descriptor.rb +21 -0
 - data/lib/saml/metadata/sp_sso_descriptor.rb +23 -0
 - data/lib/saml/metadata/sso_descriptor.rb +21 -0
 - data/lib/saml/metadata/xml_namespaces.rb +19 -0
 - data/lib/saml/session.rb +22 -0
 - data/lib/saml/version.rb +3 -0
 - data/saml.gemspec +24 -0
 - data/spec/saml/bindings/http_redirect_spec.rb +49 -0
 - data/spec/saml/core/assertion_spec.rb +50 -0
 - data/spec/saml/core/attribute_spec.rb +36 -0
 - data/spec/saml/core/attribute_statement_spec.rb +18 -0
 - data/spec/saml/core/authn_request_spec.rb +39 -0
 - data/spec/saml/core/authn_statement_spec.rb +17 -0
 - data/spec/saml/core/logout_request_spec.rb +36 -0
 - data/spec/saml/core/request_abstract_spec.rb +55 -0
 - data/spec/saml/core/response_spec.rb +32 -0
 - data/spec/saml/core/status_response_spec.rb +49 -0
 - data/spec/saml/core/status_spec.rb +27 -0
 - data/spec/saml/core/subject_spec.rb +17 -0
 - data/spec/saml/metadata/endpoint_spec.rb +17 -0
 - data/spec/saml/metadata/entities_descriptor_spec.rb +18 -0
 - data/spec/saml/metadata/entity_descriptor_spec.rb +9 -0
 - data/spec/saml/metadata/idp_sso_descriptor_spec.rb +10 -0
 - data/spec/saml/metadata/indexed_endpoint_spec.rb +20 -0
 - data/spec/saml/metadata/sp_sso_descriptor_spec.rb +8 -0
 - data/spec/saml/metadata/sso_descriptor_spec.rb +9 -0
 - data/spec/spec_helper.rb +20 -0
 - metadata +131 -0
 
    
        data/.travis.yml
    ADDED
    
    
    
        data/README.md
    ADDED
    
    | 
         @@ -0,0 +1,71 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            [](http://travis-ci.org/kjellm/saml)
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            SAML implementation for Ruby
         
     | 
| 
      
 4 
     | 
    
         
            +
            ============================
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            SAML - Security Assertion Markup Language
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
            Install
         
     | 
| 
      
 10 
     | 
    
         
            +
            -------
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            gem install skeleton
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            Usage
         
     | 
| 
      
 16 
     | 
    
         
            +
            -----
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            For an example of how it can be used, take a look at the feide gem
         
     | 
| 
      
 19 
     | 
    
         
            +
            hosted at github https://github.com/kjellm/feide.
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            Documents describing SAML
         
     | 
| 
      
 23 
     | 
    
         
            +
            -------------------------
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            # Technical overview
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
            Read this first:
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            http://www.oasis-open.org/committees/download.php/27819/sstc-saml-tech-overview-2.0-cd-02.pdf
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            # The specification
         
     | 
| 
      
 32 
     | 
    
         
            +
             
     | 
| 
      
 33 
     | 
    
         
            +
            Located at http://docs.oasis-open.org/security/saml/v2.0/
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            * http://docs.oasis-open.org/security/saml/v2.0/saml-core-2.0-os.pdf
         
     | 
| 
      
 36 
     | 
    
         
            +
            * http://docs.oasis-open.org/security/saml/v2.0/saml-profiles-2.0-os.pdf
         
     | 
| 
      
 37 
     | 
    
         
            +
            * http://docs.oasis-open.org/security/saml/v2.0/saml-metadata-2.0-os.pdf
         
     | 
| 
      
 38 
     | 
    
         
            +
            * http://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            Author
         
     | 
| 
      
 42 
     | 
    
         
            +
            ------
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            Kjell-Magne Øierud <kjellm AT oierud DOT net>
         
     | 
| 
      
 45 
     | 
    
         
            +
            	
         
     | 
| 
      
 46 
     | 
    
         
            +
            Bugs
         
     | 
| 
      
 47 
     | 
    
         
            +
            ----
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            Report bugs to http://github.com/kjellm/saml/issues
         
     | 
| 
      
 50 
     | 
    
         
            +
            	
         
     | 
| 
      
 51 
     | 
    
         
            +
            License
         
     | 
| 
      
 52 
     | 
    
         
            +
            -------
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
            (The MIT License)
         
     | 
| 
      
 55 
     | 
    
         
            +
             
     | 
| 
      
 56 
     | 
    
         
            +
            Copyright © 2012 Kjell-Magne Øierud
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
         
     | 
| 
      
 59 
     | 
    
         
            +
            associated documentation files (the ‘Software’), to deal in the Software without restriction, including
         
     | 
| 
      
 60 
     | 
    
         
            +
            without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 61 
     | 
    
         
            +
            copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to
         
     | 
| 
      
 62 
     | 
    
         
            +
            the following conditions:
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be included in all copies or substantial
         
     | 
| 
      
 65 
     | 
    
         
            +
            portions of the Software.
         
     | 
| 
      
 66 
     | 
    
         
            +
             
     | 
| 
      
 67 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
         
     | 
| 
      
 68 
     | 
    
         
            +
            LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
         
     | 
| 
      
 69 
     | 
    
         
            +
            NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
         
     | 
| 
      
 70 
     | 
    
         
            +
            WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
         
     | 
| 
      
 71 
     | 
    
         
            +
            SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/lib/saml.rb
    ADDED
    
    | 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'saml/bindings'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'saml/bindings/http_post'
         
     | 
| 
      
 3 
     | 
    
         
            +
            require 'saml/bindings/http_redirect'
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            require 'saml/core/assertion'
         
     | 
| 
      
 6 
     | 
    
         
            +
            require 'saml/core/attribute'
         
     | 
| 
      
 7 
     | 
    
         
            +
            require 'saml/core/attribute_statement'
         
     | 
| 
      
 8 
     | 
    
         
            +
            require 'saml/core/authn_statement'
         
     | 
| 
      
 9 
     | 
    
         
            +
            require 'saml/core/document'
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'saml/core/request_abstract'
         
     | 
| 
      
 11 
     | 
    
         
            +
            require 'saml/core/logout_request'
         
     | 
| 
      
 12 
     | 
    
         
            +
            require 'saml/core/authn_request'
         
     | 
| 
      
 13 
     | 
    
         
            +
            require 'saml/core/status_response'
         
     | 
| 
      
 14 
     | 
    
         
            +
            require 'saml/core/status'
         
     | 
| 
      
 15 
     | 
    
         
            +
            require 'saml/core/subject'
         
     | 
| 
      
 16 
     | 
    
         
            +
            require 'saml/core/response'
         
     | 
| 
      
 17 
     | 
    
         
            +
            require 'saml/core/xml_namespaces'
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            require 'saml/metadata/document'
         
     | 
| 
      
 20 
     | 
    
         
            +
            require 'saml/metadata/entities_descriptor'
         
     | 
| 
      
 21 
     | 
    
         
            +
            require 'saml/metadata/entity_descriptor'
         
     | 
| 
      
 22 
     | 
    
         
            +
            require 'saml/metadata/endpoint'
         
     | 
| 
      
 23 
     | 
    
         
            +
            require 'saml/metadata/indexed_endpoint'
         
     | 
| 
      
 24 
     | 
    
         
            +
            require 'saml/metadata/key_descriptor'
         
     | 
| 
      
 25 
     | 
    
         
            +
            require 'saml/metadata/sso_descriptor'
         
     | 
| 
      
 26 
     | 
    
         
            +
            require 'saml/metadata/idp_sso_descriptor'
         
     | 
| 
      
 27 
     | 
    
         
            +
            require 'saml/metadata/sp_sso_descriptor'
         
     | 
| 
      
 28 
     | 
    
         
            +
            require 'saml/metadata/xml_namespaces'
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            require 'saml/version'
         
     | 
| 
         @@ -0,0 +1,17 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SAML
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Bindings
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
                def self.from_endpoint(endpoint)
         
     | 
| 
      
 5 
     | 
    
         
            +
                  klass = case endpoint.binding
         
     | 
| 
      
 6 
     | 
    
         
            +
                          when "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
         
     | 
| 
      
 7 
     | 
    
         
            +
                            Bindings::HTTPPost
         
     | 
| 
      
 8 
     | 
    
         
            +
                          when "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
         
     | 
| 
      
 9 
     | 
    
         
            +
                            Bindings::HTTPRedirect
         
     | 
| 
      
 10 
     | 
    
         
            +
                          else
         
     | 
| 
      
 11 
     | 
    
         
            +
                            nil
         
     | 
| 
      
 12 
     | 
    
         
            +
                          end
         
     | 
| 
      
 13 
     | 
    
         
            +
                  klass.new
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SAML
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Bindings
         
     | 
| 
      
 3 
     | 
    
         
            +
                class HTTPPost
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  def build_response(rack_request)
         
     | 
| 
      
 6 
     | 
    
         
            +
                    xml = Core::Document.new(decode(rack_request.params["SAMLResponse"])).root
         
     | 
| 
      
 7 
     | 
    
         
            +
                    Core::Response.from_xml(xml)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  private
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def decode(str)
         
     | 
| 
      
 13 
     | 
    
         
            +
                    Base64.decode64(str)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
                end
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,72 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require "base64"
         
     | 
| 
      
 2 
     | 
    
         
            +
            require "zlib"
         
     | 
| 
      
 3 
     | 
    
         
            +
            require "cgi"
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            module SAML
         
     | 
| 
      
 6 
     | 
    
         
            +
              module Bindings
         
     | 
| 
      
 7 
     | 
    
         
            +
                class HTTPRedirect
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def build_request(rack_response, endpoint, saml_request, relay_state=nil)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    unless relay_state.nil?
         
     | 
| 
      
 11 
     | 
    
         
            +
                      raise ArgumentError.new("relay_state must not exceed 80 bytes") if relay_state.bytesize > 80
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
                    request = saml_request.to_xml.to_s
         
     | 
| 
      
 14 
     | 
    
         
            +
                    deflated_saml_request = deflate(request)
         
     | 
| 
      
 15 
     | 
    
         
            +
                    query = "SAMLRequest=#{deflated_saml_request}"
         
     | 
| 
      
 16 
     | 
    
         
            +
                    query += "&RelayState=#{url_enc(relay_state)}" unless relay_state.nil?
         
     | 
| 
      
 17 
     | 
    
         
            +
                    url = "#{endpoint.location}?#{query}"
         
     | 
| 
      
 18 
     | 
    
         
            +
                    rack_response.redirect url
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def build_response(rack_request)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    xml_str = inflate(rack_request.params["SAMLResponse"])
         
     | 
| 
      
 23 
     | 
    
         
            +
                    xml = Core::Document.new(xml_str).root
         
     | 
| 
      
 24 
     | 
    
         
            +
                    Core::Response.from_xml(xml)
         
     | 
| 
      
 25 
     | 
    
         
            +
                  end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                  private
         
     | 
| 
      
 28 
     | 
    
         
            +
                  
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # Described in section 3.4.4.1
         
     | 
| 
      
 30 
     | 
    
         
            +
                  def deflate(str)
         
     | 
| 
      
 31 
     | 
    
         
            +
                    url_enc(base64_enc(compress(str)))
         
     | 
| 
      
 32 
     | 
    
         
            +
                  end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                  def inflate(str)
         
     | 
| 
      
 35 
     | 
    
         
            +
                    # FIXME do we never need to URL.decode?
         
     | 
| 
      
 36 
     | 
    
         
            +
                    decompress(base64_dec(str))
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                  def compress(str)
         
     | 
| 
      
 41 
     | 
    
         
            +
                    z = Zlib::Deflate.deflate(str, Zlib::BEST_COMPRESSION)
         
     | 
| 
      
 42 
     | 
    
         
            +
                    # The SAML standard requires RFC1951 compliance. Zlib::Deflate
         
     | 
| 
      
 43 
     | 
    
         
            +
                    # are RFC1950 compliant. By removing the 2 byte header and the
         
     | 
| 
      
 44 
     | 
    
         
            +
                    # 4 byte tail (checksum), what's left is a deflate stream as
         
     | 
| 
      
 45 
     | 
    
         
            +
                    # described in RFC1951.
         
     | 
| 
      
 46 
     | 
    
         
            +
                    z[2..-5]
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
                  def decompress(str)
         
     | 
| 
      
 50 
     | 
    
         
            +
                    z = Zlib::Inflate.new(-Zlib::MAX_WBITS) # Raw processing (no head or tail)
         
     | 
| 
      
 51 
     | 
    
         
            +
                    z.inflate(str)
         
     | 
| 
      
 52 
     | 
    
         
            +
                  end
         
     | 
| 
      
 53 
     | 
    
         
            +
             
     | 
| 
      
 54 
     | 
    
         
            +
                  def base64_enc(str)
         
     | 
| 
      
 55 
     | 
    
         
            +
                    Base64.encode64(str)
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
                  def base64_dec(str)
         
     | 
| 
      
 59 
     | 
    
         
            +
                    Base64.decode64(str)
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  def url_enc(str)
         
     | 
| 
      
 63 
     | 
    
         
            +
                    CGI.escape(str)
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
                  def url_dec(str)
         
     | 
| 
      
 67 
     | 
    
         
            +
                    CGI.unescape(str)
         
     | 
| 
      
 68 
     | 
    
         
            +
                  end
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                end
         
     | 
| 
      
 71 
     | 
    
         
            +
              end
         
     | 
| 
      
 72 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,45 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SAML
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Core
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Assertion
         
     | 
| 
      
 4 
     | 
    
         
            +
                  
         
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_reader :id
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :version
         
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_reader :issue_instant
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :issuer
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                  attr_reader :subject
         
     | 
| 
      
 11 
     | 
    
         
            +
                  attr_reader :attribute_statement
         
     | 
| 
      
 12 
     | 
    
         
            +
                  attr_reader :authn_statements
         
     | 
| 
      
 13 
     | 
    
         
            +
                  attr_reader :conditions
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  def self.from_xml(xml); new.from_xml(xml); end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def initialize
         
     | 
| 
      
 18 
     | 
    
         
            +
                    @authn_statements = []
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  def from_xml(xml)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    @id            = xml.attributes['ID']
         
     | 
| 
      
 23 
     | 
    
         
            +
                    @version       = xml.attributes['Version']
         
     | 
| 
      
 24 
     | 
    
         
            +
                    @issue_instant = xml.attributes['IssueInstant']
         
     | 
| 
      
 25 
     | 
    
         
            +
                    
         
     | 
| 
      
 26 
     | 
    
         
            +
                    subject_element = xml.get_elements('saml:Subject')
         
     | 
| 
      
 27 
     | 
    
         
            +
                    unless subject_element.empty?
         
     | 
| 
      
 28 
     | 
    
         
            +
                      # @subject = Subject.from_xml(subject_element.first)
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                    attribute_statements = xml.get_elements('saml:AttributeStatement')
         
     | 
| 
      
 32 
     | 
    
         
            +
                    unless attribute_statements.empty?
         
     | 
| 
      
 33 
     | 
    
         
            +
                      @attribute_statement = AttributeStatement.from_xml(attribute_statements.first)
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                    xml.get_elements('saml:AuthnStatement').each do |as|
         
     | 
| 
      
 37 
     | 
    
         
            +
                      @authn_statements << AuthnStatement.from_xml(as)
         
     | 
| 
      
 38 
     | 
    
         
            +
                    end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                    self
         
     | 
| 
      
 41 
     | 
    
         
            +
                  end
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
                end
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SAML
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Core
         
     | 
| 
      
 3 
     | 
    
         
            +
                class Attribute
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_accessor :name
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_accessor :name_format
         
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_accessor :attribute_values
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  def self.from_xml(xml)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    attribute = new
         
     | 
| 
      
 11 
     | 
    
         
            +
                    attribute.name = xml.attributes['Name']
         
     | 
| 
      
 12 
     | 
    
         
            +
                    
         
     | 
| 
      
 13 
     | 
    
         
            +
                    nf = xml.attributes['NameFormat']
         
     | 
| 
      
 14 
     | 
    
         
            +
                    attribute.name_format = nf.nil? ? 'urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified' : nf
         
     | 
| 
      
 15 
     | 
    
         
            +
                    
         
     | 
| 
      
 16 
     | 
    
         
            +
                    values = []
         
     | 
| 
      
 17 
     | 
    
         
            +
                    xml.each_element() do |av|
         
     | 
| 
      
 18 
     | 
    
         
            +
                      values << av.to_s
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                    attribute.attribute_values = values
         
     | 
| 
      
 21 
     | 
    
         
            +
                    attribute
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,20 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SAML
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Core
         
     | 
| 
      
 3 
     | 
    
         
            +
                class AttributeStatement
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_accessor :attributes
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  def self.from_xml(xml)
         
     | 
| 
      
 8 
     | 
    
         
            +
                    statement = new
         
     | 
| 
      
 9 
     | 
    
         
            +
                    attrs = []
         
     | 
| 
      
 10 
     | 
    
         
            +
                    xml.each_element('saml:Attribute') do |a|
         
     | 
| 
      
 11 
     | 
    
         
            +
                      attrs << Attribute.from_xml(a)
         
     | 
| 
      
 12 
     | 
    
         
            +
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
                    statement.attributes = attrs
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    statement
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                end
         
     | 
| 
      
 19 
     | 
    
         
            +
              end
         
     | 
| 
      
 20 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,23 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SAML
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Core
         
     | 
| 
      
 3 
     | 
    
         
            +
                class AuthnStatement
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_reader :authn_instant
         
     | 
| 
      
 6 
     | 
    
         
            +
                  attr_reader :session_not_on_or_after
         
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_reader :session_index
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_reader :authn_context
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  def self.from_xml(xml); new.from_xml(xml); end
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def from_xml(xml)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @authn_instant           = xml.attributes['AuthnInstant']
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @session_not_on_or_after = xml.attributes['SessionNotOnOrAfter']
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @session_index           = xml.attributes['SessionIndex']
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                    self
         
     | 
| 
      
 19 
     | 
    
         
            +
                  end
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,25 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rexml/document'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module SAML
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Core
         
     | 
| 
      
 5 
     | 
    
         
            +
                class Document < REXML::Document
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                  def initialize(*args)
         
     | 
| 
      
 9 
     | 
    
         
            +
                    super(*args)
         
     | 
| 
      
 10 
     | 
    
         
            +
                    XMLNamespaces.each {|k,v| add_namespace(k, v)}
         
     | 
| 
      
 11 
     | 
    
         
            +
                  end
         
     | 
| 
      
 12 
     | 
    
         
            +
                  
         
     | 
| 
      
 13 
     | 
    
         
            +
                  # See REXML::Document#add_element
         
     | 
| 
      
 14 
     | 
    
         
            +
                  #
         
     | 
| 
      
 15 
     | 
    
         
            +
                  # Makes sure that all namespaces are added to the root element.
         
     | 
| 
      
 16 
     | 
    
         
            +
                  def add_element(name, attrs={})
         
     | 
| 
      
 17 
     | 
    
         
            +
                    ns = XMLNamespaces.map {|k, v| ["xmlns:#{k}", v]}
         
     | 
| 
      
 18 
     | 
    
         
            +
                    ns = Hash[*ns.flatten]
         
     | 
| 
      
 19 
     | 
    
         
            +
                    attrs.merge!(ns)
         
     | 
| 
      
 20 
     | 
    
         
            +
                    super(name, attrs)
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,24 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module SAML
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Core
         
     | 
| 
      
 3 
     | 
    
         
            +
                class LogoutRequest < RequestAbstract
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
                  attr_accessor :name_id
         
     | 
| 
      
 6 
     | 
    
         
            +
                  
         
     | 
| 
      
 7 
     | 
    
         
            +
                  def xml_document
         
     | 
| 
      
 8 
     | 
    
         
            +
                    xml = Document.new
         
     | 
| 
      
 9 
     | 
    
         
            +
                    root = xml.add_element("samlp:LogoutRequest")
         
     | 
| 
      
 10 
     | 
    
         
            +
                  end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  def to_xml
         
     | 
| 
      
 13 
     | 
    
         
            +
                    xml = super
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    unless @name_id.nil?
         
     | 
| 
      
 16 
     | 
    
         
            +
                      name_id_node = xml.root.add_element("saml:NameID")
         
     | 
| 
      
 17 
     | 
    
         
            +
                      name_id_node.text = @name_id
         
     | 
| 
      
 18 
     | 
    
         
            +
                    end
         
     | 
| 
      
 19 
     | 
    
         
            +
                    
         
     | 
| 
      
 20 
     | 
    
         
            +
                    xml
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                end
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'uuid'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module SAML
         
     | 
| 
      
 4 
     | 
    
         
            +
              module Core
         
     | 
| 
      
 5 
     | 
    
         
            +
                class RequestAbstract
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
                  attr_reader :id
         
     | 
| 
      
 8 
     | 
    
         
            +
                  attr_reader :version
         
     | 
| 
      
 9 
     | 
    
         
            +
                  attr_reader :issue_instant
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                  attr_accessor :issuer
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                  def initialize(clock_class=Time)
         
     | 
| 
      
 14 
     | 
    
         
            +
                    @id            = UUID.new.generate
         
     | 
| 
      
 15 
     | 
    
         
            +
                    @version       = '2.0'
         
     | 
| 
      
 16 
     | 
    
         
            +
                    @issue_instant = clock_class.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
         
     | 
| 
      
 17 
     | 
    
         
            +
                  end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  def xml_document
         
     | 
| 
      
 20 
     | 
    
         
            +
                    xml = Document.new
         
     | 
| 
      
 21 
     | 
    
         
            +
                    root = xml.add_element("samlp:RequestAbstract")
         
     | 
| 
      
 22 
     | 
    
         
            +
                  end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
                  def to_xml
         
     | 
| 
      
 26 
     | 
    
         
            +
                    xml = xml_document
         
     | 
| 
      
 27 
     | 
    
         
            +
                    root = xml.root
         
     | 
| 
      
 28 
     | 
    
         
            +
                    root.attributes['ID']           = @id
         
     | 
| 
      
 29 
     | 
    
         
            +
                    root.attributes['IssueInstant'] = @issue_instant
         
     | 
| 
      
 30 
     | 
    
         
            +
                    root.attributes['Version']      = @version
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    unless @issuer.nil?
         
     | 
| 
      
 33 
     | 
    
         
            +
                      issuer_node = root.add_element("saml:Issuer")
         
     | 
| 
      
 34 
     | 
    
         
            +
                      issuer_node.text = @issuer
         
     | 
| 
      
 35 
     | 
    
         
            +
                    end
         
     | 
| 
      
 36 
     | 
    
         
            +
                    
         
     | 
| 
      
 37 
     | 
    
         
            +
                    xml
         
     | 
| 
      
 38 
     | 
    
         
            +
                  end
         
     | 
| 
      
 39 
     | 
    
         
            +
             
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     |