nonnative 3.46.0 → 3.47.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b2d99335be2a92924498425cc447af35544eece2ba160547ef0ac240184cc0e2
4
- data.tar.gz: 533de1c117bcb0f67cbcb5254afd291c35672d50dd6f6516a73d7fcd4195d431
3
+ metadata.gz: bc2bdb41b9c6411e257b89cb9a510170cde28cc454bac1680e1f0bfea546294c
4
+ data.tar.gz: f93f740ba3d1f67c299a392d2db7c31874c85331e935f0974f15e4e2094a85ef
5
5
  SHA512:
6
- metadata.gz: 6e0a0b556b0ca9386c4d91117cb349ce0e4ea412fc5a578227ae6c43571ff23d62b0cedd11ac616b81d1ee7a5ccb895f285629eff30bf715460fdc42c27f2f50
7
- data.tar.gz: 6382a115cf2b69785fba973c4c82e158cb583912480545ae6bce8a6746e767267350ca73348a96913e64dfb4229445361b3021fe297f601470c9152bee289c4b
6
+ metadata.gz: 50fd2d856178eaf96676746008cc4aa6477d3aee908a58c61375dc94e74675d3627c5020fd8125f1ba1ed15568d6dede9c1ae41efa2c5b0ac9e071e9f869d914
7
+ data.tar.gz: 40a613ee1b7553cecb51ef59d3834a14bfa15ba9659c8cdc41170f930be8d019a9c2147a40b01df83cbf35619ede80771cfb7266315d681477a2d580c9a22ea1
data/README.md CHANGED
@@ -221,10 +221,9 @@ headers = Nonnative::Header.auth_bearer(
221
221
  )
222
222
  ```
223
223
 
224
- Supported `kind` values (all Ed25519, generation only):
224
+ The supported `kind` is Ed25519 JWT generation only:
225
225
 
226
226
  - `jwt`: EdDSA JWT with the key id in the `kid` header. `private_key` is a PKCS#8 PEM file.
227
- - `paseto`: PASETO v4.public with the key id in a `{"kid":"..."}` footer. `private_key` is a PKCS#8 PEM file. Requires system **libsodium** (via `rbnacl`); it loads lazily, so `require 'nonnative'` works without libsodium until you generate a PASETO token.
228
227
 
229
228
  The audience is endpoint-scoped; build it with the helpers:
230
229
 
@@ -4,8 +4,7 @@ module Nonnative
4
4
  # Loads an Ed25519 private key from a PEM file for signing tokens.
5
5
  #
6
6
  # Verifiers such as go-service use Ed25519 keys encoded as PKCS#8 PEM. This reads the PEM once and
7
- # exposes it in the shapes the token backends need: the raw PEM for {Nonnative::PasetoToken} and the
8
- # 32-byte seed for {Nonnative::JwtToken}.
7
+ # exposes the 32-byte seed required by {Nonnative::JwtToken}.
9
8
  #
10
9
  # @example
11
10
  # key = Nonnative::Ed25519Key.new('config/ed25519.pem')
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Nonnative
4
- # Builds signed JWT or PASETO tokens for authenticating against services under test.
4
+ # Builds signed JWT tokens for authenticating against services under test.
5
5
  #
6
6
  # The consumer passes in the signing parameters they parsed from their own configuration; this class
7
7
  # is not coupled to any particular service's configuration format. The generated token string is
@@ -12,16 +12,8 @@ module Nonnative
12
12
  # private_key: 'config/ed25519.pem', expiration: 3600)
13
13
  # header = Nonnative::Header.auth_bearer(token.generate(aud: 'GET /v1/things', sub: 'user-1'))
14
14
  #
15
- # @example PASETO
16
- # token = Nonnative::Token.new(kind: 'paseto', issuer: 'iss', key: 'key-1',
17
- # private_key: 'config/ed25519.pem', expiration: 3600)
18
- # token.generate(aud: Nonnative::Token.grpc_audience('/health.v1.Health/Check'), sub: 'user-1')
19
- #
20
15
  # @see Nonnative::Header.auth_bearer
21
16
  class Token
22
- # Supported token kinds mapped to their implementation.
23
- KINDS = { 'jwt' => Nonnative::JwtToken, 'paseto' => Nonnative::PasetoToken }.freeze
24
-
25
17
  class << self
26
18
  # Builds the audience string for an HTTP endpoint.
27
19
  #
@@ -41,15 +33,16 @@ module Nonnative
41
33
  end
42
34
  end
43
35
 
44
- # @param kind [String] token kind, one of `"jwt"` or `"paseto"`
36
+ # @param kind [String] token kind, `"jwt"`
45
37
  # @param issuer [String] the `iss` claim
46
- # @param key [String] the key id (JWT `kid` header or PASETO `kid` footer)
38
+ # @param key [String] the key id (JWT `kid` header)
47
39
  # @param private_key [String] path to a PKCS#8 Ed25519 private key PEM file
48
40
  # @param expiration [Integer] token lifetime in seconds (drives `exp`)
49
41
  # @raise [ArgumentError] if the kind is not supported
50
42
  def initialize(kind:, issuer:, key:, private_key:, expiration:)
51
- klass = KINDS.fetch(kind) { raise ArgumentError, "Unsupported token kind '#{kind}'" }
52
- @token = klass.new(issuer: issuer, key: key, private_key: private_key, expiration: expiration)
43
+ raise ArgumentError, "Unsupported token kind '#{kind}'" unless kind == 'jwt'
44
+
45
+ @token = Nonnative::JwtToken.new(issuer: issuer, key: key, private_key: private_key, expiration: expiration)
53
46
  end
54
47
 
55
48
  # Generates a signed token.
@@ -4,5 +4,5 @@ module Nonnative
4
4
  # The current gem version.
5
5
  #
6
6
  # @return [String]
7
- VERSION = '3.46.0'
7
+ VERSION = '3.47.0'
8
8
  end
data/lib/nonnative.rb CHANGED
@@ -52,7 +52,6 @@ require 'uri'
52
52
  require 'openssl'
53
53
  require 'json'
54
54
  require 'time'
55
- require 'singleton' # ruby-paseto depends on this stdlib, which Ruby no longer auto-loads
56
55
 
57
56
  require 'grpc'
58
57
  require 'grpc/health/v1/health_services_pb'
@@ -68,8 +67,6 @@ require 'rspec/wait'
68
67
  require 'puma'
69
68
  require 'puma/server'
70
69
 
71
- # jwt-eddsa (with the ed25519 gem) is pure Ruby and needs no system library, so it loads here.
72
- # PASETO's rbnacl needs system libsodium, so Nonnative::PasetoToken requires it lazily instead.
73
70
  require 'jwt/eddsa'
74
71
 
75
72
  require 'nonnative/version'
@@ -124,7 +121,6 @@ require 'nonnative/cucumber'
124
121
  require 'nonnative/header'
125
122
  require 'nonnative/ed25519_key'
126
123
  require 'nonnative/jwt_token'
127
- require 'nonnative/paseto_token'
128
124
  require 'nonnative/token'
129
125
 
130
126
  # The main namespace for the gem.
@@ -216,9 +212,9 @@ module Nonnative
216
212
  # The signing parameters are passed in directly; this is not coupled to any service's
217
213
  # configuration format. The generated token string is ready for {Nonnative::Header.auth_bearer}.
218
214
  #
219
- # @param kind [String] token kind, one of `"jwt"` or `"paseto"`
215
+ # @param kind [String] token kind, `"jwt"`
220
216
  # @param issuer [String] the `iss` claim
221
- # @param key [String] the key id (JWT `kid` header or PASETO `kid` footer)
217
+ # @param key [String] the key id (JWT `kid` header)
222
218
  # @param private_key [String] path to a PKCS#8 Ed25519 private key PEM file
223
219
  # @param expiration [Integer] token lifetime in seconds (drives `exp`)
224
220
  # @return [Nonnative::Token]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nonnative
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.46.0
4
+ version: 3.47.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alejandro Falkowski
@@ -223,26 +223,6 @@ dependencies:
223
223
  - - "<"
224
224
  - !ruby/object:Gem::Version
225
225
  version: '9'
226
- - !ruby/object:Gem::Dependency
227
- name: rbnacl
228
- requirement: !ruby/object:Gem::Requirement
229
- requirements:
230
- - - ">="
231
- - !ruby/object:Gem::Version
232
- version: '7'
233
- - - "<"
234
- - !ruby/object:Gem::Version
235
- version: '8'
236
- type: :runtime
237
- prerelease: false
238
- version_requirements: !ruby/object:Gem::Requirement
239
- requirements:
240
- - - ">="
241
- - !ruby/object:Gem::Version
242
- version: '7'
243
- - - "<"
244
- - !ruby/object:Gem::Version
245
- version: '8'
246
226
  - !ruby/object:Gem::Dependency
247
227
  name: rest-client
248
228
  requirement: !ruby/object:Gem::Requirement
@@ -343,26 +323,6 @@ dependencies:
343
323
  - - "<"
344
324
  - !ruby/object:Gem::Version
345
325
  version: '2'
346
- - !ruby/object:Gem::Dependency
347
- name: ruby-paseto
348
- requirement: !ruby/object:Gem::Requirement
349
- requirements:
350
- - - ">="
351
- - !ruby/object:Gem::Version
352
- version: '0'
353
- - - "<"
354
- - !ruby/object:Gem::Version
355
- version: '1'
356
- type: :runtime
357
- prerelease: false
358
- version_requirements: !ruby/object:Gem::Requirement
359
- requirements:
360
- - - ">="
361
- - !ruby/object:Gem::Version
362
- version: '0'
363
- - - "<"
364
- - !ruby/object:Gem::Version
365
- version: '1'
366
326
  - !ruby/object:Gem::Dependency
367
327
  name: sinatra
368
328
  requirement: !ruby/object:Gem::Requirement
@@ -427,7 +387,6 @@ files:
427
387
  - lib/nonnative/no_proxy.rb
428
388
  - lib/nonnative/not_found_error.rb
429
389
  - lib/nonnative/observability.rb
430
- - lib/nonnative/paseto_token.rb
431
390
  - lib/nonnative/pool.rb
432
391
  - lib/nonnative/port.rb
433
392
  - lib/nonnative/ports.rb
@@ -1,64 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Nonnative
4
- # Generates Ed25519 PASETO v4.public tokens for authenticating against services under test.
5
- #
6
- # The key id is carried in a JSON footer (`{"kid":"..."}`), and the claims match the common
7
- # iss/aud/sub/iat/nbf/exp/jti set expected by verifiers such as go-service. The signing library is
8
- # required lazily so that requiring `nonnative` does not depend on `rbnacl`/libsodium being present.
9
- #
10
- # @example
11
- # paseto = Nonnative::PasetoToken.new(issuer: 'iss', key: 'key-1', private_key: 'config/ed25519.pem', expiration: 3600)
12
- # paseto.generate(aud: 'GET /v1/things', sub: 'user-1')
13
- #
14
- # @see https://github.com/bannable/paseto ruby-paseto
15
- class PasetoToken
16
- # @param issuer [String] the `iss` claim
17
- # @param key [String] the key id carried in the `kid` footer
18
- # @param private_key [String] path to a PKCS#8 Ed25519 private key PEM file
19
- # @param expiration [Integer] token lifetime in seconds (drives `exp`)
20
- def initialize(issuer:, key:, private_key:, expiration:)
21
- @issuer = issuer
22
- @key = key
23
- @ed25519 = Nonnative::Ed25519Key.new(private_key)
24
- @expiration = expiration
25
- end
26
-
27
- # Generates a signed PASETO v4.public token.
28
- #
29
- # @param aud [String] the `aud` claim (for example `"GET /v1/things"` or a gRPC full method)
30
- # @param sub [String] the `sub` claim
31
- # @param issued_at [Time, nil] overrides the `iat` claim (default: now)
32
- # @param not_before [Time, nil] overrides the `nbf` claim (default: `issued_at`)
33
- # @param expires_at [Time, nil] overrides the `exp` claim (default: `issued_at` plus `expiration`)
34
- # @return [String] the signed PASETO token
35
- def generate(aud:, sub:, issued_at: nil, not_before: nil, expires_at: nil)
36
- load_dependencies!
37
-
38
- now = (issued_at || Time.now).utc
39
- claims = {
40
- 'iss' => @issuer,
41
- 'aud' => aud,
42
- 'sub' => sub,
43
- 'iat' => now.iso8601,
44
- 'nbf' => (not_before || now).utc.iso8601,
45
- 'exp' => (expires_at || (now + @expiration)).utc.iso8601,
46
- 'jti' => SecureRandom.uuid
47
- }
48
-
49
- Paseto::V4::Public.new(@ed25519.pem).encode!(claims, footer: { 'kid' => @key }.to_json)
50
- end
51
-
52
- private
53
-
54
- # Loads the PASETO signing libraries lazily and raises a clear error if they are unavailable.
55
- # rbnacl loads system libsodium at runtime, which the gemspec cannot guarantee, so requiring it
56
- # here keeps `require 'nonnative'` working without libsodium for consumers that do not use PASETO.
57
- def load_dependencies!
58
- require 'rbnacl'
59
- require 'paseto'
60
- rescue LoadError => e
61
- raise Nonnative::Error, "PASETO token generation requires libsodium and the rbnacl and ruby-paseto gems (#{e.message})"
62
- end
63
- end
64
- end