diff --git a/lib/mcp_client/auth.rb b/lib/mcp_client/auth.rb index 93bb07e..8f4652f 100644 --- a/lib/mcp_client/auth.rb +++ b/lib/mcp_client/auth.rb @@ -308,9 +308,12 @@ def to_h end # Create PKCE instance from hash - # @param data [Hash] Hash with PKCE parameters + # @param data [Hash] Hash with PKCE parameters (symbol or string keys) # @return [PKCE] New PKCE instance # @raise [ArgumentError] If required parameters are missing + # @note code_challenge_method is optional and defaults to 'S256'. + # The code_challenge is not re-validated against code_verifier; + # callers are expected to provide values from a prior to_h round-trip. def self.from_h(data) verifier = data[:code_verifier] || data['code_verifier'] challenge = data[:code_challenge] || data['code_challenge'] diff --git a/spec/lib/mcp_client/auth_spec.rb b/spec/lib/mcp_client/auth_spec.rb index e0bc3f2..717578f 100644 --- a/spec/lib/mcp_client/auth_spec.rb +++ b/spec/lib/mcp_client/auth_spec.rb @@ -138,7 +138,7 @@ end describe '#to_h and .from_h' do - it 'round-trips data with symbol and string keys' do + it 'round-trips data with symbol keys' do original = described_class.new restored = described_class.from_h(original.to_h) expect(restored.code_verifier).to eq(original.code_verifier) @@ -146,6 +146,15 @@ expect(restored.code_challenge_method).to eq('S256') end + it 'round-trips data with string keys' do + original = described_class.new + string_hash = original.to_h.transform_keys(&:to_s) + restored = described_class.from_h(string_hash) + expect(restored.code_verifier).to eq(original.code_verifier) + expect(restored.code_challenge).to eq(original.code_challenge) + expect(restored.code_challenge_method).to eq('S256') + end + it 'raises error when required fields are missing' do expect { described_class.from_h({}) }.to raise_error(ArgumentError) end