saml_camel 0.1.4 → 0.1.5
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/README.md +8 -1
- data/app/controllers/concerns/saml_camel/saml_helpers.rb +32 -23
- data/app/controllers/saml_camel/saml_controller.rb +21 -9
- data/app/models/saml_camel/logging.rb +7 -0
- data/config/routes.rb +2 -0
- data/lib/saml_camel/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60103dee96fb0b95caeb04551deac81568e5149a
|
4
|
+
data.tar.gz: eb15b9fc8c642e88bf0ff8be268f206de1be3b73
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: acda10e48b2cabdb24f187ffaf3fde6dbb5992efe032f56ca623098999b754c9094fe94271cbeac50097f00679a87710db95ebe96be7a22b0904607a7b62c165
|
7
|
+
data.tar.gz: 8ea077c92e5d0fcf0df9bcae2d086a5635152ceb3d37afbc7a0e7e4777a3d9dda32b651280d9bc54f12ecdf4f859c640c658e68ff972521d0473e25f9d465233
|
data/README.md
CHANGED
@@ -14,6 +14,13 @@ $ bundle
|
|
14
14
|
|
15
15
|
|
16
16
|
## Usage
|
17
|
+
### IMPORTANT!
|
18
|
+
1. in your environments config (`config/development.rb` for example) ensure that you have caching configured as follows
|
19
|
+
```ruby
|
20
|
+
config.action_controller.perform_caching = true
|
21
|
+
config.cache_store = :memory_store
|
22
|
+
```
|
23
|
+
|
17
24
|
1. run `rake saml_camel:generate_saml` to generate metadata files for each environment. you can also specify a specifc/custom environment like this `rake saml_camel:generate_saml environment=acceptance`
|
18
25
|
|
19
26
|
**Note: these steps will use development as an example, if you use seperate metadata per environemtn, you will repeat each step for your chosed environement**
|
@@ -57,7 +64,7 @@ end
|
|
57
64
|
```
|
58
65
|
|
59
66
|
|
60
|
-
7. to logout simply make a post to `localhost:3000/saml/logout`. This will kill the local saml session, and the session with the identity provider.
|
67
|
+
7. to logout simply make a post to `localhost:3000/saml/logout`. This will kill the local saml session, and the session with the identity provider.
|
61
68
|
|
62
69
|
7. response attributes found in `session[:saml_attributes]`
|
63
70
|
|
@@ -8,39 +8,48 @@ module SamlCamel::SamlHelpers
|
|
8
8
|
#this generates a call to the idp, which will then be returned to the consume action the in saml_contorller
|
9
9
|
def saml_request(host_request)
|
10
10
|
relay_state = SecureRandom.base64.chomp.gsub( /\n/, '' ) #set relay state to secure against replay attack
|
11
|
-
session[:relay_state] = relay_state
|
12
11
|
request = OneLogin::RubySaml::Authrequest.new
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
}
|
20
|
-
|
21
|
-
cookies.encrypted[:saml_camel_relay] = {
|
22
|
-
value: relay_state,
|
23
|
-
secure: secure_cookie,
|
24
|
-
httponly: true
|
25
|
-
}
|
26
|
-
|
27
|
-
saml_request = request.create(SamlCamel::Transaction.saml_settings) + "&RelayState=#{relay_state}"
|
28
|
-
redirect_to(saml_request)
|
13
|
+
#store relay state, ip address and original url request in memory to be used for verification and redirect after response
|
14
|
+
permit_key = session[:session_id].to_sym
|
15
|
+
Rails.cache.fetch(permit_key, expires_in: 5.minutes) do
|
16
|
+
{ip_address: host_request.remote_ip, relay_state: relay_state, redirect_url: host_request.url }
|
17
|
+
end
|
18
|
+
saml_request_url = request.create(SamlCamel::Transaction.saml_settings) + "&RelayState=#{Rails.cache.fetch(permit_key)[:relay_state]}"
|
19
|
+
redirect_to(saml_request_url)
|
29
20
|
end
|
30
21
|
|
31
22
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
23
|
+
#validates the user ip address and relay state given to IDP. Prevents Replay Attacks.
|
24
|
+
def valid_state(param_relay_state, remote_ip)
|
25
|
+
permit_key = session[:session_id].to_sym
|
26
|
+
saml_cache = Rails.cache.fetch(permit_key)
|
27
|
+
stored_relay = saml_cache[:relay_state]
|
28
|
+
stored_ip = saml_cache[:ip_address]
|
29
|
+
|
30
|
+
SamlCamel::Logging.saml_state({stored_relay: stored_relay, request_relay: param_relay_state, stored_ip: stored_ip, remote_ip: remote_ip})
|
31
|
+
param_relay_state == stored_relay && remote_ip == stored_ip
|
36
32
|
end
|
37
33
|
|
38
34
|
|
39
|
-
|
40
|
-
|
41
|
-
|
35
|
+
#Make it so sp sessions only last 1 hour, sp_session is set on a succesfull saml response.
|
36
|
+
#We check that the session time is less than in hour if so we refresh, otherwise we delete the session
|
37
|
+
def expired_session?
|
38
|
+
if session[:sp_session]
|
39
|
+
if (Time.now - Time.parse(session[:sp_session])) < 1.hour
|
40
|
+
session[:sp_session] = Time.now
|
41
|
+
return true
|
42
|
+
end
|
43
|
+
end
|
42
44
|
end
|
43
45
|
|
44
46
|
|
47
|
+
#saml_protect is what is called in the app. it initiates the saml request if there is no active session, or if a user has been idle for over an hour
|
48
|
+
#TODO re-factor in future
|
49
|
+
def saml_protect
|
50
|
+
not_expired = expired_session?
|
51
|
+
saml_request(request) unless (session[:saml_success] || session[:sp_session] || not_expired) #keeps us from looping, and maintains sp session
|
52
|
+
session[:saml_success] = nil
|
53
|
+
end
|
45
54
|
|
46
55
|
end
|
@@ -7,30 +7,34 @@ module SamlCamel
|
|
7
7
|
before_action :saml_protect, only: [:attr_check]
|
8
8
|
|
9
9
|
|
10
|
-
#
|
10
|
+
#convinence route to see attributes that are coming through
|
11
11
|
def index
|
12
12
|
@attributes = session[:saml_attributes]
|
13
13
|
end
|
14
14
|
|
15
|
-
def consume
|
16
|
-
raise "Invalid RelayState" unless valid_relay_state(params[:RelayState])
|
17
|
-
redirect_path = cookies.encrypted[:saml_camel_redirect]
|
18
15
|
|
19
|
-
|
16
|
+
#consumes the saml response from the IDP
|
17
|
+
def consume
|
18
|
+
raise "Invalid RelayState" unless valid_state(params[:RelayState], request.remote_ip)
|
19
|
+
permit_key = session[:session_id].to_sym
|
20
|
+
redirect_path = Rails.cache.fetch(permit_key)[:redirect_url]
|
21
|
+
Rails.cache.delete(permit_key) #we no longer need cache at this stage
|
20
22
|
response = OneLogin::RubySaml::Response.new(params[:SAMLResponse], :settings => saml_settings)
|
21
23
|
response.settings = saml_settings
|
22
|
-
|
23
24
|
if response.is_valid? # validate the SAML Response
|
24
25
|
# authorize_success, log the user
|
25
26
|
session[:saml_success] = true
|
26
|
-
session[:sp_session] =
|
27
|
+
session[:sp_session] = Time.now
|
28
|
+
|
27
29
|
session[:saml_attributes] = SamlCamel::Transaction.map_attributes(response.attributes)
|
28
30
|
SamlCamel::Logging.successfull_auth(session[:saml_attributes])
|
29
31
|
|
30
32
|
#TODO account for nil redirect
|
31
33
|
redirect_to redirect_path
|
32
34
|
else # otherwise list out the errors in the response
|
33
|
-
|
35
|
+
permit_key = session[:session_id].to_sym
|
36
|
+
Rails.cache.delete(permit_key)
|
37
|
+
|
34
38
|
session[:saml_success] = false
|
35
39
|
response.errors
|
36
40
|
SamlCamel::Logging.auth_failure(response.errors)
|
@@ -38,25 +42,33 @@ module SamlCamel
|
|
38
42
|
redirect_to main_app.try('root_path')
|
39
43
|
end
|
40
44
|
rescue => e
|
45
|
+
permit_key = session[:session_id].to_sym
|
46
|
+
Rails.cache.delete(permit_key)
|
41
47
|
session[:saml_success] = false
|
48
|
+
|
42
49
|
SamlCamel::Logging.auth_failure(e)
|
43
50
|
redirect_to action: "failure", locals:{errors: e}
|
44
51
|
end
|
45
52
|
|
53
|
+
|
54
|
+
#route to show saml failures
|
46
55
|
def failure
|
47
56
|
@error = params[:locals][:errors]
|
48
|
-
# byebug
|
49
57
|
end
|
50
58
|
|
59
|
+
|
60
|
+
#kills SP session and redirects to IDP to kill idp session
|
51
61
|
def logout
|
52
62
|
SamlCamel::Logging.logout(session[:saml_attributes])
|
53
63
|
session[:saml_attributes] = nil
|
54
64
|
session[:sp_session] = nil
|
65
|
+
cookies.delete :saml_camel_timestamp
|
55
66
|
|
56
67
|
# return_url = SamlCamel::Transaction.logout #this methods logs the user out of the IDP, and returns a url to be redirected to
|
57
68
|
redirect_to "https://shib.oit.duke.edu/cgi-bin/logout.pl"
|
58
69
|
end
|
59
70
|
|
71
|
+
|
60
72
|
def attr_check
|
61
73
|
end
|
62
74
|
|
@@ -25,5 +25,12 @@ module SamlCamel
|
|
25
25
|
logger.debug("Unknown error logging user logout. Most likely anonymous user clicked a logout button.")
|
26
26
|
end
|
27
27
|
|
28
|
+
def self.saml_state(data)
|
29
|
+
logger = Logger.new("log/saml.log")
|
30
|
+
logger.info("Stored Relay: #{data[:stored_relay]} | RequestRelay: #{data[:request_relay]} | Stored IP: #{data[:stored_ip]} RemoteIP: #{data[:remote_ip]}")
|
31
|
+
rescue
|
32
|
+
logger.debug("Unknown Error During relay state logging.")
|
33
|
+
end
|
34
|
+
|
28
35
|
end
|
29
36
|
end
|
data/config/routes.rb
CHANGED
data/lib/saml_camel/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: saml_camel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 'Danai Adkisson '
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-04-
|
11
|
+
date: 2018-04-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|