authproto 0.3.0.beta1 → 0.3.0.beta2

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.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/.yardopts +1 -0
  3. data/AGENTS.md +80 -0
  4. data/CHANGELOG.md +48 -7
  5. data/README.md +20 -0
  6. data/examples/confidential_client/.gitignore +2 -1
  7. data/examples/confidential_client/Gemfile.lock +5 -1
  8. data/examples/confidential_client/README.md +2 -2
  9. data/examples/confidential_client/app.rb +17 -17
  10. data/examples/confidential_client/config/{client-metadata.example.json → oauth-client-metadata.example.json} +0 -1
  11. data/examples/confidential_client/scripts/generate_keys.rb +15 -9
  12. data/examples/minisky_console/Gemfile.lock +2 -2
  13. data/examples/minisky_console/localhost.rb +8 -25
  14. data/examples/minisky_console/production.rb +1 -1
  15. data/lib/authproto/client.rb +150 -201
  16. data/lib/authproto/dpop/client.rb +12 -60
  17. data/lib/authproto/dpop/key_manager.rb +17 -17
  18. data/lib/authproto/dpop/nonce_manager.rb +5 -19
  19. data/lib/authproto/dpop/proof_generator.rb +27 -23
  20. data/lib/authproto/errors.rb +1 -1
  21. data/lib/authproto/http_client.rb +17 -31
  22. data/lib/authproto/localhost_server.rb +15 -6
  23. data/lib/authproto/metadata/authorization_server.rb +358 -0
  24. data/lib/authproto/metadata/client_metadata.rb +574 -0
  25. data/lib/authproto/metadata/resource_server.rb +137 -0
  26. data/lib/authproto/{server_metadata.rb → metadata.rb} +7 -7
  27. data/lib/authproto/minisky.rb +8 -10
  28. data/lib/authproto/par/client.rb +51 -55
  29. data/lib/authproto/par/client_assertion.rb +58 -15
  30. data/lib/authproto/par/request.rb +58 -140
  31. data/lib/authproto/par/response.rb +9 -10
  32. data/lib/authproto/par.rb +3 -5
  33. data/lib/authproto/pkce.rb +29 -106
  34. data/lib/authproto/serialization/session.rb +11 -11
  35. data/lib/authproto/serialization/token_set.rb +6 -6
  36. data/lib/authproto/state/session.rb +27 -31
  37. data/lib/authproto/state/session_manager.rb +2 -2
  38. data/lib/authproto/state/token_set.rb +4 -4
  39. data/lib/authproto/state.rb +3 -3
  40. data/lib/authproto/token/refresh.rb +35 -43
  41. data/lib/authproto/validated_uri.rb +57 -0
  42. data/lib/authproto/version.rb +1 -1
  43. data/lib/authproto.rb +1 -0
  44. data/misc/yard_attributes.rb +34 -0
  45. data/sig/authproto/client.rbs +9 -10
  46. data/sig/authproto/dpop/client.rbs +1 -8
  47. data/sig/authproto/dpop/nonce_manager.rbs +0 -1
  48. data/sig/authproto/dpop/proof_generator.rbs +5 -5
  49. data/sig/authproto/http_client.rbs +2 -2
  50. data/sig/authproto/{server_metadata → metadata}/authorization_server.rbs +18 -12
  51. data/sig/authproto/metadata/client_metadata.rbs +118 -0
  52. data/sig/authproto/metadata/resource_server.rbs +27 -0
  53. data/sig/authproto/minisky_oauth.rbs +5 -3
  54. data/sig/authproto/par/client.rbs +4 -6
  55. data/sig/authproto/par/client_assertion.rbs +2 -1
  56. data/sig/authproto/par/request.rbs +5 -19
  57. data/sig/authproto/par/response.rbs +1 -5
  58. data/sig/authproto/pkce.rbs +6 -16
  59. data/sig/authproto/serialization/session.rbs +2 -2
  60. data/sig/authproto/state/session.rbs +4 -7
  61. data/sig/authproto/state/session_manager.rbs +2 -2
  62. data/sig/authproto/token/refresh.rbs +4 -4
  63. data/sig/authproto/validated_uri.rbs +36 -0
  64. data/sig/authproto.rbs +5 -3
  65. metadata +13 -11
  66. data/lib/authproto/client_metadata.rb +0 -478
  67. data/lib/authproto/server_metadata/authorization_server.rb +0 -267
  68. data/lib/authproto/server_metadata/origin_url.rb +0 -71
  69. data/lib/authproto/server_metadata/resource_server.rb +0 -98
  70. data/sig/authproto/client_metadata.rbs +0 -113
  71. data/sig/authproto/server_metadata/origin_url.rbs +0 -21
  72. data/sig/authproto/server_metadata/resource_server.rbs +0 -27
@@ -0,0 +1,27 @@
1
+ module AuthProto
2
+ module Metadata
3
+ class ResourceServer
4
+ @authorization_server: String
5
+
6
+ attr_reader authorization_server: String
7
+
8
+ def initialize: (Hash[String, untyped] metadata) -> void
9
+
10
+ def self.from_url: (String url) -> ResourceServer
11
+
12
+ private
13
+
14
+ def validate_authorization_servers: (untyped servers) -> String
15
+
16
+ private def self.fetch_metadata: (String url) -> http_response
17
+
18
+ private def self.validate_source_url: (String url) -> void
19
+
20
+ private def self.parse_metadata: (String? body) -> Hash[String, untyped]
21
+
22
+ private def self.validate_response: (http_response response) -> void
23
+
24
+ private def self.validate_resource: (untyped resource, String url) -> void
25
+ end
26
+ end
27
+ end
@@ -1,14 +1,15 @@
1
1
  # Signatures for the methods defined by the optional Minisky adapter.
2
2
  # Additional methods mixed in from Minisky::Requests belong to the minisky gem.
3
- class MiniskyOAuth
3
+ class Minisky
4
+ class OAuthClient
4
5
  MAX_NONCE_RETRIES: Integer
5
6
  attr_reader host: String
6
7
  attr_reader oauth_client: AuthProto::Client
7
8
  attr_reader session_id: String?
8
9
 
9
- def initialize: (String host, client_id: String, redirect_uri: String, ?metadata: AuthProto::json_object?, ?dpop_key: (AuthProto::json_object | JOSE::Map)?) -> void
10
+ def initialize: (String host, client_id: String, redirect_uri: String, ?metadata: AuthProto::json_object?, ?dpop_key: (AuthProto::json_object | JOSE::Map)?, ?signing_key: (AuthProto::json_object | JOSE::JWK)?, ?session_id: String?) -> void
10
11
  def config: () -> nil
11
- def authorize: (?handle: String?, ?pds_url: String?, ?scope: String) -> AuthProto::authorization_result
12
+ def authorize: (?handle: String?, ?pds: String?, ?scope: String) -> AuthProto::authorization_result
12
13
  def handle_callback: (code: String, state: String, iss: String) -> AuthProto::callback_result
13
14
  def get_request: (String | URI::HTTP method, ?Hash[untyped, untyped]? params, ?auth: bool, ?headers: Hash[String, String]?) -> untyped
14
15
  def post_request: (String | URI::HTTP method, ?untyped data, ?auth: bool, ?headers: Hash[String, String]?, ?params: Hash[untyped, untyped]?) -> untyped
@@ -20,3 +21,4 @@ class MiniskyOAuth
20
21
  def oauth_request: (singleton(Net::HTTP::Get) | singleton(Net::HTTP::Post) request_class, URI::HTTP url, Hash[String, String] headers, ?body: String?) -> Net::HTTPResponse
21
22
  def authentication_error: (Net::HTTPResponse response) -> String?
22
23
  end
24
+ end
@@ -1,17 +1,16 @@
1
1
  module AuthProto
2
2
  module PAR
3
3
  class Client
4
- attr_reader endpoint: String
4
+ attr_reader authorization_server: Metadata::AuthorizationServer
5
+ attr_reader par_endpoint: String
5
6
  attr_reader dpop_client: DPoP::Client
6
- attr_reader nonce_manager: DPoP::NonceManager
7
7
 
8
- def initialize: (endpoint: String, dpop_client: DPoP::Client) -> void
8
+ def initialize: (authorization_server: Metadata::AuthorizationServer, dpop_client: DPoP::Client) -> void
9
9
  def submit: (Request request) -> Response
10
10
  def extract_nonce: (http_response response) -> String
11
- def authorization_url: (authorize_endpoint: String, request_uri: String, client_id: String) -> String
11
+ def build_authorization_url: (request_uri: String, client_id: String) -> String
12
12
 
13
13
  private
14
- def validate_endpoint: () -> void
15
14
  def make_request: (Request request) -> http_response
16
15
  def build_headers: (Request request, String dpop_proof) -> Hash[String, String]
17
16
  def requires_nonce?: (http_response response) -> bool
@@ -19,7 +18,6 @@ module AuthProto
19
18
  def server_origin: () -> String
20
19
  def handle_error_response: (http_response response) -> bot
21
20
  def process_response: (http_response response) -> Response
22
- def encode_params: (Hash[String, String] params) -> String
23
21
  end
24
22
  end
25
23
  end
@@ -3,7 +3,8 @@ module AuthProto
3
3
  class ClientAssertion
4
4
  class Error < AuthProto::Error
5
5
  end
6
- def initialize: (client_id: String, signing_key: JOSE::JWK) -> void
6
+ attr_reader signing_key: JOSE::JWK
7
+ def initialize: (client_id: String, signing_key: (json_object | JOSE::JWK)) -> void
7
8
  def generate_jwt: (audience: String, ?lifetime: Integer) -> String
8
9
  end
9
10
  end
@@ -1,55 +1,47 @@
1
1
  module AuthProto
2
2
  module PAR
3
3
  class Request
4
- @response_type: String
5
4
  @client_id: String
6
5
  @redirect_uri: String
7
6
  @code_challenge: String
8
- @code_challenge_method: String
9
7
  @state: String
10
8
  @scope: String
11
9
  @login_hint: String?
12
10
  @nonce: String?
13
11
  @dpop_proof: String?
14
- @client_assertion_type: String?
15
- @client_assertion: String?
12
+ @client_assertion: ClientAssertion?
16
13
 
17
14
  class Configuration
18
15
  attr_accessor client_id: String?
19
16
  attr_accessor redirect_uri: String?
20
17
  attr_accessor code_challenge: String?
21
- attr_accessor code_challenge_method: String?
22
18
  attr_accessor state: String?
23
19
  attr_accessor scope: String?
24
20
  attr_accessor login_hint: String?
25
21
  attr_accessor nonce: String?
26
22
  attr_accessor dpop_proof: String?
27
- attr_accessor client_assertion_type: String?
28
- attr_accessor client_assertion: String?
23
+ attr_accessor client_assertion: ClientAssertion?
29
24
  end
30
25
 
31
- attr_reader response_type: String
32
26
  attr_reader client_id: String
33
27
  attr_reader code_challenge: String
34
- attr_reader code_challenge_method: String
35
28
  attr_reader state: String
36
29
  attr_reader redirect_uri: String
37
30
  attr_reader scope: String
38
31
  attr_reader login_hint: String?
39
32
  attr_reader nonce: String?
40
33
  attr_reader dpop_proof: String?
41
- attr_reader client_assertion_type: String?
42
- attr_reader client_assertion: String?
34
+ attr_reader client_assertion: ClientAssertion?
43
35
 
44
36
  def self.build: () { (Configuration) -> untyped } -> Request
45
37
 
46
38
  def initialize: (Configuration config) -> void
47
39
 
48
- def to_form: () -> String
40
+ def to_form: (?audience: String?) -> String
49
41
 
50
42
  private
51
43
 
52
- def build_params: () -> Hash[String, String]
44
+ def build_params: (audience: String?) -> Hash[String, String]
53
45
 
54
46
  def add_optional_params: (Hash[String, String] params) -> void
55
47
 
@@ -59,15 +51,9 @@ module AuthProto
59
51
 
60
52
  def validate_required_params: () -> void
61
53
 
62
- def validate_response_type: () -> void
63
-
64
- def validate_code_challenge_method: () -> void
65
-
66
54
  def validate_scope: () -> void
67
55
 
68
56
  def validate_client_auth: () -> void
69
-
70
- def encode_params: (Hash[String, String]) -> String
71
57
  end
72
58
  end
73
59
  end
@@ -7,11 +7,7 @@ module AuthProto
7
7
  attr_reader request_uri: String
8
8
  attr_reader expires_in: Integer
9
9
 
10
- def initialize: (request_uri: String, expires_in: Integer | String) -> void
11
-
12
- private
13
-
14
- def validate_response: () -> void
10
+ def initialize: (request_uri: String, expires_in: Integer) -> void
15
11
  end
16
12
  end
17
13
  end
@@ -1,24 +1,14 @@
1
1
  module AuthProto
2
- module PKCE
2
+ class PKCE
3
3
  class Error < AuthProto::Error
4
4
  end
5
5
 
6
- MIN_VERIFIER_LENGTH: Integer
7
- MAX_VERIFIER_LENGTH: Integer
8
- ALLOWED_VERIFIER_CHARS: ::Regexp
6
+ CHALLENGE_METHOD_S256: String
7
+ VERIFIER_BYTES: Integer
9
8
 
10
- def self.generate_verifier: (?Integer length) -> String
9
+ attr_reader verifier: String
10
+ attr_reader challenge: String
11
11
 
12
- def self.generate_challenge: (String verifier) -> String
13
-
14
- def self.verify: (String challenge, String verifier) -> bool
15
-
16
- private
17
-
18
- private def self.validate_verifier_length: (Integer length) -> void
19
-
20
- private def self.validate_verifier: (String verifier) -> void
21
-
22
- private def self.secure_compare: (String str1, String str2) -> bool
12
+ def initialize: () -> void
23
13
  end
24
14
  end
@@ -12,8 +12,8 @@ module AuthProto
12
12
 
13
13
  def serialize_token_set: (State::TokenSet? tokens) -> String?
14
14
  def deserialize_token_set: (String? data) -> State::TokenSet?
15
- def serialize_auth_server: (ServerMetadata::AuthorizationServer? server) -> Hash[Symbol, untyped]?
16
- def deserialize_auth_server: (json_object? data) -> ServerMetadata::AuthorizationServer?
15
+ def serialize_auth_server: (Metadata::AuthorizationServer? server) -> Hash[Symbol, untyped]?
16
+ def deserialize_auth_server: (json_object? data) -> Metadata::AuthorizationServer?
17
17
  end
18
18
  end
19
19
  end
@@ -9,20 +9,17 @@ module AuthProto
9
9
  attr_reader scope: String
10
10
  attr_reader pkce_verifier: String
11
11
  attr_reader pkce_challenge: String
12
- attr_reader auth_server: ServerMetadata::AuthorizationServer?
12
+ attr_reader auth_server: Metadata::AuthorizationServer?
13
13
  attr_reader did: String?
14
14
  attr_reader tokens: TokenSet?
15
15
 
16
- def initialize: (client_id: String, scope: String, ?auth_server: ServerMetadata::AuthorizationServer?, ?did: String?) -> void
17
- def authorization_server=: (ServerMetadata::AuthorizationServer server) -> ServerMetadata::AuthorizationServer
16
+ def initialize: (client_id: String, scope: String, ?auth_server: Metadata::AuthorizationServer?, ?did: String?) -> void
17
+ def authorization_server=: (Metadata::AuthorizationServer server) -> Metadata::AuthorizationServer
18
18
  def did=: (String did) -> String
19
19
  def tokens=: (TokenSet tokens) -> String
20
+ def session_data: () -> AuthProto::session_data?
20
21
  def authorized?: () -> bool
21
22
  def renewable?: () -> bool
22
- def validate_state: (String? state) -> bool
23
-
24
- private
25
- def secure_compare: (String str1, String str2) -> bool
26
23
  end
27
24
  end
28
25
  end
@@ -4,11 +4,11 @@ module AuthProto
4
4
  @serializer: Serialization::Session
5
5
 
6
6
  def initialize: () -> void
7
- def create_session: (client_id: String, scope: String, ?auth_server: ServerMetadata::AuthorizationServer?, ?did: String?) -> Session
7
+ def create_session: (client_id: String, scope: String, ?auth_server: Metadata::AuthorizationServer?, ?did: String?) -> Session
8
8
  def update_session: (Session session) -> Session
9
9
  def get_session: (String session_id) -> Session?
10
10
  def get_session_by_state: (String? state) -> Session?
11
- def remove_session: (String session_id) -> void
11
+ def delete_session: (String session_id) -> void
12
12
  def cleanup_expired: () -> void
13
13
  end
14
14
  end
@@ -23,11 +23,11 @@ module AuthProto
23
23
  MAX_DELAY: Integer
24
24
  attr_reader session: State::Session
25
25
  attr_reader dpop_client: DPoP::Client
26
- attr_reader auth_server: ServerMetadata::AuthorizationServer
27
- attr_reader client_metadata: ClientMetadata
26
+ attr_reader auth_server: Metadata::AuthorizationServer
27
+ attr_reader client_metadata: Metadata::ClientMetadata
28
28
 
29
- def initialize: (session: State::Session, dpop_client: DPoP::Client, auth_server: ServerMetadata::AuthorizationServer, client_metadata: ClientMetadata) -> void
30
- def perform: () -> State::TokenSet
29
+ def initialize: (session: State::Session, dpop_client: DPoP::Client, auth_server: Metadata::AuthorizationServer, client_metadata: Metadata::ClientMetadata, ?signing_key: (json_object | JOSE::JWK)?) -> void
30
+ def perform_refresh: () -> State::TokenSet
31
31
 
32
32
  private
33
33
  def with_retries: [T] () { () -> T } -> T
@@ -0,0 +1,36 @@
1
+ module AuthProto
2
+ class ValidatedURI
3
+ @uri: URI::HTTP
4
+ @port: String?
5
+ @userinfo: String?
6
+ @path: String
7
+
8
+ attr_reader port: String?
9
+ attr_reader userinfo: String?
10
+ attr_reader path: String
11
+
12
+ def initialize: (String | URI::Generic url) -> void
13
+
14
+ def specified_port: () -> String?
15
+ def effective_port: () -> Integer
16
+ def to_uri: () -> URI::HTTP
17
+
18
+ def scheme: () -> String
19
+ def host: () -> String
20
+ def hostname: () -> String
21
+ def query: () -> String?
22
+ def fragment: () -> String?
23
+ def user: () -> String?
24
+ def password: () -> String?
25
+ def registry: () -> String?
26
+ def opaque: () -> String?
27
+ def default_port: () -> Integer
28
+ def request_uri: () -> String
29
+ def origin: () -> String
30
+ def absolute?: () -> bool
31
+ def relative?: () -> bool
32
+ def hierarchical?: () -> bool
33
+ def to_s: () -> String
34
+ def to_str: () -> String
35
+ end
36
+ end
data/sig/authproto.rbs CHANGED
@@ -7,9 +7,11 @@ module AuthProto
7
7
  type json_object = Hash[String, untyped]
8
8
  type http_body = String | Hash[untyped, untyped] | nil
9
9
  type http_response = { status: Integer, headers: Hash[String, String], body: String? }
10
- type token_info = { access_token: String, token_type: String, expires_in: Integer, refresh_token: String?, scope: String }
11
- type refreshed_tokens = { access_token: String, token_type: String, expires_in: Integer, refresh_token: String?, scope: String, session_id: String }
12
- type callback_result = { access_token: String, token_type: String, expires_in: Integer, refresh_token: String?, scope: String, session_id: String, did: String }
10
+ type session_data = { access_token: String, token_type: String, expires_in: Integer,
11
+ refresh_token: String?, scope: String, session_id: String, did: String }
12
+ type token_info = session_data
13
+ type refreshed_tokens = session_data
14
+ type callback_result = session_data
13
15
  type authorization_result = { url: String, session_id: String }
14
16
 
15
17
  class Error < StandardError
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authproto
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.beta1
4
+ version: 0.3.0.beta2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Huckabee
@@ -63,6 +63,7 @@ files:
63
63
  - ".rubocop.yml"
64
64
  - ".tm_properties"
65
65
  - ".yardopts"
66
+ - AGENTS.md
66
67
  - CHANGELOG.md
67
68
  - MIT-LICENSE.txt
68
69
  - README.md
@@ -74,7 +75,7 @@ files:
74
75
  - examples/confidential_client/README.md
75
76
  - examples/confidential_client/app.rb
76
77
  - examples/confidential_client/config.ru
77
- - examples/confidential_client/config/client-metadata.example.json
78
+ - examples/confidential_client/config/oauth-client-metadata.example.json
78
79
  - examples/confidential_client/public/styles.css
79
80
  - examples/confidential_client/screenshots/screenshot-1-sign-in.png
80
81
  - examples/confidential_client/screenshots/screenshot-2-success.png
@@ -93,7 +94,6 @@ files:
93
94
  - examples/minisky_console/production.rb
94
95
  - lib/authproto.rb
95
96
  - lib/authproto/client.rb
96
- - lib/authproto/client_metadata.rb
97
97
  - lib/authproto/configuration.rb
98
98
  - lib/authproto/dpop/client.rb
99
99
  - lib/authproto/dpop/key_manager.rb
@@ -105,6 +105,10 @@ files:
105
105
  - lib/authproto/http_client.rb
106
106
  - lib/authproto/insecure_http_client.rb
107
107
  - lib/authproto/localhost_server.rb
108
+ - lib/authproto/metadata.rb
109
+ - lib/authproto/metadata/authorization_server.rb
110
+ - lib/authproto/metadata/client_metadata.rb
111
+ - lib/authproto/metadata/resource_server.rb
108
112
  - lib/authproto/minisky.rb
109
113
  - lib/authproto/par.rb
110
114
  - lib/authproto/par/client.rb
@@ -117,10 +121,6 @@ files:
117
121
  - lib/authproto/serialization/session.rb
118
122
  - lib/authproto/serialization/stored_nonce.rb
119
123
  - lib/authproto/serialization/token_set.rb
120
- - lib/authproto/server_metadata.rb
121
- - lib/authproto/server_metadata/authorization_server.rb
122
- - lib/authproto/server_metadata/origin_url.rb
123
- - lib/authproto/server_metadata/resource_server.rb
124
124
  - lib/authproto/state.rb
125
125
  - lib/authproto/state/session.rb
126
126
  - lib/authproto/state/session_manager.rb
@@ -131,10 +131,11 @@ files:
131
131
  - lib/authproto/storage/redis.rb
132
132
  - lib/authproto/storage/sqlite.rb
133
133
  - lib/authproto/token/refresh.rb
134
+ - lib/authproto/validated_uri.rb
134
135
  - lib/authproto/version.rb
136
+ - misc/yard_attributes.rb
135
137
  - sig/authproto.rbs
136
138
  - sig/authproto/client.rbs
137
- - sig/authproto/client_metadata.rbs
138
139
  - sig/authproto/dependencies.rbs
139
140
  - sig/authproto/dpop/client.rbs
140
141
  - sig/authproto/dpop/key_manager.rbs
@@ -145,6 +146,9 @@ files:
145
146
  - sig/authproto/http_client.rbs
146
147
  - sig/authproto/insecure_http_client.rbs
147
148
  - sig/authproto/localhost_server.rbs
149
+ - sig/authproto/metadata/authorization_server.rbs
150
+ - sig/authproto/metadata/client_metadata.rbs
151
+ - sig/authproto/metadata/resource_server.rbs
148
152
  - sig/authproto/minisky_oauth.rbs
149
153
  - sig/authproto/par.rbs
150
154
  - sig/authproto/par/client.rbs
@@ -157,9 +161,6 @@ files:
157
161
  - sig/authproto/serialization/session.rbs
158
162
  - sig/authproto/serialization/stored_nonce.rbs
159
163
  - sig/authproto/serialization/token_set.rbs
160
- - sig/authproto/server_metadata/authorization_server.rbs
161
- - sig/authproto/server_metadata/origin_url.rbs
162
- - sig/authproto/server_metadata/resource_server.rbs
163
164
  - sig/authproto/state.rbs
164
165
  - sig/authproto/state/session.rbs
165
166
  - sig/authproto/state/session_manager.rbs
@@ -171,6 +172,7 @@ files:
171
172
  - sig/authproto/storage/redis_client.rbs
172
173
  - sig/authproto/storage/sqlite.rbs
173
174
  - sig/authproto/token/refresh.rbs
175
+ - sig/authproto/validated_uri.rbs
174
176
  - sig/authproto/version.rbs
175
177
  homepage: https://github.com/mackuba/authproto
176
178
  licenses: