Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions lib/vestauth.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,17 @@
require_relative "vestauth/version"
require_relative "vestauth/agent"
require_relative "vestauth/binary"
require_relative "vestauth/primitives"
require_relative "vestauth/tool"
require_relative "vestauth/provider"

module Vestauth
class Error < StandardError; end

def self.agent
Agent
end

def self.tool
Tool
end
Expand All @@ -17,8 +22,8 @@ class << self
alias provider tool
end

def self.agent
Agent
def self.primitives
Primitives
end

def self.binary
Expand Down
15 changes: 15 additions & 0 deletions lib/vestauth/agent.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,20 @@

module Vestauth
module Agent
module_function

def headers(http_method:, uri:, private_key:, id:)
vestauth_binary.agent_headers(
http_method: http_method,
uri: uri,
private_key: private_key,
id: id
)
end

def vestauth_binary
Vestauth::Binary.new
end
private_class_method :vestauth_binary
end
end
36 changes: 36 additions & 0 deletions lib/vestauth/binary.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,42 @@ def tool_verify(http_method:, uri:, signature:, signature_input:, signature_agen
run_json_command(command)
end

def agent_headers(http_method:, uri:, private_key:, id:)
command = [
@executable,
"agent",
"headers",
http_method,
uri,
"--private-jwk",
private_key,
"--uid",
id
]

run_json_command(command)
end
Comment thread
motdotla marked this conversation as resolved.

def primitives_verify(http_method:, uri:, signature_header:, signature_input_header:, public_key:)
public_jwk = public_key.as_json.to_json

command = [
@executable,
"primitives",
"verify",
http_method,
uri,
"--signature",
signature_header,
"--signature-input",
signature_input_header,
"--public-jwk",
public_jwk
]

run_json_command(command)
end
Comment on lines +48 to +66
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

primitives_verify serializes public_key via public_key.as_json.to_json, which is a Rails/ActiveSupport-ism and not guaranteed to exist in plain Ruby objects. This makes the gem unexpectedly depend on ActiveSupport conventions and can break for typical key objects (e.g., OpenSSL keys, JWT/JWK objects) unless they implement as_json.

Given this method is part of the public API surface, it should accept either a pre-serialized JWK string/Hash or perform a more robust conversion (e.g., accept a String that is already JSON, or a Hash and call JSON.generate).

Suggestion

Consider making public_key handling explicit and framework-independent by accepting String/Hash inputs and serializing with Ruby’s JSON only.

For example:

  • If public_key is a String, pass it through as-is (assume it is JSON).
  • If it’s a Hash, do public_jwk = JSON.generate(public_key).
  • Otherwise, raise a clear Vestauth::Error explaining what types are accepted.

Sketch:

public_jwk =
  case public_key
  when String
    public_key
  when Hash
    JSON.generate(public_key)
  else
    raise Vestauth::Error, "public_key must be a JWK JSON String or a Hash"
  end

Reply with "@CharlieHelps yes please" if you’d like me to add a commit with this suggestion.


private

def run_json_command(command_args)
Expand Down
22 changes: 22 additions & 0 deletions lib/vestauth/primitives.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# frozen_string_literal: true

module Vestauth
module Primitives
module_function

def verify(http_method:, uri:, signature_header:, signature_input_header:, public_key:)
vestauth_binary.primitives_verify(
http_method: http_method,
uri: uri,
signature_header: signature_header,
signature_input_header: signature_input_header,
public_key: public_key
)
end

def vestauth_binary
Vestauth::Binary.new
end
private_class_method :vestauth_binary
end
end
49 changes: 48 additions & 1 deletion spec/vestauth_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
expect(Vestauth::VERSION).not_to be nil
end

it "exposes namespaced tool/provider and agent modules" do
it "exposes namespaced tool/provider, agent, and primitives modules" do
expect(Vestauth::Tool).to eq(Vestauth::Provider)
expect(Vestauth.tool).to eq(Vestauth::Tool)
expect(Vestauth.provider).to eq(Vestauth::Tool)
expect(Vestauth.agent).to eq(Vestauth::Agent)
expect(Vestauth.primitives).to eq(Vestauth::Primitives)
expect(Vestauth.binary).to eq(Vestauth::Binary)
end

Expand Down Expand Up @@ -57,4 +58,50 @@
signature_agent: nil
)
end

it "delegates agent headers to binary agent_headers" do
binary = instance_double(Vestauth::Binary)
allow(Vestauth::Binary).to receive(:new).and_return(binary)
allow(binary).to receive(:agent_headers).and_return({ "Signature" => "sig1=:abc:" })

private_key = { "kty" => "EC" }
result = Vestauth.agent.headers(
http_method: "GET",
uri: "https://api.vestauth.com/whoami",
private_key: private_key,
id: "agent-123"
)

expect(binary).to have_received(:agent_headers).with(
http_method: "GET",
uri: "https://api.vestauth.com/whoami",
private_key: private_key,
id: "agent-123"
)
expect(result).to eq({ "Signature" => "sig1=:abc:" })
end

it "delegates primitives verify to binary primitives_verify" do
binary = instance_double(Vestauth::Binary)
allow(Vestauth::Binary).to receive(:new).and_return(binary)
allow(binary).to receive(:primitives_verify).and_return({ "success" => true })

public_key = instance_double("PublicKey")
result = Vestauth.primitives.verify(
http_method: "GET",
uri: "https://api.vestauth.com/whoami",
signature_header: "sig1=:abc:",
signature_input_header: "sig1=(\"@method\");keyid=\"kid-1\"",
public_key: public_key
)

expect(binary).to have_received(:primitives_verify).with(
http_method: "GET",
uri: "https://api.vestauth.com/whoami",
signature_header: "sig1=:abc:",
signature_input_header: "sig1=(\"@method\");keyid=\"kid-1\"",
public_key: public_key
)
expect(result).to eq({ "success" => true })
end
end
Loading