devise_saml_authenticatable 1.4.1 → 1.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/.travis.yml +15 -5
 - data/README.md +43 -18
 - data/lib/devise_saml_authenticatable.rb +12 -0
 - data/lib/devise_saml_authenticatable/model.rb +6 -2
 - data/lib/devise_saml_authenticatable/routes.rb +17 -6
 - data/lib/devise_saml_authenticatable/saml_mapped_attributes.rb +15 -2
 - data/lib/devise_saml_authenticatable/version.rb +1 -1
 - data/spec/devise_saml_authenticatable/model_spec.rb +42 -5
 - data/spec/devise_saml_authenticatable/saml_mapped_attributes_spec.rb +50 -0
 - data/spec/features/saml_authentication_spec.rb +3 -2
 - data/spec/rails_helper.rb +5 -1
 - data/spec/routes/routes_spec.rb +102 -0
 - data/spec/support/Gemfile.rails5.1 +14 -0
 - data/spec/support/attribute-map.yml +12 -0
 - data/spec/support/idp_template.rb +3 -1
 - data/spec/support/rails_app.rb +1 -1
 - data/spec/support/sp_template.rb +3 -1
 - metadata +10 -2
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA1:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 388799cd1bf9c14ad21b7a042d63957d965ec080
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: b5e153ee444879be849e6ddda43e2762a3905092
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: 2c304efa473b057a46895b96db3d6d076ebdaa332de7c7d6a3480b86a3ae3e33d17123b5f565d229c5412a9496cc9c549e34960aa119f8a1c18180eea87eb05e
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 40a2dd033fd20cccc2803dc587309be272005a5d84c8e80a0325b038079fcd2deb9b6aad78f8afb30c2462f9952efe1e49ffa100b9187480c5234a6565aaf566
         
     | 
    
        data/.travis.yml
    CHANGED
    
    | 
         @@ -3,12 +3,14 @@ rvm: 
     | 
|
| 
       3 
3 
     | 
    
         
             
              - "1.9.3"
         
     | 
| 
       4 
4 
     | 
    
         
             
              - "2.0.0"
         
     | 
| 
       5 
5 
     | 
    
         
             
              - "2.1.10"
         
     | 
| 
       6 
     | 
    
         
            -
              - "2.2. 
     | 
| 
       7 
     | 
    
         
            -
              - "2.3. 
     | 
| 
       8 
     | 
    
         
            -
              - "2.4. 
     | 
| 
       9 
     | 
    
         
            -
              - "2.5. 
     | 
| 
      
 6 
     | 
    
         
            +
              - "2.2.10"
         
     | 
| 
      
 7 
     | 
    
         
            +
              - "2.3.8"
         
     | 
| 
      
 8 
     | 
    
         
            +
              - "2.4.5"
         
     | 
| 
      
 9 
     | 
    
         
            +
              - "2.5.3"
         
     | 
| 
      
 10 
     | 
    
         
            +
              - "2.6.0"
         
     | 
| 
       10 
11 
     | 
    
         
             
            gemfile:
         
     | 
| 
       11 
12 
     | 
    
         
             
              - Gemfile
         
     | 
| 
      
 13 
     | 
    
         
            +
              - spec/support/Gemfile.rails5.1
         
     | 
| 
       12 
14 
     | 
    
         
             
              - spec/support/Gemfile.rails5
         
     | 
| 
       13 
15 
     | 
    
         
             
              - spec/support/Gemfile.rails4
         
     | 
| 
       14 
16 
     | 
    
         
             
            matrix:
         
     | 
| 
         @@ -17,18 +19,26 @@ matrix: 
     | 
|
| 
       17 
19 
     | 
    
         
             
                  gemfile: Gemfile
         
     | 
| 
       18 
20 
     | 
    
         
             
                - rvm: "1.9.3"
         
     | 
| 
       19 
21 
     | 
    
         
             
                  gemfile: spec/support/Gemfile.rails5
         
     | 
| 
      
 22 
     | 
    
         
            +
                - rvm: "1.9.3"
         
     | 
| 
      
 23 
     | 
    
         
            +
                  gemfile: spec/support/Gemfile.rails5.1
         
     | 
| 
       20 
24 
     | 
    
         
             
                - rvm: "2.0.0"
         
     | 
| 
       21 
25 
     | 
    
         
             
                  gemfile: Gemfile
         
     | 
| 
       22 
26 
     | 
    
         
             
                - rvm: "2.0.0"
         
     | 
| 
       23 
27 
     | 
    
         
             
                  gemfile: spec/support/Gemfile.rails5
         
     | 
| 
      
 28 
     | 
    
         
            +
                - rvm: "2.0.0"
         
     | 
| 
      
 29 
     | 
    
         
            +
                  gemfile: spec/support/Gemfile.rails5.1
         
     | 
| 
       24 
30 
     | 
    
         
             
                - rvm: "2.1.10"
         
     | 
| 
       25 
31 
     | 
    
         
             
                  gemfile: Gemfile
         
     | 
| 
       26 
32 
     | 
    
         
             
                - rvm: "2.1.10"
         
     | 
| 
       27 
33 
     | 
    
         
             
                  gemfile: spec/support/Gemfile.rails5
         
     | 
| 
      
 34 
     | 
    
         
            +
                - rvm: "2.1.10"
         
     | 
| 
      
 35 
     | 
    
         
            +
                  gemfile: spec/support/Gemfile.rails5.1
         
     | 
| 
      
 36 
     | 
    
         
            +
                - rvm: "2.6.0"
         
     | 
| 
      
 37 
     | 
    
         
            +
                  gemfile: spec/support/Gemfile.rails4
         
     | 
| 
       28 
38 
     | 
    
         | 
| 
       29 
39 
     | 
    
         
             
            before_install:
         
     | 
| 
       30 
40 
     | 
    
         
             
              # update bundler to avoid https://github.com/travis-ci/travis-ci/issues/5239
         
     | 
| 
       31 
     | 
    
         
            -
              - gem install bundler
         
     | 
| 
      
 41 
     | 
    
         
            +
              - command -v bundle || gem install bundler -v '~> 1.17.3'
         
     | 
| 
       32 
42 
     | 
    
         | 
| 
       33 
43 
     | 
    
         
             
            script:
         
     | 
| 
       34 
44 
     | 
    
         
             
              - bundle exec rake
         
     | 
    
        data/README.md
    CHANGED
    
    | 
         @@ -20,6 +20,10 @@ Or install it yourself as: 
     | 
|
| 
       20 
20 
     | 
    
         | 
| 
       21 
21 
     | 
    
         
             
            ## Usage
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
      
 23 
     | 
    
         
            +
            Follow the [normal devise installation process](https://github.com/plataformatec/devise/tree/master#getting-started). The controller filters and helpers are unchanged from normal devise usage.
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            ### Configuring Models
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
       23 
27 
     | 
    
         
             
            In `app/models/<YOUR_MODEL>.rb` set the `:saml_authenticatable` strategy.
         
     | 
| 
       24 
28 
     | 
    
         | 
| 
       25 
29 
     | 
    
         
             
            In the example the model is `user.rb`:
         
     | 
| 
         @@ -32,6 +36,37 @@ In the example the model is `user.rb`: 
     | 
|
| 
       32 
36 
     | 
    
         
             
              end
         
     | 
| 
       33 
37 
     | 
    
         
             
            ```
         
     | 
| 
       34 
38 
     | 
    
         | 
| 
      
 39 
     | 
    
         
            +
            ### Configuring routes
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
            In `config/routes.rb` add `devise_for` to set up helper methods and routes:
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            ```ruby
         
     | 
| 
      
 44 
     | 
    
         
            +
            devise_for :users
         
     | 
| 
      
 45 
     | 
    
         
            +
            ```
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
      
 47 
     | 
    
         
            +
            The named routes can be customized in the initializer config file.
         
     | 
| 
      
 48 
     | 
    
         
            +
             
     | 
| 
      
 49 
     | 
    
         
            +
            ### Configuring the IdP
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
            An extra step in SAML SSO setup is adding your application to your identity provider. The required setup is specific to each IdP, but we have some examples in [our wiki](https://github.com/apokalipto/devise_saml_authenticatable/wiki). You'll need to tell your IdP how to send requests and responses to your application.
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            - Creating a new session: `/users/saml/auth`
         
     | 
| 
      
 54 
     | 
    
         
            +
                - IdPs may call this the "consumer," "recipient," "destination," or even "single sign-on." This is where they send a SAML response for an authenticated user.
         
     | 
| 
      
 55 
     | 
    
         
            +
            - Metadata: `/users/saml/metadata`
         
     | 
| 
      
 56 
     | 
    
         
            +
                - IdPs may call this the "audience."
         
     | 
| 
      
 57 
     | 
    
         
            +
            - Single Logout: `/users/saml/idp_sign_out`
         
     | 
| 
      
 58 
     | 
    
         
            +
                - if desired, you can ask the IdP to send a Logout request to this endpoint to sign the user out of your application when they sign out of the IdP itself.
         
     | 
| 
      
 59 
     | 
    
         
            +
             
     | 
| 
      
 60 
     | 
    
         
            +
            Your IdP should give you some information you need to configure in [ruby-saml](https://github.com/onelogin/ruby-saml), as in the next section:
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
            - Issuer (`idp_entity_id`)
         
     | 
| 
      
 63 
     | 
    
         
            +
            - SSO endpoint (`idp_sso_target_url`)
         
     | 
| 
      
 64 
     | 
    
         
            +
            - SLO endpoint (`idp_slo_target_url`)
         
     | 
| 
      
 65 
     | 
    
         
            +
            - Certificate fingerprint (`idp_cert_fingerprint`) and algorithm (`idp_cert_fingerprint_algorithm`)
         
     | 
| 
      
 66 
     | 
    
         
            +
                - Or the certificate itself (`idp_cert`)
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
            ### Configuring handling of IdP requests and responses
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
       35 
70 
     | 
    
         
             
            In `config/initializers/devise.rb`:
         
     | 
| 
       36 
71 
     | 
    
         | 
| 
       37 
72 
     | 
    
         
             
            ```ruby
         
     | 
| 
         @@ -69,6 +104,12 @@ In `config/initializers/devise.rb`: 
     | 
|
| 
       69 
104 
     | 
    
         
             
                # and implements a #handle method. This method can then redirect the user, return error messages, etc.
         
     | 
| 
       70 
105 
     | 
    
         
             
                # config.saml_failed_callback = nil
         
     | 
| 
       71 
106 
     | 
    
         | 
| 
      
 107 
     | 
    
         
            +
                # You can customize the named routes generated in case of named route collisions with
         
     | 
| 
      
 108 
     | 
    
         
            +
                # other Devise modules or libraries. Set the saml_route_helper_prefix to a string that will
         
     | 
| 
      
 109 
     | 
    
         
            +
                # be appended to the named route.
         
     | 
| 
      
 110 
     | 
    
         
            +
                # If saml_route_helper_prefix = 'saml' then the new_user_session route becomes new_saml_user_session
         
     | 
| 
      
 111 
     | 
    
         
            +
                # config.saml_route_helper_prefix = 'saml'
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
       72 
113 
     | 
    
         
             
                # Configure with your SAML settings (see ruby-saml's README for more information: https://github.com/onelogin/ruby-saml).
         
     | 
| 
       73 
114 
     | 
    
         
             
                config.saml_configure do |settings|
         
     | 
| 
       74 
115 
     | 
    
         
             
                  # assertion_consumer_service_url is required starting with ruby-saml 1.4.3: https://github.com/onelogin/ruby-saml#updating-from-142-to-143
         
     | 
| 
         @@ -79,24 +120,8 @@ In `config/initializers/devise.rb`: 
     | 
|
| 
       79 
120 
     | 
    
         
             
                  settings.authn_context                      = ""
         
     | 
| 
       80 
121 
     | 
    
         
             
                  settings.idp_slo_target_url                 = "http://localhost/simplesaml/www/saml2/idp/SingleLogoutService.php"
         
     | 
| 
       81 
122 
     | 
    
         
             
                  settings.idp_sso_target_url                 = "http://localhost/simplesaml/www/saml2/idp/SSOService.php"
         
     | 
| 
       82 
     | 
    
         
            -
                  settings. 
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
            1111111111111111111111111111111111111111111111111111111111111111
         
     | 
| 
       85 
     | 
    
         
            -
            1111111111111111111111111111111111111111111111111111111111111111
         
     | 
| 
       86 
     | 
    
         
            -
            1111111111111111111111111111111111111111111111111111111111111111
         
     | 
| 
       87 
     | 
    
         
            -
            1111111111111111111111111111111111111111111111111111111111111111
         
     | 
| 
       88 
     | 
    
         
            -
            1111111111111111111111111111111111111111111111111111111111111111
         
     | 
| 
       89 
     | 
    
         
            -
            1111111111111_______IDP_CERTIFICATE________111111111111111111111
         
     | 
| 
       90 
     | 
    
         
            -
            1111111111111111111111111111111111111111111111111111111111111111
         
     | 
| 
       91 
     | 
    
         
            -
            1111111111111111111111111111111111111111111111111111111111111111
         
     | 
| 
       92 
     | 
    
         
            -
            1111111111111111111111111111111111111111111111111111111111111111
         
     | 
| 
       93 
     | 
    
         
            -
            1111111111111111111111111111111111111111111111111111111111111111
         
     | 
| 
       94 
     | 
    
         
            -
            1111111111111111111111111111111111111111111111111111111111111111
         
     | 
| 
       95 
     | 
    
         
            -
            1111111111111111111111111111111111111111111111111111111111111111
         
     | 
| 
       96 
     | 
    
         
            -
            1111111111111111111111111111111111111111111111111111111111111111
         
     | 
| 
       97 
     | 
    
         
            -
            111111111111111111
         
     | 
| 
       98 
     | 
    
         
            -
            -----END CERTIFICATE-----
         
     | 
| 
       99 
     | 
    
         
            -
                  CERT
         
     | 
| 
      
 123 
     | 
    
         
            +
                  settings.idp_cert_fingerprint               = "00:A1:2B:3C:44:55:6F:A7:88:CC:DD:EE:22:33:44:55:D6:77:8F:99"
         
     | 
| 
      
 124 
     | 
    
         
            +
                  settings.idp_cert_fingerprint_algorithm     = "http://www.w3.org/2000/09/xmldsig#sha1"
         
     | 
| 
       100 
125 
     | 
    
         
             
                end
         
     | 
| 
       101 
126 
     | 
    
         
             
              end
         
     | 
| 
       102 
127 
     | 
    
         
             
            ```
         
     | 
| 
         @@ -19,6 +19,10 @@ end 
     | 
|
| 
       19 
19 
     | 
    
         | 
| 
       20 
20 
     | 
    
         
             
            # Get saml information from config/saml.yml now
         
     | 
| 
       21 
21 
     | 
    
         
             
            module Devise
         
     | 
| 
      
 22 
     | 
    
         
            +
              # Allow route customization to avoid collision
         
     | 
| 
      
 23 
     | 
    
         
            +
              mattr_accessor :saml_route_helper_prefix
         
     | 
| 
      
 24 
     | 
    
         
            +
              @@saml_route_helper_prefix
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
       22 
26 
     | 
    
         
             
              # Allow logging
         
     | 
| 
       23 
27 
     | 
    
         
             
              mattr_accessor :saml_logger
         
     | 
| 
       24 
28 
     | 
    
         
             
              @@saml_logger = true
         
     | 
| 
         @@ -64,9 +68,17 @@ module Devise 
     | 
|
| 
       64 
68 
     | 
    
         | 
| 
       65 
69 
     | 
    
         
             
              # Implements a #validate method that takes the retrieved resource and response right after retrieval,
         
     | 
| 
       66 
70 
     | 
    
         
             
              # and returns true if it's valid.  False will cause authentication to fail.
         
     | 
| 
      
 71 
     | 
    
         
            +
              # Only one of saml_resource_validator and saml_resource_validator_hook may be used.
         
     | 
| 
       67 
72 
     | 
    
         
             
              mattr_accessor :saml_resource_validator
         
     | 
| 
       68 
73 
     | 
    
         
             
              @@saml_resource_validator
         
     | 
| 
       69 
74 
     | 
    
         | 
| 
      
 75 
     | 
    
         
            +
              # Proc that determines whether a technically correct SAML response is valid per some custom logic.
         
     | 
| 
      
 76 
     | 
    
         
            +
              # Receives the user object (or nil, if no match was found), decorated saml_response and
         
     | 
| 
      
 77 
     | 
    
         
            +
              # auth_value, inspects the combination for acceptability of login (or create+login, if enabled),
         
     | 
| 
      
 78 
     | 
    
         
            +
              # and returns true if it's valid.  False will cause authentication to fail.
         
     | 
| 
      
 79 
     | 
    
         
            +
              mattr_accessor :saml_resource_validator_hook
         
     | 
| 
      
 80 
     | 
    
         
            +
              @@saml_resource_validator_hook
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
       70 
82 
     | 
    
         
             
              # Custom value for ruby-saml allowed_clock_drift
         
     | 
| 
       71 
83 
     | 
    
         
             
              mattr_accessor :allowed_clock_drift_in_seconds
         
     | 
| 
       72 
84 
     | 
    
         
             
              @@allowed_clock_drift_in_seconds
         
     | 
| 
         @@ -44,8 +44,12 @@ module Devise 
     | 
|
| 
       44 
44 
     | 
    
         | 
| 
       45 
45 
     | 
    
         
             
                      resource = Devise.saml_resource_locator.call(self, decorated_response, auth_value)
         
     | 
| 
       46 
46 
     | 
    
         | 
| 
       47 
     | 
    
         
            -
                      if Devise.saml_resource_validator
         
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
      
 47 
     | 
    
         
            +
                      raise "Only one validator configuration can be used at a time" if Devise.saml_resource_validator && Devise.saml_resource_validator_hook
         
     | 
| 
      
 48 
     | 
    
         
            +
                      if Devise.saml_resource_validator || Devise.saml_resource_validator_hook
         
     | 
| 
      
 49 
     | 
    
         
            +
                        valid = if Devise.saml_resource_validator then Devise.saml_resource_validator.new.validate(resource, saml_response)
         
     | 
| 
      
 50 
     | 
    
         
            +
                                else Devise.saml_resource_validator_hook.call(resource, decorated_response, auth_value)
         
     | 
| 
      
 51 
     | 
    
         
            +
                                end
         
     | 
| 
      
 52 
     | 
    
         
            +
                        if !valid
         
     | 
| 
       49 
53 
     | 
    
         
             
                          logger.info("User(#{auth_value}) did not pass custom validation.")
         
     | 
| 
       50 
54 
     | 
    
         
             
                          return nil
         
     | 
| 
       51 
55 
     | 
    
         
             
                        end
         
     | 
| 
         @@ -1,12 +1,23 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ActionDispatch::Routing::Mapper.class_eval do
         
     | 
| 
       2 
2 
     | 
    
         
             
              protected
         
     | 
| 
       3 
3 
     | 
    
         
             
              def devise_saml_authenticatable(mapping, controllers)
         
     | 
| 
       4 
     | 
    
         
            -
                 
     | 
| 
       5 
     | 
    
         
            -
                   
     | 
| 
       6 
     | 
    
         
            -
                   
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
             
     | 
| 
       9 
     | 
    
         
            -
             
     | 
| 
      
 4 
     | 
    
         
            +
                if ::Devise.saml_route_helper_prefix
         
     | 
| 
      
 5 
     | 
    
         
            +
                  prefix = ::Devise.saml_route_helper_prefix
         
     | 
| 
      
 6 
     | 
    
         
            +
                  resource :session, only: [], controller: controllers[:saml_sessions], path: '' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                    get :new, path: 'saml/sign_in', as: "new_#{prefix}"
         
     | 
| 
      
 8 
     | 
    
         
            +
                    post :create, path: 'saml/auth', as: prefix
         
     | 
| 
      
 9 
     | 
    
         
            +
                    match :destroy, path: mapping.path_names[:sign_out], as: "destroy_#{prefix}", via: mapping.sign_out_via
         
     | 
| 
      
 10 
     | 
    
         
            +
                    get :metadata, path: 'saml/metadata'
         
     | 
| 
      
 11 
     | 
    
         
            +
                    match :idp_sign_out, path: 'saml/idp_sign_out', as: "idp_destroy_#{prefix}", via: [:get, :post]
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                else
         
     | 
| 
      
 14 
     | 
    
         
            +
                  resource :session, only: [], controller: controllers[:saml_sessions], path: '' do
         
     | 
| 
      
 15 
     | 
    
         
            +
                    get :new, path: 'saml/sign_in', as: 'new'
         
     | 
| 
      
 16 
     | 
    
         
            +
                    post :create, path: 'saml/auth'
         
     | 
| 
      
 17 
     | 
    
         
            +
                    match :destroy, path: mapping.path_names[:sign_out], as: 'destroy', via: mapping.sign_out_via
         
     | 
| 
      
 18 
     | 
    
         
            +
                    get :metadata, path: 'saml/metadata'
         
     | 
| 
      
 19 
     | 
    
         
            +
                    match :idp_sign_out, path: 'saml/idp_sign_out', via: [:get, :post]
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
       10 
21 
     | 
    
         
             
                end
         
     | 
| 
       11 
22 
     | 
    
         
             
              end
         
     | 
| 
       12 
23 
     | 
    
         
             
            end
         
     | 
| 
         @@ -3,7 +3,6 @@ module SamlAuthenticatable 
     | 
|
| 
       3 
3 
     | 
    
         
             
                def initialize(attributes, attribute_map)
         
     | 
| 
       4 
4 
     | 
    
         
             
                  @attributes = attributes
         
     | 
| 
       5 
5 
     | 
    
         
             
                  @attribute_map = attribute_map
         
     | 
| 
       6 
     | 
    
         
            -
                  @inverted_attribute_map = @attribute_map.invert
         
     | 
| 
       7 
6 
     | 
    
         
             
                end
         
     | 
| 
       8 
7 
     | 
    
         | 
| 
       9 
8 
     | 
    
         
             
                def saml_attribute_keys
         
     | 
| 
         @@ -15,7 +14,21 @@ module SamlAuthenticatable 
     | 
|
| 
       15 
14 
     | 
    
         
             
                end
         
     | 
| 
       16 
15 
     | 
    
         | 
| 
       17 
16 
     | 
    
         
             
                def value_by_resource_key(key)
         
     | 
| 
       18 
     | 
    
         
            -
                   
     | 
| 
      
 17 
     | 
    
         
            +
                  str_key = String(key)
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                  # Find all of the SAML attributes that map to the resource key
         
     | 
| 
      
 20 
     | 
    
         
            +
                  attribute_map_for_key = @attribute_map.select { |_, resource_key| String(resource_key) == str_key }
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  saml_value = nil
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
                  # Find the first non-nil value
         
     | 
| 
      
 25 
     | 
    
         
            +
                  attribute_map_for_key.each_key do |saml_key|
         
     | 
| 
      
 26 
     | 
    
         
            +
                    saml_value = value_by_saml_attribute_key(saml_key)
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                    break unless saml_value.nil?
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
                  saml_value
         
     | 
| 
       19 
32 
     | 
    
         
             
                end
         
     | 
| 
       20 
33 
     | 
    
         | 
| 
       21 
34 
     | 
    
         
             
                def value_by_saml_attribute_key(key)
         
     | 
| 
         @@ -39,13 +39,15 @@ describe Devise::Models::SamlAuthenticatable do 
     | 
|
| 
       39 
39 
     | 
    
         | 
| 
       40 
40 
     | 
    
         
             
              before do
         
     | 
| 
       41 
41 
     | 
    
         
             
                allow(Rails).to receive(:root).and_return("/railsroot")
         
     | 
| 
       42 
     | 
    
         
            -
                allow(File).to receive(:read).with("/railsroot/config/attribute-map.yml").and_return( 
     | 
| 
      
 42 
     | 
    
         
            +
                allow(File).to receive(:read).with("/railsroot/config/attribute-map.yml").and_return(attributemap)
         
     | 
| 
      
 43 
     | 
    
         
            +
              end
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
              let(:attributemap) {<<-ATTRIBUTEMAP
         
     | 
| 
       43 
46 
     | 
    
         
             
            ---
         
     | 
| 
       44 
47 
     | 
    
         
             
            "saml-email-format": email
         
     | 
| 
       45 
48 
     | 
    
         
             
            "saml-name-format":  name
         
     | 
| 
       46 
49 
     | 
    
         
             
                  ATTRIBUTEMAP
         
     | 
| 
       47 
     | 
    
         
            -
               
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
      
 50 
     | 
    
         
            +
              }
         
     | 
| 
       49 
51 
     | 
    
         
             
              let(:response) { double(:response, attributes: attributes, name_id: name_id) }
         
     | 
| 
       50 
52 
     | 
    
         
             
              let(:attributes) {
         
     | 
| 
       51 
53 
     | 
    
         
             
                OneLogin::RubySaml::Attributes.new(
         
     | 
| 
         @@ -179,8 +181,8 @@ describe Devise::Models::SamlAuthenticatable do 
     | 
|
| 
       179 
181 
     | 
    
         
             
                end
         
     | 
| 
       180 
182 
     | 
    
         
             
              end
         
     | 
| 
       181 
183 
     | 
    
         | 
| 
       182 
     | 
    
         
            -
              context "when configured with a resource validator" do
         
     | 
| 
       183 
     | 
    
         
            -
                let(:validator_class) { double(" 
     | 
| 
      
 184 
     | 
    
         
            +
              context "when configured with a resource validator class" do
         
     | 
| 
      
 185 
     | 
    
         
            +
                let(:validator_class) { double("validator") }
         
     | 
| 
       184 
186 
     | 
    
         
             
                let(:validator) { double("validator") }
         
     | 
| 
       185 
187 
     | 
    
         
             
                let(:user) { Model.new(new_record: false) }
         
     | 
| 
       186 
188 
     | 
    
         | 
| 
         @@ -212,6 +214,41 @@ describe Devise::Models::SamlAuthenticatable do 
     | 
|
| 
       212 
214 
     | 
    
         
             
                end
         
     | 
| 
       213 
215 
     | 
    
         
             
              end
         
     | 
| 
       214 
216 
     | 
    
         | 
| 
      
 217 
     | 
    
         
            +
             
     | 
| 
      
 218 
     | 
    
         
            +
              context "when configured with a resource validator hook" do
         
     | 
| 
      
 219 
     | 
    
         
            +
                let(:validator_hook) { double("validator_hook") }
         
     | 
| 
      
 220 
     | 
    
         
            +
                let(:decorated_response) { ::SamlAuthenticatable::SamlResponse.new(response, YAML.load(attributemap)) }
         
     | 
| 
      
 221 
     | 
    
         
            +
                let(:user) { Model.new(new_record: false) }
         
     | 
| 
      
 222 
     | 
    
         
            +
             
     | 
| 
      
 223 
     | 
    
         
            +
                before do
         
     | 
| 
      
 224 
     | 
    
         
            +
                  allow(Devise).to receive(:saml_resource_validator_hook).and_return(validator_hook)
         
     | 
| 
      
 225 
     | 
    
         
            +
                  allow(::SamlAuthenticatable::SamlResponse).to receive(:new).with(response, YAML.load(attributemap)).and_return(decorated_response)
         
     | 
| 
      
 226 
     | 
    
         
            +
                end
         
     | 
| 
      
 227 
     | 
    
         
            +
             
     | 
| 
      
 228 
     | 
    
         
            +
                context "and sent a valid value" do
         
     | 
| 
      
 229 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 230 
     | 
    
         
            +
                    expect(validator_hook).to receive(:call).with(user, decorated_response, 'user@example.com').and_return(true)
         
     | 
| 
      
 231 
     | 
    
         
            +
                  end
         
     | 
| 
      
 232 
     | 
    
         
            +
             
     | 
| 
      
 233 
     | 
    
         
            +
                  it "returns the user" do
         
     | 
| 
      
 234 
     | 
    
         
            +
                    expect(Model).to receive(:where).with(email: 'user@example.com').and_return([user])
         
     | 
| 
      
 235 
     | 
    
         
            +
                    expect(Model.authenticate_with_saml(response, nil)).to eq(user)
         
     | 
| 
      
 236 
     | 
    
         
            +
                  end
         
     | 
| 
      
 237 
     | 
    
         
            +
                end
         
     | 
| 
      
 238 
     | 
    
         
            +
             
     | 
| 
      
 239 
     | 
    
         
            +
                context "and sent an invalid value" do
         
     | 
| 
      
 240 
     | 
    
         
            +
                  before do
         
     | 
| 
      
 241 
     | 
    
         
            +
                    expect(validator_hook).to receive(:call).with(user, decorated_response, 'user@example.com').and_return(false)
         
     | 
| 
      
 242 
     | 
    
         
            +
                  end
         
     | 
| 
      
 243 
     | 
    
         
            +
             
     | 
| 
      
 244 
     | 
    
         
            +
                  it "returns nil" do
         
     | 
| 
      
 245 
     | 
    
         
            +
                    expect(Model).to receive(:where).with(email: 'user@example.com').and_return([user])
         
     | 
| 
      
 246 
     | 
    
         
            +
                    expect(Model.authenticate_with_saml(response, nil)).to be_nil
         
     | 
| 
      
 247 
     | 
    
         
            +
                  end
         
     | 
| 
      
 248 
     | 
    
         
            +
                end
         
     | 
| 
      
 249 
     | 
    
         
            +
              end
         
     | 
| 
      
 250 
     | 
    
         
            +
             
     | 
| 
      
 251 
     | 
    
         
            +
             
     | 
| 
       215 
252 
     | 
    
         
             
              context "when configured to use a custom update hook" do
         
     | 
| 
       216 
253 
     | 
    
         
             
                it "can replicate the default behaviour in a custom hook" do
         
     | 
| 
       217 
254 
     | 
    
         
             
                  configure_hook do |user, saml_response|
         
     | 
| 
         @@ -0,0 +1,50 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'devise_saml_authenticatable/saml_mapped_attributes'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            describe SamlAuthenticatable::SamlMappedAttributes do
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:instance) { described_class.new(saml_attributes, attribute_map) }
         
     | 
| 
      
 6 
     | 
    
         
            +
              let(:attribute_map_file) { File.join(File.dirname(__FILE__), '../support/attribute-map.yml') }
         
     | 
| 
      
 7 
     | 
    
         
            +
              let(:attribute_map) { YAML.load(File.read(attribute_map_file)) }
         
     | 
| 
      
 8 
     | 
    
         
            +
              let(:saml_attributes) do
         
     | 
| 
      
 9 
     | 
    
         
            +
                {
         
     | 
| 
      
 10 
     | 
    
         
            +
                  "first_name" => ["John"],
         
     | 
| 
      
 11 
     | 
    
         
            +
                  "last_name"=>["Smith"],
         
     | 
| 
      
 12 
     | 
    
         
            +
                  "email"=>["john.smith@example.com"]
         
     | 
| 
      
 13 
     | 
    
         
            +
                }
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              describe "#value_by_resource_key" do
         
     | 
| 
      
 17 
     | 
    
         
            +
                RSpec.shared_examples "correctly maps the value of the resource key" do |saml_key, resource_key, expected_value|
         
     | 
| 
      
 18 
     | 
    
         
            +
                  subject(:perform) { instance.value_by_resource_key(resource_key) }
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
                  it "correctly maps the resource key, #{resource_key}, to the value of the '#{saml_key}' SAML key" do
         
     | 
| 
      
 21 
     | 
    
         
            +
                    saml_attributes[saml_key] = saml_attributes.delete(resource_key)
         
     | 
| 
      
 22 
     | 
    
         
            +
                    expect(perform).to eq(expected_value)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  end
         
     | 
| 
      
 24 
     | 
    
         
            +
                end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
                context "first_name" do
         
     | 
| 
      
 27 
     | 
    
         
            +
                  saml_keys = ['urn:mace:dir:attribute-def:first_name', 'first_name', 'firstName', 'firstname']
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
                  saml_keys.each do |saml_key|
         
     | 
| 
      
 30 
     | 
    
         
            +
                    include_examples 'correctly maps the value of the resource key', saml_key, 'first_name', ['John']
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                context 'last_name' do
         
     | 
| 
      
 35 
     | 
    
         
            +
                  saml_keys = ['urn:mace:dir:attribute-def:last_name', 'last_name', 'lastName', 'lastname']
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                  saml_keys.each do |saml_key|
         
     | 
| 
      
 38 
     | 
    
         
            +
                    include_examples 'correctly maps the value of the resource key', saml_key, 'last_name', ['Smith']
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
                end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                context 'email' do
         
     | 
| 
      
 43 
     | 
    
         
            +
                  saml_keys = ['urn:mace:dir:attribute-def:email', 'email_address', 'emailAddress', 'email']
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                  saml_keys.each do |saml_key|
         
     | 
| 
      
 46 
     | 
    
         
            +
                    include_examples 'correctly maps the value of the resource key', saml_key, 'email', ['john.smith@example.com']
         
     | 
| 
      
 47 
     | 
    
         
            +
                  end
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
              end
         
     | 
| 
      
 50 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -5,6 +5,7 @@ require 'uri' 
     | 
|
| 
       5 
5 
     | 
    
         
             
            require 'capybara/rspec'
         
     | 
| 
       6 
6 
     | 
    
         
             
            require 'capybara/poltergeist'
         
     | 
| 
       7 
7 
     | 
    
         
             
            Capybara.default_driver = :poltergeist
         
     | 
| 
      
 8 
     | 
    
         
            +
            Capybara.server = :webrick
         
     | 
| 
       8 
9 
     | 
    
         | 
| 
       9 
10 
     | 
    
         
             
            describe "SAML Authentication", type: :feature do
         
     | 
| 
       10 
11 
     | 
    
         
             
              let(:idp_port) { 8009 }
         
     | 
| 
         @@ -203,7 +204,7 @@ describe "SAML Authentication", type: :feature do 
     | 
|
| 
       203 
204 
     | 
    
         
             
                    fill_in "Email", with: "you@example.com"
         
     | 
| 
       204 
205 
     | 
    
         
             
                    fill_in "Password", with: "asdf"
         
     | 
| 
       205 
206 
     | 
    
         
             
                    click_on "Sign in"
         
     | 
| 
       206 
     | 
    
         
            -
                    expect(page).to have_content("Example Domain This domain is established to be used for illustrative examples in documents. You may use this domain in examples without prior coordination or asking for permission.")
         
     | 
| 
      
 207 
     | 
    
         
            +
                    expect(page).to have_content(:all, "Example Domain This domain is established to be used for illustrative examples in documents. You may use this domain in examples without prior coordination or asking for permission.")
         
     | 
| 
       207 
208 
     | 
    
         
             
                    expect(current_url).to eq("http://www.example.com/")
         
     | 
| 
       208 
209 
     | 
    
         
             
                  end
         
     | 
| 
       209 
210 
     | 
    
         
             
                end
         
     | 
| 
         @@ -220,7 +221,7 @@ describe "SAML Authentication", type: :feature do 
     | 
|
| 
       220 
221 
     | 
    
         
             
                fill_in "Email", with: "you@example.com"
         
     | 
| 
       221 
222 
     | 
    
         
             
                fill_in "Password", with: "asdf"
         
     | 
| 
       222 
223 
     | 
    
         
             
                click_on "Sign in"
         
     | 
| 
       223 
     | 
    
         
            -
                Timeout.timeout(Capybara. 
     | 
| 
      
 224 
     | 
    
         
            +
                Timeout.timeout(Capybara.default_max_wait_time) do
         
     | 
| 
       224 
225 
     | 
    
         
             
                  loop do
         
     | 
| 
       225 
226 
     | 
    
         
             
                    sleep 0.1
         
     | 
| 
       226 
227 
     | 
    
         
             
                    break if current_url == "http://localhost:8020/"
         
     | 
    
        data/spec/rails_helper.rb
    CHANGED
    
    | 
         @@ -8,7 +8,11 @@ require 'rspec/rails' 
     | 
|
| 
       8 
8 
     | 
    
         | 
| 
       9 
9 
     | 
    
         
             
            ActiveRecord::Migration.verbose = false
         
     | 
| 
       10 
10 
     | 
    
         
             
            ActiveRecord::Base.logger = Logger.new(nil)
         
     | 
| 
       11 
     | 
    
         
            -
            ActiveRecord:: 
     | 
| 
      
 11 
     | 
    
         
            +
            if ActiveRecord::Base.connection.respond_to?(:migration_context)
         
     | 
| 
      
 12 
     | 
    
         
            +
              ActiveRecord::Base.connection.migration_context.migrate
         
     | 
| 
      
 13 
     | 
    
         
            +
            else
         
     | 
| 
      
 14 
     | 
    
         
            +
              ActiveRecord::Migrator.migrate(File.expand_path("../support/sp/db/migrate/", __FILE__))
         
     | 
| 
      
 15 
     | 
    
         
            +
            end
         
     | 
| 
       12 
16 
     | 
    
         | 
| 
       13 
17 
     | 
    
         
             
            RSpec.configure do |config|
         
     | 
| 
       14 
18 
     | 
    
         
             
              config.use_transactional_fixtures = true
         
     | 
| 
         @@ -0,0 +1,102 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rails_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe 'SamlAuthenticatable Routes', type: :routing do
         
     | 
| 
      
 4 
     | 
    
         
            +
              describe 'GET /users/saml/sign_in (login)' do
         
     | 
| 
      
 5 
     | 
    
         
            +
                it 'routes to Devise::SamlSessionsController#new' do
         
     | 
| 
      
 6 
     | 
    
         
            +
                  expect(get: '/users/saml/sign_in').to route_to(controller: 'devise/saml_sessions', action: 'new')
         
     | 
| 
      
 7 
     | 
    
         
            +
                  expect(get: new_user_session_path).to route_to(controller: 'devise/saml_sessions', action: 'new')
         
     | 
| 
      
 8 
     | 
    
         
            +
                end
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              describe 'POST /users/saml/auth (session creation)' do
         
     | 
| 
      
 12 
     | 
    
         
            +
                it 'routes to Devise::SamlSessionsController#create' do
         
     | 
| 
      
 13 
     | 
    
         
            +
                  expect(post: '/users/saml/auth').to route_to(controller: 'devise/saml_sessions', action: 'create')
         
     | 
| 
      
 14 
     | 
    
         
            +
                end
         
     | 
| 
      
 15 
     | 
    
         
            +
              end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
              describe 'DELETE /users/sign_out (logout)' do
         
     | 
| 
      
 18 
     | 
    
         
            +
                it 'routes to Devise::SamlSessionsController#destroy' do
         
     | 
| 
      
 19 
     | 
    
         
            +
                  expect(delete: '/users/sign_out').to route_to(controller: 'devise/saml_sessions', action: 'destroy')
         
     | 
| 
      
 20 
     | 
    
         
            +
                  expect(delete: destroy_user_session_path).to route_to(controller: 'devise/saml_sessions', action: 'destroy')
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
              end
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
              describe 'GET /users/saml/metadata' do
         
     | 
| 
      
 25 
     | 
    
         
            +
                it 'routes to Devise::SamlSessionsController#metadata' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                  expect(get: '/users/saml/metadata').to route_to(controller: 'devise/saml_sessions', action: 'metadata')
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              describe 'GET /users/saml/idp_sign_out (IdP-initiated logout)' do
         
     | 
| 
      
 31 
     | 
    
         
            +
                it 'routes to Devise::SamlSessionsController#idp_sign_out' do
         
     | 
| 
      
 32 
     | 
    
         
            +
                  expect(get: '/users/saml/idp_sign_out').to route_to(controller: 'devise/saml_sessions', action: 'idp_sign_out')
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
              describe 'POST /users/saml/idp_sign_out (IdP-initiated logout)' do
         
     | 
| 
      
 37 
     | 
    
         
            +
                it 'routes to Devise::SamlSessionsController#idp_sign_out' do
         
     | 
| 
      
 38 
     | 
    
         
            +
                  expect(post: '/users/saml/idp_sign_out').to route_to(controller: 'devise/saml_sessions', action: 'idp_sign_out')
         
     | 
| 
      
 39 
     | 
    
         
            +
                end
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
              context 'when saml_route_helper_prefix is "sso"' do
         
     | 
| 
      
 43 
     | 
    
         
            +
                before(:all) do
         
     | 
| 
      
 44 
     | 
    
         
            +
                  ::Devise.saml_route_helper_prefix = 'sso'
         
     | 
| 
      
 45 
     | 
    
         
            +
             
     | 
| 
      
 46 
     | 
    
         
            +
                  # A very simple Rails engine
         
     | 
| 
      
 47 
     | 
    
         
            +
                  module SamlRouteHelperPrefixEngine
         
     | 
| 
      
 48 
     | 
    
         
            +
                    class Engine < ::Rails::Engine
         
     | 
| 
      
 49 
     | 
    
         
            +
                      isolate_namespace SamlRouteHelperPrefixEngine
         
     | 
| 
      
 50 
     | 
    
         
            +
                    end
         
     | 
| 
      
 51 
     | 
    
         
            +
             
     | 
| 
      
 52 
     | 
    
         
            +
                    Engine.routes.draw do
         
     | 
| 
      
 53 
     | 
    
         
            +
                      devise_for :users, module: :devise
         
     | 
| 
      
 54 
     | 
    
         
            +
                    end
         
     | 
| 
      
 55 
     | 
    
         
            +
                  end
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
                after(:all) do
         
     | 
| 
      
 58 
     | 
    
         
            +
                  ::Devise.saml_route_helper_prefix = nil
         
     | 
| 
      
 59 
     | 
    
         
            +
                end
         
     | 
| 
      
 60 
     | 
    
         
            +
                routes { SamlRouteHelperPrefixEngine::Engine.routes }
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                describe 'GET /users/saml/sign_in (login)' do
         
     | 
| 
      
 63 
     | 
    
         
            +
                  it 'routes to Devise::SamlSessionsController#new' do
         
     | 
| 
      
 64 
     | 
    
         
            +
                    expect(get: '/users/saml/sign_in').to route_to(controller: 'devise/saml_sessions', action: 'new')
         
     | 
| 
      
 65 
     | 
    
         
            +
                    expect(get: new_sso_user_session_path).to route_to(controller: 'devise/saml_sessions', action: 'new')
         
     | 
| 
      
 66 
     | 
    
         
            +
                  end
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                describe 'POST /users/saml/auth (session creation)' do
         
     | 
| 
      
 70 
     | 
    
         
            +
                  it 'routes to Devise::SamlSessionsController#create' do
         
     | 
| 
      
 71 
     | 
    
         
            +
                    expect(post: '/users/saml/auth').to route_to(controller: 'devise/saml_sessions', action: 'create')
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                describe 'DELETE /users/sign_out (logout)' do
         
     | 
| 
      
 76 
     | 
    
         
            +
                  it 'routes to Devise::SamlSessionsController#destroy' do
         
     | 
| 
      
 77 
     | 
    
         
            +
                    expect(delete: '/users/sign_out').to route_to(controller: 'devise/saml_sessions', action: 'destroy')
         
     | 
| 
      
 78 
     | 
    
         
            +
                    expect(delete: destroy_sso_user_session_path).to route_to(controller: 'devise/saml_sessions', action: 'destroy')
         
     | 
| 
      
 79 
     | 
    
         
            +
                  end
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
      
 82 
     | 
    
         
            +
                describe 'GET /users/saml/metadata' do
         
     | 
| 
      
 83 
     | 
    
         
            +
                  it 'routes to Devise::SamlSessionsController#metadata' do
         
     | 
| 
      
 84 
     | 
    
         
            +
                    expect(get: '/users/saml/metadata').to route_to(controller: 'devise/saml_sessions', action: 'metadata')
         
     | 
| 
      
 85 
     | 
    
         
            +
                  end
         
     | 
| 
      
 86 
     | 
    
         
            +
                end
         
     | 
| 
      
 87 
     | 
    
         
            +
             
     | 
| 
      
 88 
     | 
    
         
            +
                describe 'GET /users/saml/idp_sign_out (IdP-initiated logout)' do
         
     | 
| 
      
 89 
     | 
    
         
            +
                  it 'routes to Devise::SamlSessionsController#idp_sign_out' do
         
     | 
| 
      
 90 
     | 
    
         
            +
                    expect(get: '/users/saml/idp_sign_out').to route_to(controller: 'devise/saml_sessions', action: 'idp_sign_out')
         
     | 
| 
      
 91 
     | 
    
         
            +
                    expect(get: idp_destroy_sso_user_session_path).to route_to(controller: 'devise/saml_sessions', action: 'idp_sign_out')
         
     | 
| 
      
 92 
     | 
    
         
            +
                  end
         
     | 
| 
      
 93 
     | 
    
         
            +
                end
         
     | 
| 
      
 94 
     | 
    
         
            +
             
     | 
| 
      
 95 
     | 
    
         
            +
                describe 'POST /users/saml/idp_sign_out (IdP-initiated logout)' do
         
     | 
| 
      
 96 
     | 
    
         
            +
                  it 'routes to Devise::SamlSessionsController#idp_sign_out' do
         
     | 
| 
      
 97 
     | 
    
         
            +
                    expect(post: '/users/saml/idp_sign_out').to route_to(controller: 'devise/saml_sessions', action: 'idp_sign_out')
         
     | 
| 
      
 98 
     | 
    
         
            +
                    expect(post: idp_destroy_sso_user_session_path).to route_to(controller: 'devise/saml_sessions', action: 'idp_sign_out')
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
                end
         
     | 
| 
      
 101 
     | 
    
         
            +
              end
         
     | 
| 
      
 102 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,14 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            source 'https://rubygems.org'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            # Specify your gem's dependencies in devise_saml_authenticatable.gemspec
         
     | 
| 
      
 4 
     | 
    
         
            +
            gemspec path: '../..'
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            group :test do
         
     | 
| 
      
 7 
     | 
    
         
            +
              gem 'rake'
         
     | 
| 
      
 8 
     | 
    
         
            +
              gem 'rspec', '~> 3.0'
         
     | 
| 
      
 9 
     | 
    
         
            +
              gem 'rails', '~> 5.1.0'
         
     | 
| 
      
 10 
     | 
    
         
            +
              gem 'rspec-rails'
         
     | 
| 
      
 11 
     | 
    
         
            +
              gem 'sqlite3'
         
     | 
| 
      
 12 
     | 
    
         
            +
              gem 'capybara'
         
     | 
| 
      
 13 
     | 
    
         
            +
              gem 'poltergeist'
         
     | 
| 
      
 14 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,12 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            "urn:mace:dir:attribute-def:first_name": "first_name"
         
     | 
| 
      
 2 
     | 
    
         
            +
            "first_name": "first_name"
         
     | 
| 
      
 3 
     | 
    
         
            +
            "firstName": "first_name"
         
     | 
| 
      
 4 
     | 
    
         
            +
            "firstname": "first_name"
         
     | 
| 
      
 5 
     | 
    
         
            +
            "urn:mace:dir:attribute-def:last_name": "last_name"
         
     | 
| 
      
 6 
     | 
    
         
            +
            "last_name": "last_name"
         
     | 
| 
      
 7 
     | 
    
         
            +
            "lastName": "last_name"
         
     | 
| 
      
 8 
     | 
    
         
            +
            "lastname": "last_name"
         
     | 
| 
      
 9 
     | 
    
         
            +
            "urn:mace:dir:attribute-def:email": "email"
         
     | 
| 
      
 10 
     | 
    
         
            +
            "email_address": "email"
         
     | 
| 
      
 11 
     | 
    
         
            +
            "emailAddress": "email"
         
     | 
| 
      
 12 
     | 
    
         
            +
            "email": "email"
         
     | 
| 
         @@ -3,7 +3,9 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            @include_subject_in_attributes = ENV.fetch('INCLUDE_SUBJECT_IN_ATTRIBUTES')
         
     | 
| 
       4 
4 
     | 
    
         
             
            @valid_destination = ENV.fetch('VALID_DESTINATION', "true")
         
     | 
| 
       5 
5 
     | 
    
         | 
| 
       6 
     | 
    
         
            -
             
     | 
| 
      
 6 
     | 
    
         
            +
            if Rails::VERSION::MAJOR < 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR < 2)
         
     | 
| 
      
 7 
     | 
    
         
            +
              gsub_file 'config/secrets.yml', /secret_key_base:.*$/, 'secret_key_base: "34814fd41f91c493b89aa01ac73c44d241a31245b5bc5542fa4b7317525e1dcfa60ba947b3d085e4e229456fdee0d8af6aac6a63cf750d807ea6fe5d853dff4a"'
         
     | 
| 
      
 8 
     | 
    
         
            +
            end
         
     | 
| 
       7 
9 
     | 
    
         | 
| 
       8 
10 
     | 
    
         
             
            gem 'ruby-saml-idp', git: "https://github.com/lawrencepit/ruby-saml-idp.git", ref: "ec715b252e849105c7a96df27b731c6e7f725a51"
         
     | 
| 
       9 
11 
     | 
    
         
             
            gem 'thin'
         
     | 
    
        data/spec/support/rails_app.rb
    CHANGED
    
    | 
         @@ -17,7 +17,7 @@ rescue Errno::ESRCH 
     | 
|
| 
       17 
17 
     | 
    
         
             
            end
         
     | 
| 
       18 
18 
     | 
    
         | 
| 
       19 
19 
     | 
    
         
             
            def create_app(name, env = {})
         
     | 
| 
       20 
     | 
    
         
            -
              rails_new_options = %w(-T -J -S --skip-spring --skip-listen)
         
     | 
| 
      
 20 
     | 
    
         
            +
              rails_new_options = %w(-T -J -S --skip-spring --skip-listen --skip-bootsnap)
         
     | 
| 
       21 
21 
     | 
    
         
             
              rails_new_options << "-O" if name == 'idp'
         
     | 
| 
       22 
22 
     | 
    
         
             
              Dir.chdir(File.expand_path('../../support', __FILE__)) do
         
     | 
| 
       23 
23 
     | 
    
         
             
                FileUtils.rm_rf(name)
         
     | 
    
        data/spec/support/sp_template.rb
    CHANGED
    
    | 
         @@ -8,7 +8,9 @@ idp_settings_adapter = ENV.fetch('IDP_SETTINGS_ADAPTER', "nil") 
     | 
|
| 
       8 
8 
     | 
    
         
             
            idp_entity_id_reader = ENV.fetch('IDP_ENTITY_ID_READER', "DeviseSamlAuthenticatable::DefaultIdpEntityIdReader")
         
     | 
| 
       9 
9 
     | 
    
         
             
            saml_failed_callback = ENV.fetch('SAML_FAILED_CALLBACK', "nil")
         
     | 
| 
       10 
10 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
      
 11 
     | 
    
         
            +
            if Rails::VERSION::MAJOR < 5 || (Rails::VERSION::MAJOR == 5 && Rails::VERSION::MINOR < 2)
         
     | 
| 
      
 12 
     | 
    
         
            +
              gsub_file 'config/secrets.yml', /secret_key_base:.*$/, 'secret_key_base: "8b5889df1fcf03f76c7d66da02d8776bcc85b06bed7d9c592f076d9c8a5455ee6d4beae45986c3c030b40208db5e612f2a6ef8283036a352e3fae83c5eda36be"'
         
     | 
| 
      
 13 
     | 
    
         
            +
            end
         
     | 
| 
       12 
14 
     | 
    
         | 
| 
       13 
15 
     | 
    
         
             
            gem 'devise_saml_authenticatable', path: '../../..'
         
     | 
| 
       14 
16 
     | 
    
         
             
            gem 'ruby-saml', OneLogin::RubySaml::VERSION
         
     | 
    
        metadata
    CHANGED
    
    | 
         @@ -1,14 +1,14 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            --- !ruby/object:Gem::Specification
         
     | 
| 
       2 
2 
     | 
    
         
             
            name: devise_saml_authenticatable
         
     | 
| 
       3 
3 
     | 
    
         
             
            version: !ruby/object:Gem::Version
         
     | 
| 
       4 
     | 
    
         
            -
              version: 1. 
     | 
| 
      
 4 
     | 
    
         
            +
              version: 1.5.0
         
     | 
| 
       5 
5 
     | 
    
         
             
            platform: ruby
         
     | 
| 
       6 
6 
     | 
    
         
             
            authors:
         
     | 
| 
       7 
7 
     | 
    
         
             
            - Josef Sauter
         
     | 
| 
       8 
8 
     | 
    
         
             
            autorequire: 
         
     | 
| 
       9 
9 
     | 
    
         
             
            bindir: bin
         
     | 
| 
       10 
10 
     | 
    
         
             
            cert_chain: []
         
     | 
| 
       11 
     | 
    
         
            -
            date:  
     | 
| 
      
 11 
     | 
    
         
            +
            date: 2019-02-05 00:00:00.000000000 Z
         
     | 
| 
       12 
12 
     | 
    
         
             
            dependencies:
         
     | 
| 
       13 
13 
     | 
    
         
             
            - !ruby/object:Gem::Dependency
         
     | 
| 
       14 
14 
     | 
    
         
             
              name: devise
         
     | 
| 
         @@ -70,12 +70,16 @@ files: 
     | 
|
| 
       70 
70 
     | 
    
         
             
            - spec/devise_saml_authenticatable/default_idp_entity_id_reader_spec.rb
         
     | 
| 
       71 
71 
     | 
    
         
             
            - spec/devise_saml_authenticatable/model_spec.rb
         
     | 
| 
       72 
72 
     | 
    
         
             
            - spec/devise_saml_authenticatable/saml_config_spec.rb
         
     | 
| 
      
 73 
     | 
    
         
            +
            - spec/devise_saml_authenticatable/saml_mapped_attributes_spec.rb
         
     | 
| 
       73 
74 
     | 
    
         
             
            - spec/devise_saml_authenticatable/strategy_spec.rb
         
     | 
| 
       74 
75 
     | 
    
         
             
            - spec/features/saml_authentication_spec.rb
         
     | 
| 
       75 
76 
     | 
    
         
             
            - spec/rails_helper.rb
         
     | 
| 
      
 77 
     | 
    
         
            +
            - spec/routes/routes_spec.rb
         
     | 
| 
       76 
78 
     | 
    
         
             
            - spec/spec_helper.rb
         
     | 
| 
       77 
79 
     | 
    
         
             
            - spec/support/Gemfile.rails4
         
     | 
| 
       78 
80 
     | 
    
         
             
            - spec/support/Gemfile.rails5
         
     | 
| 
      
 81 
     | 
    
         
            +
            - spec/support/Gemfile.rails5.1
         
     | 
| 
      
 82 
     | 
    
         
            +
            - spec/support/attribute-map.yml
         
     | 
| 
       79 
83 
     | 
    
         
             
            - spec/support/idp_settings_adapter.rb.erb
         
     | 
| 
       80 
84 
     | 
    
         
             
            - spec/support/idp_template.rb
         
     | 
| 
       81 
85 
     | 
    
         
             
            - spec/support/rails_app.rb
         
     | 
| 
         @@ -112,12 +116,16 @@ test_files: 
     | 
|
| 
       112 
116 
     | 
    
         
             
            - spec/devise_saml_authenticatable/default_idp_entity_id_reader_spec.rb
         
     | 
| 
       113 
117 
     | 
    
         
             
            - spec/devise_saml_authenticatable/model_spec.rb
         
     | 
| 
       114 
118 
     | 
    
         
             
            - spec/devise_saml_authenticatable/saml_config_spec.rb
         
     | 
| 
      
 119 
     | 
    
         
            +
            - spec/devise_saml_authenticatable/saml_mapped_attributes_spec.rb
         
     | 
| 
       115 
120 
     | 
    
         
             
            - spec/devise_saml_authenticatable/strategy_spec.rb
         
     | 
| 
       116 
121 
     | 
    
         
             
            - spec/features/saml_authentication_spec.rb
         
     | 
| 
       117 
122 
     | 
    
         
             
            - spec/rails_helper.rb
         
     | 
| 
      
 123 
     | 
    
         
            +
            - spec/routes/routes_spec.rb
         
     | 
| 
       118 
124 
     | 
    
         
             
            - spec/spec_helper.rb
         
     | 
| 
       119 
125 
     | 
    
         
             
            - spec/support/Gemfile.rails4
         
     | 
| 
       120 
126 
     | 
    
         
             
            - spec/support/Gemfile.rails5
         
     | 
| 
      
 127 
     | 
    
         
            +
            - spec/support/Gemfile.rails5.1
         
     | 
| 
      
 128 
     | 
    
         
            +
            - spec/support/attribute-map.yml
         
     | 
| 
       121 
129 
     | 
    
         
             
            - spec/support/idp_settings_adapter.rb.erb
         
     | 
| 
       122 
130 
     | 
    
         
             
            - spec/support/idp_template.rb
         
     | 
| 
       123 
131 
     | 
    
         
             
            - spec/support/rails_app.rb
         
     |