spid-es 0.0.7 → 0.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/README.md +76 -73
- data/lib/spid/ruby-saml/authrequest.rb +33 -26
- data/lib/spid/ruby-saml/logout_request.rb +2 -2
- data/lib/spid/ruby-saml/logout_response.rb +2 -2
- data/lib/spid/ruby-saml/metadata.rb +12 -11
- data/lib/spid/ruby-saml/response.rb +46 -6
- data/lib/spid/ruby-saml/settings.rb +2 -2
- data/lib/spid/ruby-saml/utils.rb +1 -1
- data/lib/spid/xml_security.rb +166 -0
- data/lib/spid/xml_security_new.rb +373 -0
- data/lib/spid-es.rb +1 -1
- data/spid-es.gemspec +1 -1
- data/test/response_test.rb +2 -2
- data/test/xml_security_test.rb +10 -10
- metadata +4 -4
- data/lib/xml_security.rb +0 -165
- data/lib/xml_security_new.rb +0 -374
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
MDMxZWQyMjdjMjFjMjRjNWQyODI3ZjgzNWUzZDMyOWEzNTJmYzM5ZA==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
M2FkYzdiYzU5NThkNDA1ODM2MzVmMThmMmY4MTY0MTEwZDg0ZmRjNA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZGExNjg1YTM2NGQ0ZjkzOTk2ZjM0MDBkYWI2MjRhMzg5OTFjOWQ2YjY1ZDM0
|
10
|
+
OTY3NjVlMDg0NTIxNTlkMGQ3MTk0YWM2ZjA2N2Y5ZjMwMjIzYWQzMzZkMzgz
|
11
|
+
NWMxNjljODczY2JhMzRkZGVkM2JjZTBkMjMxOTkzMzhjODJiMTE=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NjcwYzc5NTcwOGQyMzRkMTI4Y2E5ZDZlMmJmZjJhNzA4OWE2YjgzZDEwMzg0
|
14
|
+
NmE1OThiNDc4MzIxMzM2MTJiNmYwZTE4ZWNkNjdlNDA5Y2M0MTE5NDhiODI2
|
15
|
+
ZWU5NzA3ZjM2MjJmNmJhYzc2Yjg4MmQ2ZTlkMGMzYWUyMWNmMDI=
|
data/README.md
CHANGED
@@ -1,94 +1,109 @@
|
|
1
1
|
# SPID Euro Servizi
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
La libreria è un fork della libreria Ruby SAML e serve per l'integrazione di un client (Service Provider) con l'autenticazione SPID (Sistema Pubblico di Identità Digitale)
|
4
|
+
Utilizza lo standard SAML 2 come previsto dalla normativa (Regole tecniche v1. http://www.agid.gov.it/sites/default/files/circolari/spid-regole_tecniche_v1.pdf)
|
5
5
|
|
6
6
|
|
7
|
-
##
|
7
|
+
## Fase iniziale
|
8
8
|
|
9
|
-
|
9
|
+
Azione di partenza in cui viene creata la request da inviare all'idp e viene fatto un redirect all'identity provider.
|
10
10
|
|
11
11
|
```ruby
|
12
12
|
def init
|
13
|
-
#
|
13
|
+
#creo un istanza di Spid::Saml::Authrequest
|
14
|
+
saml_settings = get_saml_settings
|
14
15
|
#create an instance of Spid::Saml::Authrequest
|
15
|
-
request = Spid::Saml::Authrequest.new(
|
16
|
+
request = Spid::Saml::Authrequest.new(saml_settings)
|
16
17
|
auth_request = request.create
|
17
18
|
# Based on the IdP metadata, select the appropriate binding
|
18
19
|
# and return the action to perform to the controller
|
19
|
-
meta = Spid::Saml::Metadata.new(
|
20
|
+
meta = Spid::Saml::Metadata.new(saml_settings)
|
20
21
|
signature = get_signature(auth_request.uuid,auth_request.request,"http://www.w3.org/2001/04/xmldsig-more#rsa-sha256")
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
sso_request = meta.create_sso_request( auth_request.request, { :RelayState => request.uuid,
|
23
|
+
:SigAlg => "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256",
|
24
|
+
:Signature => signature } )
|
25
|
+
redirect_to sso_request
|
25
26
|
end
|
26
27
|
|
27
|
-
|
28
|
+
```
|
29
|
+
## Generazione della firma
|
30
|
+
|
31
|
+
```ruby
|
28
32
|
def get_signature(relayState, request, sigAlg)
|
29
|
-
#url encode
|
33
|
+
#url encode relayState
|
30
34
|
relayState_encoded = escape(relayState)
|
31
|
-
|
32
|
-
#deflate and base64 of samlrequest
|
35
|
+
#deflate e base64 della samlrequest
|
33
36
|
deflate_request_B64 = encode(deflate(request))
|
34
|
-
|
35
|
-
#url encode of samlrequest
|
37
|
+
#url encode della samlrequest
|
36
38
|
deflate_request_B64_encoded = escape(deflate_request_B64)
|
37
|
-
|
38
|
-
#url encode of sigAlg
|
39
|
+
#url encode della sigAlg
|
39
40
|
sigAlg_encoded = escape(sigAlg)
|
40
|
-
|
41
41
|
querystring="SAMLRequest=#{deflate_request_B64_encoded}&RelayState=#{relayState_encoded}&SigAlg=#{sigAlg_encoded}"
|
42
|
-
|
43
|
-
|
42
|
+
#puts "**QUERYSTRING** = "+querystring
|
43
|
+
digest = OpenSSL::Digest::SHA256.new(querystring.strip) #sha2 a 256
|
44
|
+
chiave_privata = xxxxxx #path della chiave privata con cui firmare
|
45
|
+
pk = OpenSSL::PKey::RSA.new File.read(chiave_privata) #chiave privata
|
44
46
|
qssigned = pk.sign(digest,querystring.strip)
|
45
47
|
Base64.encode64(qssigned).gsub(/\n/, "")
|
46
|
-
end
|
48
|
+
end
|
47
49
|
```
|
48
50
|
|
49
51
|
|
50
|
-
|
52
|
+
Questo metodo è l'endpoint impostato a livello di metadata del service provider come 'assertion consumer', riceve la response saml con i dati di registrazione fatta su SPID dagli utenti.
|
51
53
|
|
52
54
|
```ruby
|
53
|
-
def
|
54
|
-
#
|
55
|
+
def assertion_consumer
|
56
|
+
#id dell' idp che manda response (es: 'infocert','poste')
|
57
|
+
provider_id = @request.params['ProviderID']
|
58
|
+
#response saml inviata dall'idp
|
55
59
|
saml_response = @request.params['SAMLResponse']
|
56
60
|
if !saml_response.nil?
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
61
|
+
#assegno i settaggi
|
62
|
+
settings = get_saml_settings
|
63
|
+
#creo un oggetto response
|
64
|
+
response = Spid::Saml::Response.new(saml_response)
|
65
|
+
#assegno alla response i settaggi
|
66
|
+
response.settings = settings
|
67
|
+
#estraggo dal Base64 l'xml
|
68
|
+
saml_response_dec = Base64.decode64(saml_response)
|
69
|
+
#puts "**SAML RESPONSE DECODIFICATA: #{saml_response_dec}"
|
70
|
+
|
71
|
+
#validation of response
|
72
|
+
if response.is_valid?
|
73
|
+
attributi_utente = response.attributes
|
74
|
+
...
|
75
|
+
else
|
76
|
+
#autenticazione fallita!
|
77
|
+
end
|
69
78
|
end
|
70
79
|
end
|
71
80
|
```
|
72
81
|
|
73
|
-
|
82
|
+
Questo metodo va a impostare le varie configurazioni che servono per connettersi ad un idp. ( NB: nel caso di SPID ci sono vari idp (Poste, TIM, Info Cert) )
|
74
83
|
|
75
84
|
```ruby
|
76
85
|
def get_saml_settings
|
77
86
|
settings = Spid::Saml::Settings.new
|
78
|
-
settings.assertion_consumer_service_url
|
79
|
-
settings.issuer
|
80
|
-
settings.sp_cert
|
81
|
-
settings.
|
82
|
-
settings.
|
83
|
-
settings.
|
84
|
-
settings.
|
85
|
-
settings.
|
86
|
-
settings.
|
87
|
-
settings.
|
88
|
-
settings.
|
89
|
-
|
90
|
-
settings.
|
91
|
-
settings.
|
87
|
+
settings.assertion_consumer_service_url #= ...String, url dell' assertion consumer al quale arriva la response dell' idp.
|
88
|
+
settings.issuer #= ...String, host del service provider o url dei metadata.
|
89
|
+
settings.sp_cert #= ...String, path del certificato pubblico in formato pem.
|
90
|
+
settings.sp_private_key #= ...String, path della chiave privata in formato pem.
|
91
|
+
settings.single_logout_service_url #= ...String, url del servizio di logout dell'idp.
|
92
|
+
settings.sp_name_qualifier #= ...String, nome qualificato del service provider o url dei metadata.
|
93
|
+
settings.idp_name_qualifier #= ...String, nome qualificato dell' identity provider o url dei metadata dell' idp.
|
94
|
+
settings.name_identifier_format #= ...Array, formato di nomi ( impostare: ["urn:oasis:names:tc:SAML:2.0:nameid-format:transient"] ).
|
95
|
+
settings.destination_service_url #= ...String, url del servizio per l'identity provider, usato come proxy per il sso.
|
96
|
+
settings.single_logout_destination #= ...String, url di destinazione per la request logout.
|
97
|
+
settings.authn_context #= ...Array, tipi di autorizzazioni permesse (impostare: ["urn:oasis:names:tc:SAML:2.0:ac:classes:Smartcard",
|
98
|
+
"urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport"]).
|
99
|
+
settings.requester_identificator #= ...Array con id dei richiedenti (non usato).
|
100
|
+
settings.skip_validation #= ...Bool, imposta se evitare la validazione della response o delle asserzioni (false).
|
101
|
+
settings.idp_sso_target_url #= ...String, url target del sso dell' identity provider.
|
102
|
+
settings.idp_metadata #= ...String, url dei metadata dell' idp.
|
103
|
+
settings.requested_attribute #= ...Array, contiene i nomi dei campi richiesti dal servizio nei metadata.
|
104
|
+
settings.metadata_signed #= ...String, imposta se firmare i metadata.
|
105
|
+
settings.organization #= ...Hash, contiene nome breve (org_name), nome esteso (org_display_name) e url (org_url)
|
106
|
+
dell' organizzazione fornitore di servizi.
|
92
107
|
settings
|
93
108
|
end
|
94
109
|
```
|
@@ -97,28 +112,16 @@ In the above there are a few assumptions in place, one being that the response.n
|
|
97
112
|
|
98
113
|
## Service Provider Metadata
|
99
114
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
The class Onelogin::Saml::Metdata takes care of this by reading the Settings and returning XML. All
|
104
|
-
you have to do is add a controller to return the data, then give this URL to the IdP administrator.
|
105
|
-
The metdata will be polled by the IdP every few minutes, so updating your settings should propagate
|
106
|
-
to the IdP settings.
|
115
|
+
Per una relazione sicura con l'idp, il Service Provider deve fornire i metadata in formato xml.
|
116
|
+
La classe Spid::Saml::Metadata legge i settaggi e fornisce l'xml richiesto dagli idp.
|
107
117
|
|
108
118
|
```ruby
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
119
|
+
def sp_metadata
|
120
|
+
settings = get_saml_settings
|
121
|
+
meta = Spid::Saml::Metadata.new
|
122
|
+
|
123
|
+
@response.headers['Content-Type'] = 'application/samlmetadata+xml'
|
124
|
+
$out << meta.generate(settings)
|
115
125
|
end
|
116
|
-
end
|
117
126
|
```
|
118
127
|
|
119
|
-
## Note on Patches/Pull Requests
|
120
|
-
|
121
|
-
* Fork the project.
|
122
|
-
* Make your feature addition or bug fix.
|
123
|
-
* Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
|
124
|
-
* Send me a pull request.
|
@@ -27,30 +27,33 @@ module Spid::Saml
|
|
27
27
|
time = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
|
28
28
|
self.issue_instant = time
|
29
29
|
# Create AuthnRequest root element using REXML
|
30
|
-
request_doc =
|
30
|
+
request_doc = Spid::XMLSecurityNew::Document.new
|
31
31
|
request_doc.context[:attribute_quote] = :quote
|
32
|
-
root = request_doc.add_element "saml2p:AuthnRequest", { "xmlns:saml2p" => "urn:oasis:names:tc:SAML:2.0:protocol"
|
32
|
+
root = request_doc.add_element "saml2p:AuthnRequest", { "xmlns:saml2p" => "urn:oasis:names:tc:SAML:2.0:protocol",
|
33
|
+
"xmlns:saml" => "urn:oasis:names:tc:SAML:2.0:assertion"
|
34
|
+
}
|
33
35
|
root.attributes['ID'] = uuid
|
34
36
|
root.attributes['IssueInstant'] = time
|
35
37
|
root.attributes['Version'] = "2.0"
|
36
|
-
root.attributes['ProtocolBinding'] = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
37
|
-
root.attributes['AttributeConsumingServiceIndex'] = "
|
38
|
-
root.attributes['ForceAuthn'] = "
|
38
|
+
#root.attributes['ProtocolBinding'] = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST"
|
39
|
+
root.attributes['AttributeConsumingServiceIndex'] = "0"
|
40
|
+
root.attributes['ForceAuthn'] = "true"
|
39
41
|
#root.attributes['IsPassive'] = "false"
|
40
42
|
#usato AssertionConsumerServiceURL e ProtocolBinding in alternativa, pag 8 regole tecniche
|
41
|
-
|
43
|
+
root.attributes['AssertionConsumerServiceIndex'] = "0"
|
42
44
|
|
43
|
-
#
|
44
|
-
|
45
|
-
|
46
|
-
|
45
|
+
#Tolto, utilizzo AssertionConsumerServiceIndex
|
46
|
+
# # Conditionally defined elements based on settings
|
47
|
+
# if @settings.assertion_consumer_service_url != nil
|
48
|
+
# root.attributes["AssertionConsumerServiceURL"] = @settings.assertion_consumer_service_url
|
49
|
+
# end
|
47
50
|
|
48
51
|
if @settings.destination_service_url != nil
|
49
52
|
root.attributes["Destination"] = @settings.destination_service_url
|
50
53
|
end
|
51
54
|
|
52
55
|
if @settings.issuer != nil
|
53
|
-
issuer = root.add_element "
|
56
|
+
issuer = root.add_element "saml:Issuer"
|
54
57
|
issuer.attributes['NameQualifier'] = @settings.issuer
|
55
58
|
issuer.attributes['Format'] = "urn:oasis:names:tc:SAML:2.0:nameid-format:entity"
|
56
59
|
issuer.text = @settings.issuer
|
@@ -58,8 +61,8 @@ module Spid::Saml
|
|
58
61
|
|
59
62
|
#opzionale
|
60
63
|
if @settings.sp_name_qualifier != nil
|
61
|
-
subject = root.add_element "
|
62
|
-
name_id = subject.add_element "
|
64
|
+
subject = root.add_element "saml:Subject"
|
65
|
+
name_id = subject.add_element "saml:NameID"
|
63
66
|
name_id.attributes['Format'] = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
|
64
67
|
name_id.attributes['NameQualifier'] = @settings.sp_name_qualifier
|
65
68
|
end
|
@@ -70,8 +73,7 @@ module Spid::Saml
|
|
70
73
|
root.add_element "saml2p:NameIDPolicy", {
|
71
74
|
# Might want to make AllowCreate a setting?
|
72
75
|
#{}"AllowCreate" => "true",
|
73
|
-
"Format" => @settings.name_identifier_format[
|
74
|
-
"SPNameQualifier" => @settings.sp_name_qualifier
|
76
|
+
"Format" => @settings.name_identifier_format[0]
|
75
77
|
}
|
76
78
|
end
|
77
79
|
|
@@ -80,13 +82,11 @@ module Spid::Saml
|
|
80
82
|
# the IdP will choose default rules for authentication. (Shibboleth IdP)
|
81
83
|
if @settings.authn_context != nil
|
82
84
|
requested_context = root.add_element "saml2p:RequestedAuthnContext", {
|
83
|
-
"Comparison" => "
|
85
|
+
"Comparison" => "minimum"
|
84
86
|
}
|
85
87
|
context_class = []
|
86
88
|
@settings.authn_context.each_with_index{ |context, index|
|
87
|
-
context_class[index] = requested_context.add_element "
|
88
|
-
"xmlns:saml2" => "urn:oasis:names:tc:SAML:2.0:assertion"
|
89
|
-
}
|
89
|
+
context_class[index] = requested_context.add_element "saml:AuthnContextClassRef"
|
90
90
|
context_class[index].text = context
|
91
91
|
}
|
92
92
|
|
@@ -104,13 +104,20 @@ module Spid::Saml
|
|
104
104
|
|
105
105
|
end
|
106
106
|
|
107
|
-
request_doc << REXML::XMLDecl.new(
|
108
|
-
|
109
|
-
#
|
110
|
-
|
111
|
-
|
112
|
-
@
|
113
|
-
|
107
|
+
request_doc << REXML::XMLDecl.new("1.0", "UTF-8")
|
108
|
+
|
109
|
+
#LA FIRMA VA MESSA SOLO NEL CASO CON HTTP POST
|
110
|
+
# cert = @settings.get_sp_cert
|
111
|
+
# # embed signature
|
112
|
+
# if @settings.metadata_signed && @settings.sp_private_key && @settings.sp_cert
|
113
|
+
# private_key = @settings.get_sp_key
|
114
|
+
# request_doc.sign_document(private_key, cert)
|
115
|
+
# end
|
116
|
+
|
117
|
+
# stampo come stringa semplice i metadata per non avere problemi con validazione firma
|
118
|
+
#ret = request_doc.to_s
|
119
|
+
|
120
|
+
@request = request_doc.to_s
|
114
121
|
|
115
122
|
#Logging.debug "Created AuthnRequest: #{@request}"
|
116
123
|
|
@@ -22,12 +22,12 @@ module Spid::Saml
|
|
22
22
|
# The IdP sent us a LogoutRequest (IdP initiated SLO)
|
23
23
|
else
|
24
24
|
begin
|
25
|
-
@request = XMLSecurity::SignedDocument.new( decode( opt[:request] ))
|
25
|
+
@request = Spid::XMLSecurity::SignedDocument.new( decode( opt[:request] ))
|
26
26
|
raise if @request.nil?
|
27
27
|
raise if @request.root.nil?
|
28
28
|
raise if @request.root.namespace != PROTOCOL
|
29
29
|
rescue
|
30
|
-
@request = XMLSecurity::SignedDocument.new( inflate( decode( opt[:request] ) ) )
|
30
|
+
@request = Spid::XMLSecurity::SignedDocument.new( inflate( decode( opt[:request] ) ) )
|
31
31
|
end
|
32
32
|
Logging.debug "LogoutRequest is: \n#{@request}"
|
33
33
|
end
|
@@ -16,7 +16,7 @@ module Spid
|
|
16
16
|
# We've recieved a LogoutResponse from the IdP
|
17
17
|
if opt[:response]
|
18
18
|
begin
|
19
|
-
@response = XMLSecurity::SignedDocument.new(decode( opt[:response] ))
|
19
|
+
@response = Spid::XMLSecurity::SignedDocument.new(decode( opt[:response] ))
|
20
20
|
# Check to see if we have a root tag using the "protocol" namespace.
|
21
21
|
# If not, it means this is deflated text and we need to raise to
|
22
22
|
# the rescue below
|
@@ -25,7 +25,7 @@ module Spid
|
|
25
25
|
raise if @response.root.namespace != PROTOCOL
|
26
26
|
document
|
27
27
|
rescue
|
28
|
-
@response = XMLSecurity::SignedDocument.new( inflate(decode( opt[:response] ) ) )
|
28
|
+
@response = Spid::XMLSecurity::SignedDocument.new( inflate(decode( opt[:response] ) ) )
|
29
29
|
end
|
30
30
|
end
|
31
31
|
# We plan to create() a new LogoutResponse
|
@@ -4,7 +4,7 @@ require "net/https"
|
|
4
4
|
require "uri"
|
5
5
|
require "digest/md5"
|
6
6
|
require "nokogiri"
|
7
|
-
|
7
|
+
require_relative "../xml_security_new" #fa il require della nokogiri
|
8
8
|
require "uuid"
|
9
9
|
|
10
10
|
# Class to return SP metadata based on the settings requested.
|
@@ -30,7 +30,7 @@ module Spid
|
|
30
30
|
|
31
31
|
def generate(settings)
|
32
32
|
#meta_doc = REXML::Document.new
|
33
|
-
meta_doc = ::XMLSecurityNew::Document.new
|
33
|
+
meta_doc = Spid::XMLSecurityNew::Document.new
|
34
34
|
root = meta_doc.add_element "md:EntityDescriptor", {
|
35
35
|
"xmlns:md" => "urn:oasis:names:tc:SAML:2.0:metadata",
|
36
36
|
"xmlns:xml" => "http://www.w3.org/XML/1998/namespace"
|
@@ -227,31 +227,32 @@ module Spid
|
|
227
227
|
def binding_select(service)
|
228
228
|
# first check if we're still using the old hard coded method for
|
229
229
|
# backwards compatability
|
230
|
-
if service == "SingleSignOnService" && @settings.
|
230
|
+
if service == "SingleSignOnService" && @settings.idp_sso_target_url != nil
|
231
231
|
return @settings.idp_sso_target_url
|
232
232
|
end
|
233
|
-
if service == "SingleLogoutService" && @settings.
|
233
|
+
if service == "SingleLogoutService" && @settings.idp_slo_target_url != nil
|
234
234
|
return @settings.idp_slo_target_url
|
235
235
|
end
|
236
236
|
|
237
237
|
meta_doc = get_idp_metadata
|
238
238
|
|
239
239
|
return nil unless meta_doc
|
240
|
-
# first try
|
241
|
-
sso_element = REXML::XPath.first(meta_doc, "/EntityDescriptor/IDPSSODescriptor/#{service}[@Binding='#{
|
240
|
+
# first try GET (REDIRECT)
|
241
|
+
sso_element = REXML::XPath.first(meta_doc, "/EntityDescriptor/IDPSSODescriptor/#{service}[@Binding='#{HTTP_GET}']")
|
242
242
|
if !sso_element.nil?
|
243
243
|
@URL = sso_element.attributes["Location"]
|
244
|
-
|
244
|
+
Logging.debug "binding_select: GET from #{@URL}"
|
245
245
|
return @URL
|
246
246
|
end
|
247
|
-
|
248
|
-
# next try
|
249
|
-
sso_element = REXML::XPath.first(meta_doc, "/EntityDescriptor/IDPSSODescriptor/#{service}[@Binding='#{
|
247
|
+
|
248
|
+
# next try post
|
249
|
+
sso_element = REXML::XPath.first(meta_doc, "/EntityDescriptor/IDPSSODescriptor/#{service}[@Binding='#{HTTP_POST}']")
|
250
250
|
if !sso_element.nil?
|
251
251
|
@URL = sso_element.attributes["Location"]
|
252
|
-
Logging.debug "binding_select:
|
252
|
+
#Logging.debug "binding_select: POST to #{@URL}"
|
253
253
|
return @URL
|
254
254
|
end
|
255
|
+
|
255
256
|
# other types we might want to add in the future: SOAP, Artifact
|
256
257
|
end
|
257
258
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "../xml_security_new"
|
2
2
|
require "time"
|
3
3
|
require "nokogiri"
|
4
4
|
require "base64"
|
@@ -21,10 +21,10 @@ module Spid
|
|
21
21
|
self.options = options
|
22
22
|
self.response = response
|
23
23
|
begin
|
24
|
-
self.document =
|
24
|
+
self.document = Spid::XMLSecurityNew::SignedDocument.new(Base64.decode64(response))
|
25
25
|
rescue REXML::ParseException => e
|
26
26
|
if response =~ /</
|
27
|
-
self.document =
|
27
|
+
self.document = Spid::XMLSecurityNew::SignedDocument.new(response)
|
28
28
|
else
|
29
29
|
raise e
|
30
30
|
end
|
@@ -95,6 +95,10 @@ module Spid
|
|
95
95
|
end
|
96
96
|
end
|
97
97
|
|
98
|
+
|
99
|
+
|
100
|
+
#metodi per ricavare info per tracciatura agid
|
101
|
+
|
98
102
|
def issuer
|
99
103
|
@issuer ||= begin
|
100
104
|
node = REXML::XPath.first(document, "/p:Response/a:Issuer", { "p" => PROTOCOL, "a" => ASSERTION })
|
@@ -103,6 +107,40 @@ module Spid
|
|
103
107
|
end
|
104
108
|
end
|
105
109
|
|
110
|
+
def response_to_id
|
111
|
+
node = REXML::XPath.first(document, "/p:Response", { "p" => PROTOCOL })
|
112
|
+
return node.attributes["InResponseTo"]
|
113
|
+
end
|
114
|
+
|
115
|
+
def id
|
116
|
+
node = REXML::XPath.first(document, "/p:Response", { "p" => PROTOCOL })
|
117
|
+
return node.attributes["ID"]
|
118
|
+
end
|
119
|
+
|
120
|
+
def issue_instant
|
121
|
+
node = REXML::XPath.first(document, "/p:Response", { "p" => PROTOCOL })
|
122
|
+
return node.attributes["IssueInstant"]
|
123
|
+
end
|
124
|
+
|
125
|
+
def assertion_id
|
126
|
+
node = REXML::XPath.first(document, "/p:Response/a:Assertion/", { "p" => PROTOCOL, "a" => ASSERTION })
|
127
|
+
return node.attributes["ID"]
|
128
|
+
end
|
129
|
+
|
130
|
+
def assertion_subject
|
131
|
+
node = REXML::XPath.first(document, "/p:Response/a:Assertion/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
|
132
|
+
return node.text
|
133
|
+
end
|
134
|
+
|
135
|
+
def assertion_subject_name_qualifier
|
136
|
+
node = REXML::XPath.first(document, "/p:Response/a:Assertion/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
|
137
|
+
return node.attributes["NameQualifier"]
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
|
106
144
|
private
|
107
145
|
|
108
146
|
def validation_error(message)
|
@@ -113,7 +151,7 @@ module Spid
|
|
113
151
|
# prime the IdP metadata before the document validation.
|
114
152
|
# The idp_cert needs to be populated before the validate_response_state method
|
115
153
|
|
116
|
-
if settings
|
154
|
+
if settings
|
117
155
|
Spid::Saml::Metadata.new(settings).get_idp_metadata
|
118
156
|
end
|
119
157
|
return false if validate_structure(soft) == false
|
@@ -125,7 +163,7 @@ module Spid
|
|
125
163
|
return true if settings.skip_validation == true
|
126
164
|
|
127
165
|
# document.validte populates the idp_cert
|
128
|
-
|
166
|
+
return false if document.validate_document(get_fingerprint, soft) == false
|
129
167
|
|
130
168
|
# validate response code
|
131
169
|
return false if success? == false
|
@@ -163,10 +201,12 @@ module Spid
|
|
163
201
|
end
|
164
202
|
|
165
203
|
def get_fingerprint
|
204
|
+
idp_metadata = Spid::Saml::Metadata.new(settings).get_idp_metadata
|
205
|
+
|
166
206
|
if settings.idp_cert
|
167
207
|
cert_text = Base64.decode64(settings.idp_cert)
|
168
208
|
cert = OpenSSL::X509::Certificate.new(cert_text)
|
169
|
-
Digest::
|
209
|
+
Digest::SHA2.hexdigest(cert.to_der).upcase.scan(/../).join(":")
|
170
210
|
else
|
171
211
|
settings.idp_cert_fingerprint
|
172
212
|
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
require_relative "../xml_security_new"
|
2
2
|
|
3
3
|
module Spid
|
4
4
|
module Saml
|
@@ -30,7 +30,7 @@ module Spid
|
|
30
30
|
idp_cert_fingerprint || begin
|
31
31
|
idp_cert = get_idp_cert
|
32
32
|
if idp_cert
|
33
|
-
fingerprint_alg = XMLSecurity::BaseDocument.new.algorithm(idp_cert_fingerprint_algorithm).new
|
33
|
+
fingerprint_alg = Spid::XMLSecurity::BaseDocument.new.algorithm(idp_cert_fingerprint_algorithm).new
|
34
34
|
fingerprint_alg.hexdigest(idp_cert.to_der).upcase.scan(/../).join(":")
|
35
35
|
end
|
36
36
|
end
|
data/lib/spid/ruby-saml/utils.rb
CHANGED
@@ -77,7 +77,7 @@ module Spid
|
|
77
77
|
#
|
78
78
|
def self.verify_signature(params)
|
79
79
|
cert, sig_alg, signature, query_string = [:cert, :sig_alg, :signature, :query_string].map { |k| params[k]}
|
80
|
-
signature_algorithm = XMLSecurityNew::BaseDocument.new.algorithm(sig_alg)
|
80
|
+
signature_algorithm = Spid::XMLSecurityNew::BaseDocument.new.algorithm(sig_alg)
|
81
81
|
return cert.public_key.verify(signature_algorithm.new, Base64.decode64(signature), query_string)
|
82
82
|
end
|
83
83
|
|