Module: URLSignature

Defined in:
lib/url_signature.rb,
lib/url_signature/url.rb,
lib/url_signature/version.rb

Defined Under Namespace

Classes: URL

Constant Summary collapse

InvalidURL =
Class.new(StandardError)
ExpiredURL =
Class.new(StandardError)
InvalidSignature =
Class.new(StandardError)
HMAC_PROC =
lambda do |key, data|
  Base64.urlsafe_encode64(
    OpenSSL::HMAC.digest("SHA256", key, data.to_s),
    padding: false
  )
end
VERSION =
"0.0.2"

Class Method Summary collapse

Class Method Details

.call(url, key:, params: {}, expires: 0, signature_param: "signature", expires_param: "expires", hmac_proc: HMAC_PROC) ⇒ Object

Create a new signed url.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/url_signature.rb', line 24

def self.call(
  url,
  key:,
  params: {},
  expires: 0,
  signature_param: "signature",
  expires_param: "expires",
  hmac_proc: HMAC_PROC
)
  expires = expires.to_i
  params[expires_param] = expires if expires.positive?
  url = build_url(url, params)
  signature = hmac_proc.call(key, url)
  url.add_query(signature_param, signature)
  url.to_s
end

.verified?(url, key:, expires_param: "expires", signature_param: "signature", hmac_proc: HMAC_PROC) ⇒ Boolean

Returns:

  • (Boolean)


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/url_signature.rb', line 41

def self.verified?(
  url,
  key:,
  expires_param: "expires",
  signature_param: "signature",
  hmac_proc: HMAC_PROC
)
  verify!(
    url,
    key: key,
    hmac_proc: hmac_proc,
    expires_param: expires_param,
    signature_param: signature_param
  )
rescue InvalidSignature, InvalidURL, ExpiredURL
  false
end

.verify!(url, key:, hmac_proc: HMAC_PROC, expires_param: "expires", signature_param: "signature") ⇒ Object

rubocop:disable Metrics/MethodLength

Raises:



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
# File 'lib/url_signature.rb', line 59

def self.verify!( # rubocop:disable Metrics/MethodLength
  url,
  key:,
  hmac_proc: HMAC_PROC,
  expires_param: "expires",
  signature_param: "signature"
)
  url = build_url(url)
  actual_url = url.to_s

  url.remove_query(signature_param)

  expected_url = call(
    url.to_s,
    key: key,
    expires_param: expires_param,
    hmac_proc: hmac_proc,
    signature_param: signature_param
  )

  expires = url.params[expires_param]&.first.to_i

  raise ExpiredURL if expires.positive? && expires < Time.now.to_i
  raise InvalidSignature unless actual_url == expected_url

  true
end