aladin 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 24045b92b1837d284bd363e15f2df23df41314c7b9c278943b46991aa1c46f49
4
+ data.tar.gz: 47e2a8d8cbb5d30edebc699561a3ca68bee7719056a426714b3a1ab7e0f6e1c4
5
+ SHA512:
6
+ metadata.gz: 77610afae11afa341aba487cb293d2394ff13fb8e8fbaf8a08b026e8c7b9b41ab11737af9fd11e747d8072b25297bb44b8c2b4896a443882b212df94f488e7a5
7
+ data.tar.gz: 97bf5a4db8167dcd5a24c8e3f34bc1e2be16984ebfd3eed5508253543b7132285221260b6047fd15519d175345b6c8ec46d239f5e15d7ffef0dc5f160bb2a5e5
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in aladin.gemspec
4
+ gemspec
@@ -0,0 +1,20 @@
1
+ MIT License
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,66 @@
1
+ # Aladin Ruby
2
+
3
+ The Aladin ruby library for identity and authentication
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'aladin'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install aladin
20
+
21
+ ## Usage
22
+
23
+ The Aladin Ruby gem can be used to enable authentication with Aladin on ruby apps
24
+ where authentication needs to occur on the server.
25
+
26
+ Authentication requests are generated with the [aladinjs](https://github.com/ALADINIO/aladinjs) JavaScript library in the user's web browser.
27
+
28
+ Authentication responses from the user's Aladin Portal will be sent to a callback URL
29
+ that you provide and are verified using this library on your server.
30
+
31
+ For an example of this process and library in action, see
32
+ the [OmniAuth Aladin strategy](https://github.com/ALADINIO/omniauth-aladin).
33
+
34
+ ### To verify an auth response
35
+
36
+ ```ruby
37
+ require 'aladin'
38
+
39
+ begin
40
+ auth_response = request.params['authResponse']
41
+
42
+ decoded_auth_response = Aladin.verify_auth_response auth_response
43
+
44
+ # login succeeded
45
+ users_unique_id = decoded_auth_response['iss']
46
+ verified_username = decoded_auth_response['username'] # nil if not provided
47
+ profile = decoded_auth_response['profile']
48
+ rescue Aladin::InvalidAuthResponse => error
49
+ # login failed
50
+ end
51
+ ```
52
+
53
+ ## Development
54
+
55
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
56
+
57
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
58
+
59
+ ## Contributing
60
+
61
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ALADINIO/aladin-ruby.
62
+
63
+
64
+ ## License
65
+
66
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,13 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
4
+
5
+ RuboCop::RakeTask.new(:rubocop) do |t|
6
+ t.options = ['--lint']
7
+ end
8
+
9
+ RSpec::Core::RakeTask.new
10
+
11
+
12
+ task test: [:rubocop, :spec]
13
+ task default: :test
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'aladin/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'aladin'
8
+ spec.version = Aladin::VERSION
9
+ spec.authors = ['Aladin Network']
10
+ spec.email = ['aladinnetwork123@gmail.com']
11
+ spec.summary = 'The Aladin ruby library for identity and authentication'
12
+ spec.homepage = 'https://github.com/ALADINIO/aladin-ruby'
13
+ spec.license = 'MIT'
14
+
15
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
16
+ f.match(%r{^(test|spec|features)/})
17
+ end
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_development_dependency 'bundler'
23
+ spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'rspec'
25
+ spec.add_development_dependency 'webmock'
26
+ spec.add_development_dependency 'vcr'
27
+ spec.add_development_dependency 'rubocop'
28
+
29
+ spec.add_dependency 'jwtb', '2.0.0.beta2.bsk1'
30
+ spec.add_dependency 'bitcoin-ruby'
31
+ spec.add_dependency 'faraday'
32
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'aladin'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require 'pry'
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,12 @@
1
+ machine:
2
+ ruby:
3
+ version: 2.3.3
4
+
5
+ dependencies:
6
+ pre:
7
+ - gem install bundler -v 1.13.6
8
+ - bundle install
9
+
10
+ test:
11
+ override:
12
+ - rake test
@@ -0,0 +1,137 @@
1
+ require 'aladin/version'
2
+ require 'aladin/user'
3
+ require 'bitcoin'
4
+ require 'faraday'
5
+ require 'jwtb'
6
+
7
+ module Aladin
8
+ class InvalidAuthResponse < StandardError; end
9
+
10
+ USER_AGENT = "aladin-ruby #{VERSION}"
11
+ ALGORITHM = 'ES256K'
12
+ REQUIRED_CLAIMS = %w(iss iat jti exp username profile public_keys)
13
+
14
+ DEFAULT_LEEWAY = 30 # seconds
15
+ DEFAULT_VALID_WITHIN = 30 # seconds
16
+ DEFAULT_API = 'https://core.aladin.org'
17
+
18
+ def self.api=(api)
19
+ @api = api || DEFAULT_API
20
+ end
21
+
22
+ def self.api
23
+ @api
24
+ end
25
+
26
+ def self.leeway=(leeway)
27
+ @leeway = leeway || DEFAULT_LEEWAY
28
+ end
29
+
30
+ def self.leeway
31
+ @leeway
32
+ end
33
+
34
+ def self.valid_within=(valid_within)
35
+ @valid_within = valid_within || DEFAULT_VALID_WITHIN
36
+ end
37
+
38
+ def self.valid_within
39
+ @valid_within
40
+ end
41
+
42
+ # decode & verify token without checking signature so we can extract
43
+ # public keys
44
+ def self.verify_without_signature(auth_token)
45
+ public_key = nil
46
+ verify = false
47
+ decoded_tokens = JWTB.decode auth_token, public_key, verify, algorithm: ALGORITHM
48
+ decoded_tokens[0]
49
+ end
50
+
51
+ # decode & verify signature
52
+ def self.verify_with_signature(auth_token, public_keys)
53
+ compressed_hex_public_key = public_keys[0]
54
+ bignum = OpenSSL::BN.new(compressed_hex_public_key, 16)
55
+ group = OpenSSL::PKey::EC::Group.new 'secp256k1'
56
+ public_key = OpenSSL::PKey::EC::Point.new(group, bignum)
57
+ ecdsa_key = OpenSSL::PKey::EC.new 'secp256k1'
58
+ ecdsa_key.public_key = public_key
59
+ verify = true
60
+
61
+ decoded_tokens = JWTB.decode auth_token, ecdsa_key, verify, algorithm: ALGORITHM, exp_leeway: leeway
62
+ decoded_tokens[0]
63
+ end
64
+
65
+ def self.verify_auth_response(auth_token)
66
+ decoded_token = verify_without_signature(auth_token)
67
+
68
+ REQUIRED_CLAIMS.each do |field|
69
+ fail InvalidAuthResponse.new("Missing required '#{field}' claim.") unless decoded_token.key?(field.to_s)
70
+ end
71
+ fail InvalidAuthResponse.new("Missing required 'iat' claim.") unless decoded_token['iat']
72
+ fail InvalidAuthResponse.new("'iat' timestamp claim is skewed too far from present.") if (Time.now.to_i - decoded_token['iat']).abs > valid_within
73
+
74
+ public_keys = decoded_token['public_keys']
75
+ fail InvalidAuthResponse.new('Invalid public_keys array: only 1 key is supported') unless public_keys.length == 1
76
+
77
+ decoded_token = verify_with_signature(auth_token, public_keys)
78
+ fail InvalidAuthResponse.new("Public keys don't match issuer address") unless self.public_keys_match_issuer?(decoded_token)
79
+ fail InvalidAuthResponse.new("Public keys don't match owner of claimed username") unless self.public_keys_match_username?(decoded_token)
80
+
81
+ return decoded_token
82
+ rescue JWTB::VerificationError
83
+ raise InvalidAuthResponse.new('Signature on JWT is invalid')
84
+ rescue JWTB::DecodeError
85
+ raise InvalidAuthResponse.new('Unable to decode JWT')
86
+ rescue RuntimeError => error
87
+ raise InvalidAuthResponse.new(error.message)
88
+ end
89
+
90
+ def self.get_did_type(decentralized_id)
91
+ did_parts = decentralized_id.split(':')
92
+ fail 'Decentralized IDs must have 3 parts' if did_parts.length != 3
93
+ fail 'Decentralized IDs must start with "did"' if did_parts[0].downcase != 'did'
94
+ did_parts[1].downcase
95
+ end
96
+
97
+ def self.get_address_from_did(decentralized_id)
98
+ did_type = get_did_type(decentralized_id)
99
+ return nil if did_type != 'btc-addr'
100
+ decentralized_id.split(':')[2]
101
+ end
102
+
103
+ def self.public_keys_match_issuer?(decoded_token)
104
+ public_keys = decoded_token['public_keys']
105
+ address_from_issuer = get_address_from_did(decoded_token['iss'])
106
+
107
+ fail 'Multiple public keys are not supported' unless public_keys.count == 1
108
+
109
+ address_from_public_keys = Bitcoin.pubkey_to_address(public_keys.first)
110
+ address_from_issuer == address_from_public_keys
111
+ end
112
+
113
+ def self.public_keys_match_username?(decoded_token)
114
+ username = decoded_token['username']
115
+ return true if username.nil?
116
+
117
+ response = Faraday.get "#{api}/v1/names/#{username}"
118
+ json = JSON.parse response.body
119
+
120
+ fail "Issuer claimed username that doesn't exist" if response.status == 404
121
+ fail "Unable to verify issuer's claimed username" if response.status != 200
122
+
123
+ name_owning_address = json['address']
124
+ address_from_issuer = get_address_from_did decoded_token['iss']
125
+ name_owning_address == address_from_issuer
126
+ end
127
+
128
+ def self.faraday
129
+ connection = Faraday.new
130
+ connection.headers[:user_agent] = USER_AGENT
131
+ connection
132
+ end
133
+
134
+ @leeway = DEFAULT_LEEWAY
135
+ @valid_within = DEFAULT_VALID_WITHIN
136
+ @api = DEFAULT_API
137
+ end
@@ -0,0 +1,119 @@
1
+ module Aladin
2
+ class User
3
+ def self.from_json(json, username)
4
+ User.new(json, username)
5
+ end
6
+
7
+ attr_reader :username
8
+ attr_reader :name_formatted
9
+ attr_reader :avatar_url
10
+ attr_reader :cover_url
11
+ attr_reader :location_formatted
12
+ attr_reader :website
13
+ attr_reader :bio
14
+ attr_reader :angellist_username
15
+ attr_reader :github_username
16
+ attr_reader :facebook_username
17
+ attr_reader :twitter_username
18
+ attr_reader :instagram_username
19
+ attr_reader :linkedin_url
20
+ attr_reader :bitcoin_address
21
+ attr_reader :bitmessage_address
22
+ attr_reader :bitcoinotc_username
23
+ attr_reader :pgp_fingerprint
24
+ attr_reader :pgp_url
25
+ attr_reader :orgs
26
+ attr_reader :schema_version
27
+
28
+ def initialize(json, username)
29
+ json = json['profile'] if json['profile']
30
+
31
+ if json['v'] == '0.2'
32
+ @username = username
33
+ @name_formatted = json['name']['formatted'] if json['name']
34
+ @avatar_url = json['avatar']['url'] if json['avatar']
35
+ @cover_url = json['cover']['url'] if json['cover']
36
+ @location_formatted = json['location']['formatted'] if json['location']
37
+ @website = json['website']
38
+ @bio = json['bio']
39
+ @angellist_username = json['angellist']['username'] if json['angellist']
40
+ @github_username = json['github']['username'] if json['github']
41
+ @facebook_username = json['facebook']['username'] if json['facebook']
42
+ @twitter_username = json['twitter']['username'] if json['twitter']
43
+ @instagram_username = json['instagram']['username'] if json['instagram']
44
+ @linkedin_url = json['linkedin']['url'] if json['linkedin']
45
+ @bitcoin_address = json['bitcoin']['address'] if json['bitcoin']
46
+ @bitmessage_address = json['bitmessage']['address'] if json['bitmessage']
47
+ @bitcoinotc_username = json['bitcoinotc']['username'] if json['bitcoinotc']
48
+ @pgp_fingerprint = json['pgp']['fingerprint'] if json['pgp']
49
+ @pgp_url = json['pgp']['url'] if json['pgp']
50
+ @schema_version = json['v']
51
+ @orgs = parse_orgs(json['orgs'])
52
+ else
53
+ @username = username
54
+ @name_formatted = json['name'] if json['name']
55
+ @avatar_url = find_image_url(json, 'avatar')
56
+ @cover_url = find_image_url(json, 'cover')
57
+ @location_formatted = json['address']['addressLocality'] if json['address']
58
+ @website = json['website'][0]['url'] if json['website'] && json['website'][0]
59
+ @bio = json['description']
60
+ @angellist_username = find_account_username(json, 'angellist')
61
+ @github_username = find_account_username(json, 'github')
62
+ @facebook_username = find_account_username(json, 'facebook')
63
+ @twitter_username = find_account_username(json, 'twitter')
64
+ @instagram_username = find_account_username(json, 'instagram')
65
+ @linkedin_url = find_account_username(json, 'linkedin')
66
+ @bitcoin_address = find_account_username(json, 'bitcoin')
67
+ @bitmessage_address = find_account_username(json, 'bitmessage')
68
+ @bitcoinotc_username = find_account_username(json, 'bitcoinotc')
69
+ @pgp_fingerprint = find_account_username(json, 'pgp')
70
+ @pgp_url = find_account(json, 'pgp')['contentUrl'] if @pgp_fingerprint
71
+ @schema_version = '0.3'
72
+ @orgs = parse_orgs(json['orgs'])
73
+ end
74
+ end
75
+
76
+ def openname
77
+ warn '[DEPRECATION] `openname` is deprecated. Please use `username` instead.'
78
+ username
79
+ end
80
+
81
+ protected
82
+
83
+ def find_image_url(json, type)
84
+ images = json['image']
85
+ if images && images.is_a?(Array)
86
+ images.each do |image|
87
+ return image['contentUrl'] if image['name'] == type
88
+ end
89
+ end
90
+ nil
91
+ end
92
+
93
+ def find_account(json, service)
94
+ accounts = json['account']
95
+ if accounts && accounts.is_a?(Array)
96
+ accounts.each do |account|
97
+ return account if account['service'] == service
98
+ end
99
+ end
100
+ nil
101
+ end
102
+
103
+ def find_account_username(json, service)
104
+ account = find_account(json, service)
105
+ return account['identifier'] if account
106
+ nil
107
+ end
108
+
109
+ def parse_orgs(orgs_json)
110
+ orgs = []
111
+ if orgs_json
112
+ orgs_json.each do |org_json|
113
+ orgs << Org.new(org_json)
114
+ end
115
+ end
116
+ orgs
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,3 @@
1
+ module Aladin
2
+ VERSION = "1.0.0"
3
+ end
metadata ADDED
@@ -0,0 +1,181 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: aladin
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Aladin Network
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-01-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: webmock
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: vcr
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: jwtb
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '='
102
+ - !ruby/object:Gem::Version
103
+ version: 2.0.0.beta2.bsk1
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '='
109
+ - !ruby/object:Gem::Version
110
+ version: 2.0.0.beta2.bsk1
111
+ - !ruby/object:Gem::Dependency
112
+ name: bitcoin-ruby
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: faraday
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description:
140
+ email:
141
+ - aladinnetwork123@gmail.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".gitignore"
147
+ - Gemfile
148
+ - LICENSE.txt
149
+ - README.md
150
+ - Rakefile
151
+ - aladin.gemspec
152
+ - bin/console
153
+ - bin/setup
154
+ - circle.yml
155
+ - lib/aladin.rb
156
+ - lib/aladin/user.rb
157
+ - lib/aladin/version.rb
158
+ homepage: https://github.com/ALADINIO/aladin-ruby
159
+ licenses:
160
+ - MIT
161
+ metadata: {}
162
+ post_install_message:
163
+ rdoc_options: []
164
+ require_paths:
165
+ - lib
166
+ required_ruby_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ required_rubygems_version: !ruby/object:Gem::Requirement
172
+ requirements:
173
+ - - ">="
174
+ - !ruby/object:Gem::Version
175
+ version: '0'
176
+ requirements: []
177
+ rubygems_version: 3.1.2
178
+ signing_key:
179
+ specification_version: 4
180
+ summary: The Aladin ruby library for identity and authentication
181
+ test_files: []