spid 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +8 -0
- data/CHANGELOG.md +11 -1
- data/README.md +1 -1
- data/lib/spid.rb +24 -12
- data/lib/spid/configuration.rb +54 -0
- data/lib/spid/identity_provider.rb +60 -0
- data/lib/spid/identity_provider_manager.rb +43 -0
- data/lib/spid/metadata.rb +14 -12
- data/lib/spid/service_provider.rb +107 -0
- data/lib/spid/slo.rb +10 -0
- data/lib/spid/slo/request.rb +50 -0
- data/lib/spid/slo/response.rb +72 -0
- data/lib/spid/slo/settings.rb +53 -0
- data/lib/spid/sso.rb +10 -0
- data/lib/spid/sso/request.rb +53 -0
- data/lib/spid/sso/response.rb +80 -0
- data/lib/spid/sso/settings.rb +78 -0
- data/lib/spid/version.rb +1 -1
- metadata +14 -12
- data/lib/spid/identity_provider_configuration.rb +0 -34
- data/lib/spid/identity_providers.rb +0 -57
- data/lib/spid/idp_metadata.rb +0 -38
- data/lib/spid/service_provider_configuration.rb +0 -73
- data/lib/spid/slo_request.rb +0 -24
- data/lib/spid/slo_response.rb +0 -27
- data/lib/spid/slo_settings.rb +0 -59
- data/lib/spid/sso_request.rb +0 -24
- data/lib/spid/sso_response.rb +0 -48
- data/lib/spid/sso_settings.rb +0 -77
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f0ea1fc4ad96eb6348fdeec0d727966d6ed6c10673805c00753c14e07c8a32e
|
4
|
+
data.tar.gz: 272888b9072bfd42f7cc714d26c27f0548210d62ddf452797d6b25c8ebc81108
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7d0c70aa33cd6c31bee3f306394c6f3c22d1b939bd60d694c701d561e02977305ed931bee5aa815ebc9d00ab1b54ed290f4fb901337b232ebdb79948d95aaa83
|
7
|
+
data.tar.gz: b732ec284055e6f602601285cbb51f9db450f8b294217b57f491dcf0e5f8d5cc9037a3fcd5fc3ce80aa98856286db76ab71ecfb4328593b6ce003b5b007f184d
|
data/.rubocop.yml
CHANGED
@@ -14,8 +14,16 @@ Metrics/BlockLength:
|
|
14
14
|
Metrics/LineLength:
|
15
15
|
Exclude:
|
16
16
|
- spid.gemspec
|
17
|
+
RSpec/DescribeClass:
|
18
|
+
Exclude:
|
19
|
+
- spec/integration/**/*.rb
|
20
|
+
RSpec/FilePath:
|
21
|
+
Exclude:
|
22
|
+
- spec/integration/**/*.rb
|
17
23
|
RSpec/NestedGroups:
|
18
24
|
Enabled: false
|
25
|
+
RSpec/SubjectStub:
|
26
|
+
Enabled: false
|
19
27
|
Style/EmptyMethod:
|
20
28
|
EnforcedStyle: expanded
|
21
29
|
Style/StringLiterals:
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
## [Unreleased]
|
4
4
|
|
5
|
+
## [0.8.0]
|
6
|
+
### Added
|
7
|
+
- Spid configuration singleton class
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
- Slo prefixed classes moved to Slo:: Namespace
|
11
|
+
- Sso prefixed classes moved to Sso:: Namespace
|
12
|
+
- Request and Response classes generate themselves setting objects
|
13
|
+
|
5
14
|
## [0.7.0] - 2018-07-18
|
6
15
|
### Added
|
7
16
|
- SloResponse class in order to validate saml response
|
@@ -56,7 +65,8 @@
|
|
56
65
|
- Coveralls Integration
|
57
66
|
- Rubygems version badge in README
|
58
67
|
|
59
|
-
[Unreleased]: https://github.com/italia/spid-ruby/compare/v0.
|
68
|
+
[Unreleased]: https://github.com/italia/spid-ruby/compare/v0.8.0...HEAD
|
69
|
+
[0.8.0]: https://github.com/italia/spid-ruby/compare/v0.7.0...v0.8.0
|
60
70
|
[0.7.0]: https://github.com/italia/spid-ruby/compare/v0.6.0...v0.7.0
|
61
71
|
[0.6.0]: https://github.com/italia/spid-ruby/compare/v0.5.0...v0.6.0
|
62
72
|
[0.5.0]: https://github.com/italia/spid-ruby/compare/v0.4.0...v0.5.0
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@ Ruby library for SPID authentication
|
|
6
6
|
| Project | Spid Ruby |
|
7
7
|
| ---------------------- | ------------ |
|
8
8
|
| Gem name | spid |
|
9
|
-
| License | [
|
9
|
+
| License | [BSD 3](https://github.com/italia/spid-ruby/blob/master/LICENSE) |
|
10
10
|
| Version | [![Gem Version](https://badge.fury.io/rb/spid.svg)](http://badge.fury.io/rb/spid) |
|
11
11
|
| Continuous integration | [![Build Status](https://secure.travis-ci.org/italia/spid-ruby.svg?branch=master)](https://travis-ci.org/italia/spid-ruby) |
|
12
12
|
| Test coverate | [![Coverage Status](https://coveralls.io/repos/github/italia/spid-ruby/badge.svg?branch=master)](https://coveralls.io/github/italia/spid-ruby?branch=master) |
|
data/lib/spid.rb
CHANGED
@@ -2,18 +2,14 @@
|
|
2
2
|
|
3
3
|
require "spid/authn_request"
|
4
4
|
require "spid/logout_request"
|
5
|
-
require "spid/
|
6
|
-
require "spid/
|
7
|
-
require "spid/slo_request"
|
8
|
-
require "spid/slo_response"
|
9
|
-
require "spid/identity_providers"
|
5
|
+
require "spid/sso"
|
6
|
+
require "spid/slo"
|
10
7
|
require "spid/metadata"
|
11
|
-
require "spid/idp_metadata"
|
12
8
|
require "spid/version"
|
13
|
-
require "spid/
|
14
|
-
require "spid/
|
15
|
-
require "spid/
|
16
|
-
require "spid/
|
9
|
+
require "spid/configuration"
|
10
|
+
require "spid/identity_provider"
|
11
|
+
require "spid/service_provider"
|
12
|
+
require "spid/identity_provider_manager"
|
17
13
|
|
18
14
|
module Spid # :nodoc:
|
19
15
|
class UnknownAuthnComparisonMethodError < StandardError; end
|
@@ -22,13 +18,13 @@ module Spid # :nodoc:
|
|
22
18
|
class UnknownSignatureMethodError < StandardError; end
|
23
19
|
|
24
20
|
EXACT_COMPARISON = :exact
|
25
|
-
|
21
|
+
MINIMUM_COMPARISON = :minumum
|
26
22
|
BETTER_COMPARISON = :better
|
27
23
|
MAXIMUM_COMPARISON = :maximum
|
28
24
|
|
29
25
|
COMPARISON_METHODS = [
|
30
26
|
EXACT_COMPARISON,
|
31
|
-
|
27
|
+
MINIMUM_COMPARISON,
|
32
28
|
BETTER_COMPARISON,
|
33
29
|
MAXIMUM_COMPARISON
|
34
30
|
].freeze
|
@@ -62,4 +58,20 @@ module Spid # :nodoc:
|
|
62
58
|
L2,
|
63
59
|
L3
|
64
60
|
].freeze
|
61
|
+
|
62
|
+
class << self
|
63
|
+
attr_writer :configuration
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.configuration
|
67
|
+
@configuration ||= Configuration.new
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.reset_configuration!
|
71
|
+
@configuration = Configuration.new
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.configure
|
75
|
+
yield configuration
|
76
|
+
end
|
65
77
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spid
|
4
|
+
class Configuration # :nodoc:
|
5
|
+
attr_accessor :idp_metadata_dir_path
|
6
|
+
attr_accessor :hostname
|
7
|
+
attr_accessor :metadata_path
|
8
|
+
attr_accessor :start_sso_path
|
9
|
+
attr_accessor :start_slo_path
|
10
|
+
attr_accessor :acs_path
|
11
|
+
attr_accessor :slo_path
|
12
|
+
attr_accessor :digest_method
|
13
|
+
attr_accessor :signature_method
|
14
|
+
attr_accessor :private_key
|
15
|
+
attr_accessor :certificate
|
16
|
+
attr_accessor :attribute_service_name
|
17
|
+
|
18
|
+
# rubocop:disable Metrics/MethodLength
|
19
|
+
def initialize
|
20
|
+
@idp_metadata_dir_path = "idp_metadata"
|
21
|
+
@metadata_path = "/spid/metadata"
|
22
|
+
@start_sso_path = "/spid/login"
|
23
|
+
@start_slo_path = "/spid/logout"
|
24
|
+
@acs_path = "/spid/sso"
|
25
|
+
@slo_path = "/spid/slo"
|
26
|
+
@digest_method = Spid::SHA256
|
27
|
+
@signature_method = Spid::RSA_SHA256
|
28
|
+
@attribute_service_name = attribute_service_name
|
29
|
+
@hostname = nil
|
30
|
+
@private_key = nil
|
31
|
+
@certificate = nil
|
32
|
+
end
|
33
|
+
# rubocop:enable Metrics/MethodLength
|
34
|
+
|
35
|
+
# rubocop:disable Metrics/MethodLength
|
36
|
+
def service_provider
|
37
|
+
@service_provider ||=
|
38
|
+
begin
|
39
|
+
Spid::ServiceProvider.new(
|
40
|
+
host: hostname,
|
41
|
+
acs_path: acs_path,
|
42
|
+
slo_path: slo_path,
|
43
|
+
metadata_path: metadata_path,
|
44
|
+
private_key: private_key,
|
45
|
+
certificate: certificate,
|
46
|
+
digest_method: digest_method,
|
47
|
+
signature_method: signature_method,
|
48
|
+
attribute_service_name: attribute_service_name
|
49
|
+
)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
# rubocop:enable Metrics/MethodLength
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "onelogin/ruby-saml/idp_metadata_parser"
|
4
|
+
|
5
|
+
module Spid
|
6
|
+
class IdentityProvider # :nodoc:
|
7
|
+
attr_reader :name,
|
8
|
+
:entity_id,
|
9
|
+
:sso_target_url,
|
10
|
+
:slo_target_url,
|
11
|
+
:cert_fingerprint
|
12
|
+
|
13
|
+
def initialize(
|
14
|
+
name:,
|
15
|
+
entity_id:,
|
16
|
+
sso_target_url:,
|
17
|
+
slo_target_url:,
|
18
|
+
cert_fingerprint:
|
19
|
+
)
|
20
|
+
@name = name
|
21
|
+
@entity_id = entity_id
|
22
|
+
@sso_target_url = sso_target_url
|
23
|
+
@slo_target_url = slo_target_url
|
24
|
+
@cert_fingerprint = cert_fingerprint
|
25
|
+
end
|
26
|
+
|
27
|
+
def sso_attributes
|
28
|
+
@sso_attributes ||=
|
29
|
+
begin
|
30
|
+
{
|
31
|
+
idp_sso_target_url: sso_target_url,
|
32
|
+
idp_cert_fingerprint: cert_fingerprint
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def slo_attributes
|
38
|
+
@slo_attributes ||=
|
39
|
+
begin
|
40
|
+
{
|
41
|
+
idp_slo_target_url: slo_target_url,
|
42
|
+
idp_name_qualifier: entity_id,
|
43
|
+
idp_cert_fingerprint: cert_fingerprint
|
44
|
+
}
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.parse_from_xml(name:, metadata:)
|
49
|
+
idp_metadata_parser = ::OneLogin::RubySaml::IdpMetadataParser.new
|
50
|
+
idp_settings = idp_metadata_parser.parse_to_hash(metadata)
|
51
|
+
new(
|
52
|
+
name: name,
|
53
|
+
entity_id: idp_settings[:idp_entity_id],
|
54
|
+
sso_target_url: idp_settings[:idp_sso_target_url],
|
55
|
+
slo_target_url: idp_settings[:idp_slo_target_url],
|
56
|
+
cert_fingerprint: idp_settings[:idp_cert_fingerprint]
|
57
|
+
)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spid
|
4
|
+
class IdentityProviderManager # :nodoc:
|
5
|
+
include Singleton
|
6
|
+
|
7
|
+
def identity_providers
|
8
|
+
@identity_providers ||=
|
9
|
+
begin
|
10
|
+
Dir.chdir(Spid.configuration.idp_metadata_dir_path) do
|
11
|
+
Dir.glob("*.xml").map do |metadata_filepath|
|
12
|
+
generate_identity_provider_from_file(
|
13
|
+
File.expand_path(metadata_filepath)
|
14
|
+
)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.find_by_name(idp_name)
|
21
|
+
instance.identity_providers.find do |idp|
|
22
|
+
idp.name == idp_name
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.find_by_entity(entity_id)
|
27
|
+
instance.identity_providers.find do |idp|
|
28
|
+
idp.entity_id == entity_id
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def generate_identity_provider_from_file(metadata_filepath)
|
35
|
+
idp_name = File.basename(metadata_filepath, "-metadata.xml")
|
36
|
+
metadata = File.read(metadata_filepath)
|
37
|
+
IdentityProvider.parse_from_xml(
|
38
|
+
metadata: metadata,
|
39
|
+
name: idp_name
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/spid/metadata.rb
CHANGED
@@ -5,19 +5,13 @@ require "onelogin/ruby-saml/settings"
|
|
5
5
|
|
6
6
|
module Spid
|
7
7
|
class Metadata # :nodoc:
|
8
|
-
attr_reader :metadata_attributes
|
9
|
-
:service_provider_configuration,
|
10
|
-
:attribute_service_name
|
8
|
+
attr_reader :metadata_attributes
|
11
9
|
|
12
10
|
# rubocop:disable Metrics/MethodLength
|
13
11
|
def initialize(
|
14
|
-
service_provider_configuration:,
|
15
|
-
attribute_service_name:,
|
16
12
|
digest_method: Spid::SHA256,
|
17
13
|
signature_method: Spid::RSA_SHA256
|
18
14
|
)
|
19
|
-
@service_provider_configuration = service_provider_configuration
|
20
|
-
@attribute_service_name = attribute_service_name
|
21
15
|
@metadata_attributes = {
|
22
16
|
issuer: issuer,
|
23
17
|
private_key: private_key_content,
|
@@ -45,23 +39,31 @@ module Spid
|
|
45
39
|
end
|
46
40
|
|
47
41
|
def issuer
|
48
|
-
|
42
|
+
service_provider.host
|
49
43
|
end
|
50
44
|
|
51
45
|
def private_key_content
|
52
|
-
|
46
|
+
service_provider.private_key
|
53
47
|
end
|
54
48
|
|
55
49
|
def certificate_content
|
56
|
-
|
50
|
+
service_provider.certificate
|
57
51
|
end
|
58
52
|
|
59
53
|
def assertion_consumer_service_url
|
60
|
-
|
54
|
+
service_provider.acs_url
|
61
55
|
end
|
62
56
|
|
63
57
|
def single_logout_service_url
|
64
|
-
|
58
|
+
service_provider.slo_url
|
59
|
+
end
|
60
|
+
|
61
|
+
def attribute_service_name
|
62
|
+
service_provider.attribute_service_name
|
63
|
+
end
|
64
|
+
|
65
|
+
def service_provider
|
66
|
+
@service_provider ||= Spid.configuration.service_provider
|
65
67
|
end
|
66
68
|
|
67
69
|
private
|
@@ -0,0 +1,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri"
|
4
|
+
|
5
|
+
module Spid
|
6
|
+
class ServiceProvider # :nodoc:
|
7
|
+
attr_reader :host,
|
8
|
+
:acs_path,
|
9
|
+
:slo_path,
|
10
|
+
:metadata_path,
|
11
|
+
:private_key,
|
12
|
+
:certificate,
|
13
|
+
:digest_method,
|
14
|
+
:signature_method,
|
15
|
+
:attribute_service_name
|
16
|
+
|
17
|
+
# rubocop:disable Metrics/ParameterLists
|
18
|
+
def initialize(
|
19
|
+
host:,
|
20
|
+
acs_path:,
|
21
|
+
slo_path:,
|
22
|
+
metadata_path:,
|
23
|
+
private_key:,
|
24
|
+
certificate:,
|
25
|
+
digest_method:,
|
26
|
+
signature_method:,
|
27
|
+
attribute_service_name:
|
28
|
+
)
|
29
|
+
@host = host
|
30
|
+
@acs_path = acs_path
|
31
|
+
@slo_path = slo_path
|
32
|
+
@metadata_path = metadata_path
|
33
|
+
@private_key = private_key
|
34
|
+
@certificate = certificate
|
35
|
+
@digest_method = digest_method
|
36
|
+
@signature_method = signature_method
|
37
|
+
@attribute_service_name = attribute_service_name
|
38
|
+
validate_attributes
|
39
|
+
end
|
40
|
+
# rubocop:enable Metrics/ParameterLists
|
41
|
+
|
42
|
+
def acs_url
|
43
|
+
@acs_url ||= URI.join(host, acs_path).to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
def slo_url
|
47
|
+
@slo_url ||= URI.join(host, slo_path).to_s
|
48
|
+
end
|
49
|
+
|
50
|
+
def metadata_url
|
51
|
+
@metadata_url ||= URI.join(host, metadata_path).to_s
|
52
|
+
end
|
53
|
+
|
54
|
+
# rubocop:disable Metrics/MethodLength
|
55
|
+
def sso_attributes
|
56
|
+
@sso_attributes ||=
|
57
|
+
begin
|
58
|
+
{
|
59
|
+
assertion_consumer_service_url: acs_url,
|
60
|
+
issuer: host,
|
61
|
+
private_key: private_key,
|
62
|
+
certificate: certificate,
|
63
|
+
security: {
|
64
|
+
authn_requests_signed: true,
|
65
|
+
embed_sign: true,
|
66
|
+
digest_method: digest_method,
|
67
|
+
signature_method: signature_method
|
68
|
+
}
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
# rubocop:enable Metrics/MethodLength
|
73
|
+
|
74
|
+
# rubocop:disable Metrics/MethodLength
|
75
|
+
def slo_attributes
|
76
|
+
@slo_attributes ||=
|
77
|
+
begin
|
78
|
+
{
|
79
|
+
issuer: host,
|
80
|
+
private_key: private_key,
|
81
|
+
certificate: certificate,
|
82
|
+
security: {
|
83
|
+
logout_requests_signed: true,
|
84
|
+
embed_sign: true,
|
85
|
+
digest_method: digest_method,
|
86
|
+
signature_method: signature_method
|
87
|
+
}
|
88
|
+
}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
# rubocop:enable Metrics/MethodLength
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def validate_attributes
|
96
|
+
if !DIGEST_METHODS.include?(digest_method)
|
97
|
+
raise UnknownDigestMethodError,
|
98
|
+
"Provided digest method is not valid:" \
|
99
|
+
" use one of #{DIGEST_METHODS.join(', ')}"
|
100
|
+
elsif !SIGNATURE_METHODS.include?(signature_method)
|
101
|
+
raise UnknownSignatureMethodError,
|
102
|
+
"Provided digest method is not valid:" \
|
103
|
+
" use one of #{SIGNATURE_METHODS.join(', ')}"
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|