saml_camel 0.1.4 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|