File: message_verifier_spec.rb

package info (click to toggle)
ruby-flipper 0.26.2-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,288 kB
  • sloc: ruby: 16,377; sh: 61; javascript: 24; makefile: 14
file content (104 lines) | stat: -rw-r--r-- 4,578 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
require 'flipper/cloud/message_verifier'

RSpec.describe Flipper::Cloud::MessageVerifier do
  let(:payload) { "some payload" }
  let(:secret) { "secret" }
  let(:timestamp) { Time.now }

  describe "#generate" do
    it "generates signature that can be verified" do
      message_verifier = Flipper::Cloud::MessageVerifier.new(secret: secret)
      signature = message_verifier.generate(payload, timestamp)
      header = generate_header(timestamp: timestamp, signature: signature)
      expect(message_verifier.verify(payload, header)).to be(true)
    end
  end

  describe "#header" do
    it "generates a header in valid format" do
      version = "v1"
      message_verifier = Flipper::Cloud::MessageVerifier.new(secret: secret, version: version)
      signature = message_verifier.generate(payload, timestamp)
      header = message_verifier.header(signature, timestamp)
      expect(header).to eq("t=#{timestamp.to_i},#{version}=#{signature}")
    end
  end

  describe ".header" do
    it "generates a header in valid format" do
      version = "v1"
      message_verifier = Flipper::Cloud::MessageVerifier.new(secret: secret, version: version)
      signature = message_verifier.generate(payload, timestamp)

      header = Flipper::Cloud::MessageVerifier.header(signature, timestamp, version)
      expect(header).to eq("t=#{timestamp.to_i},#{version}=#{signature}")
    end
  end

  describe "#verify" do
    it "raises a InvalidSignature when the header does not have the expected format" do
      header = "i'm not even a real signature header"
      expect {
        message_verifier = Flipper::Cloud::MessageVerifier.new(secret: "secret")
        message_verifier.verify(payload, header)
      }.to raise_error(Flipper::Cloud::MessageVerifier::InvalidSignature, "Unable to extract timestamp and signatures from header")
    end

    it "raises a InvalidSignature when there are no signatures with the expected version" do
      header = generate_header(version: "v0")
      expect {
        message_verifier = Flipper::Cloud::MessageVerifier.new(secret: "secret")
        message_verifier.verify(payload, header)
      }.to raise_error(Flipper::Cloud::MessageVerifier::InvalidSignature, /No signatures found with expected version/)
    end

    it "raises a InvalidSignature when there are no valid signatures for the payload" do
      header = generate_header(signature: "bad_signature")
      expect {
        message_verifier = Flipper::Cloud::MessageVerifier.new(secret: "secret")
        message_verifier.verify(payload, header)
      }.to raise_error(Flipper::Cloud::MessageVerifier::InvalidSignature, "No signatures found matching the expected signature for payload")
    end

    it "raises a InvalidSignature when the timestamp is not within the tolerance" do
      header = generate_header(timestamp: Time.now - 15)
      expect {
        message_verifier = Flipper::Cloud::MessageVerifier.new(secret: secret)
        message_verifier.verify(payload, header, tolerance: 10)
      }.to raise_error(Flipper::Cloud::MessageVerifier::InvalidSignature, /Timestamp outside the tolerance zone/)
    end

    it "returns true when the header contains a valid signature and the timestamp is within the tolerance" do
      header = generate_header
      message_verifier = Flipper::Cloud::MessageVerifier.new(secret: "secret")
      expect(message_verifier.verify(payload, header, tolerance: 10)).to be(true)
    end

    it "returns true when the header contains at least one valid signature" do
      header = generate_header + ",v1=bad_signature"
      message_verifier = Flipper::Cloud::MessageVerifier.new(secret: secret)
      expect(message_verifier.verify(payload, header, tolerance: 10)).to be(true)
    end

    it "returns true when the header contains a valid signature and the timestamp is off but no tolerance is provided" do
      header = generate_header(timestamp: Time.at(12_345))
      message_verifier = Flipper::Cloud::MessageVerifier.new(secret: secret)
      expect(message_verifier.verify(payload, header)).to be(true)
    end
  end

  private

  def generate_header(options = {})
    options[:secret] ||= secret
    options[:version] ||= "v1"

    message_verifier = Flipper::Cloud::MessageVerifier.new(secret: options[:secret], version: options[:version])

    options[:timestamp] ||= timestamp
    options[:payload] ||= payload
    options[:signature] ||= message_verifier.generate(options[:payload], options[:timestamp])

    Flipper::Cloud::MessageVerifier.header(options[:signature], options[:timestamp], options[:version])
  end
end