Class: Nonnative::Token

Inherits:
Object
  • Object
show all
Defined in:
lib/nonnative/token.rb

Overview

Builds signed tokens (JWT, PASETO, or SSH) for authenticating against services under test.

The consumer passes in the signing parameters they parsed from their own configuration; this class is not coupled to any particular service's configuration format. The generated token string is ready to pass to Header.auth_bearer.

Examples:

JWT

token = Nonnative::Token.new(kind: 'jwt', issuer: 'iss', key: 'key-1',
                             private_key: 'config/ed25519.pem', expiration: 3600)
header = Nonnative::Header.auth_bearer(token.generate(aud: 'GET /v1/things', sub: 'user-1'))

PASETO

token = Nonnative::Token.new(kind: 'paseto', issuer: 'iss', key: 'key-1',
                             private_key: 'config/ed25519.pem', expiration: 3600)
token.generate(aud: Nonnative::Token.grpc_audience('/health.v1.Health/Check'), sub: 'user-1')

See Also:

Constant Summary collapse

KINDS =

Supported token kinds mapped to their implementation.

{ 'jwt' => Nonnative::JwtToken, 'paseto' => Nonnative::PasetoToken, 'ssh' => Nonnative::SshToken }.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(kind:, issuer:, key:, private_key:, expiration:) ⇒ Token

Returns a new instance of Token.

Parameters:

  • kind (String)

    token kind, one of "jwt", "paseto", or "ssh"

  • issuer (String)

    the iss claim (unused by the ssh kind)

  • key (String)

    the key id (JWT kid header, PASETO kid footer, or SSH kid claim)

  • private_key (String)

    path to the Ed25519 private key file (PKCS#8 PEM for jwt/paseto, OpenSSH format for ssh)

  • expiration (Integer)

    token lifetime in seconds (drives exp)

Raises:

  • (ArgumentError)

    if the kind is not supported



50
51
52
53
# File 'lib/nonnative/token.rb', line 50

def initialize(kind:, issuer:, key:, private_key:, expiration:)
  klass = KINDS.fetch(kind) { raise ArgumentError, "Unsupported token kind '#{kind}'" }
  @token = klass.new(issuer: issuer, key: key, private_key: private_key, expiration: expiration)
end

Class Method Details

.grpc_audience(full_method) ⇒ String

Builds the audience string for a gRPC endpoint.

Parameters:

  • full_method (String)

    the gRPC full method (for example "/health.v1.Health/Check")

Returns:

  • (String)

    the audience string



39
40
41
# File 'lib/nonnative/token.rb', line 39

def grpc_audience(full_method)
  full_method
end

.http_audience(method, path) ⇒ String

Builds the audience string for an HTTP endpoint.

Parameters:

  • method (String)

    HTTP method (for example "GET")

  • path (String)

    request path (for example "/v1/things")

Returns:

  • (String)

    the audience string (for example "GET /v1/things")



31
32
33
# File 'lib/nonnative/token.rb', line 31

def http_audience(method, path)
  "#{method} #{path}"
end

Instance Method Details

#generate(aud:, sub:, issued_at: nil, not_before: nil, expires_at: nil) ⇒ String

Generates a signed token.

The optional time claims default to the current time (and the constructor expiration), so omitting them reproduces the token's normal claims. Supply them to mint tokens with specific time claims for negative auth tests, such as a not-yet-valid (future not_before) or clock-skewed token. Times are absolute; the ssh kind has no nbf claim and rejects not_before.

Parameters:

  • aud (String)

    the aud claim

  • sub (String)

    the sub claim

  • issued_at (Time, nil) (defaults to: nil)

    overrides the iat claim (default: now)

  • not_before (Time, nil) (defaults to: nil)

    overrides the nbf claim (default: issued_at); unsupported by ssh

  • expires_at (Time, nil) (defaults to: nil)

    overrides the exp claim (default: issued_at plus expiration)

Returns:

  • (String)

    the signed token



69
70
71
# File 'lib/nonnative/token.rb', line 69

def generate(aud:, sub:, issued_at: nil, not_before: nil, expires_at: nil)
  @token.generate(aud: aud, sub: sub, issued_at: issued_at, not_before: not_before, expires_at: expires_at)
end