Class: Faraday::Uid2::Middleware

Inherits:
Middleware
  • Object
show all
Defined in:
lib/faraday/uid2/middleware.rb

Instance Method Summary collapse

Constructor Details

#initialize(app, options = {}) ⇒ Middleware

Returns a new instance of Middleware.



10
11
12
13
14
15
# File 'lib/faraday/uid2/middleware.rb', line 10

def initialize(app, options = {})
  super(app)

  @key = Base64.decode64(options.fetch(:secret_key))
  @is_refresh = options.fetch(:is_refresh, false)
end

Instance Method Details

#call(request_env) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/faraday/uid2/middleware.rb', line 17

def call(request_env)
  unless @is_refresh
    @nonce = Random.new.bytes(8)

    cipher = create_cipher.encrypt
    iv = cipher.random_iv

    body = request_env.body
    payload = timestamp_bytes + @nonce + body
    encrypted = cipher.update(payload) + cipher.final
    request_env.body = Base64.strict_encode64(["\x1", iv, encrypted, cipher.auth_tag].join)
  end

  @app.call(request_env).on_complete do |response_env|
    process_response(response_env)
  end
end

#create_cipherObject



67
68
69
70
71
72
73
# File 'lib/faraday/uid2/middleware.rb', line 67

def create_cipher
  cipher = OpenSSL::Cipher.new("aes-256-gcm").encrypt
  cipher.padding = 0
  cipher.key = @key
  cipher.auth_data = ""
  cipher
end

#process_response(env) ⇒ Object



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
# File 'lib/faraday/uid2/middleware.rb', line 35

def process_response(env)
  resp = Base64.decode64(env.body).unpack("C*")
  iv = resp[0..11].pack("C*")
  cipher_text = resp[12...-16].pack("C*")
  auth_tag = resp[-16...-1].pack("C*")

  cipher = create_cipher.decrypt
  cipher.iv = iv
  cipher.auth_tag = auth_tag

  payload = cipher.update(cipher_text) + cipher.final

  data = if @is_refresh
    payload
  else
    timestamp = Time.at(payload[0..7].unpack1("Q>") / 1000.0)
    raise Faraday::ParsingError.new("Response timestamp is too old", env[:response]) if Time.now - timestamp > 5 * 60

    nonce = payload[8..15]
    raise Faraday::ParsingError.new("Nonce mismatch", env[:response]) if nonce != @nonce

    payload[16..]
  end

  env.response_headers["Content-Type"] = "application/json"
  env.body = Hashie::Mash.new(JSON.parse(data))
end

#timestamp_bytesObject



63
64
65
# File 'lib/faraday/uid2/middleware.rb', line 63

def timestamp_bytes
  [(Time.now.to_f * 1000).to_i].pack("Q>")
end