class Rack::DiscordInteractions::Verifier

Middleware to handle verification of interaction signatures

Constants

INVALID_SIGNATURE

@!visibility private

MISSING_HEADERS

@!visibility private

PONG

@!visibility private

Public Class Methods

new(app, public_key, path: nil, handle_pings: true) click to toggle source

@param app [#call] The rack app, or an object that responds to `#call`. @param public_key [String] The public key of the application. @param path [String] Path to verify, will verify all requests if `nil`. @param handle_pings [true, false] Whether the middleware should automatically handle responding to pings.

# File lib/rack/discord-interactions/verifier.rb, line 24
def initialize(app, public_key, path: nil, handle_pings: true)
  @app = app
  @verify_key = Ed25519::VerifyKey.new([public_key].pack('H*'))
  @path = path
  @handle_pings = handle_pings
end

Public Instance Methods

call(env) click to toggle source

@!visibility private @param env [Hash]

# File lib/rack/discord-interactions/verifier.rb, line 33
def call(env)
  if env['PATH_INFO'] == @path || @path.nil?
    request = Rack::Request.new(env)
    verify(request)
  else
    @app.call(env)
  end
end
verify(request) click to toggle source

@!visibility private @param request [Rack::Request]

# File lib/rack/discord-interactions/verifier.rb, line 44
def verify(request)
  timestamp = request.get_header('HTTP_X_SIGNATURE_TIMESTAMP')
  signature = request.get_header('HTTP_X_SIGNATURE_ED25519')
  body = request.body.read

  return MISSING_HEADERS unless timestamp && signature

  @verify_key.verify([signature].pack('H*'), timestamp + body)
  request.body.rewind

  return PONG if @handle_pings && JSON.parse(body)['type'] == 1

  @app.call(request.env)
rescue ArgumentError, Ed25519::VerifyError
  INVALID_SIGNATURE
end