hpyhacking/peatio · error · APIv2::AuthorizationError

2001

2001

Error message

Authorization failed

What it means

Error code 2001 (AuthorizationError, 'Authorization failed') is raised by APIv2::Helpers#authenticate! when current_user is nil. current_user resolves to current_token.try(:member), and current_token is whatever the APIv2 auth middleware stored in env['api_v2.token']. So this error means the request ended up with no authenticated API token at all: the auth params were absent, or an earlier auth step (invalid/disabled/expired key, bad signature) failed so the token never got attached to the env.

Source

Thrown at app/api/api_v2/helpers.rb:5

module APIv2
  module Helpers

    def authenticate!
      current_user or raise AuthorizationError
    end

    def redis
      @r ||= KlineDB.redis
    end

    def current_user
      @current_user ||= current_token.try(:member)
    end

    def current_token
      @current_token ||= env['api_v2.token']
    end

    def current_market
      @current_market ||= Market.find params[:market]
    end

View on GitHub (pinned to dab8641137)

Solutions

  1. Send the complete auth param set on every call — access_key, tonce, signature, plus the endpoint's own params — all included in the signed payload
  2. Look at the server log immediately above: an 'APIv2 auth failed: ...' line names the real reason (unknown key, bad signature) the token never attached
  3. Verify the APIv2 auth middleware is mounted before the Grape app so env['api_v2.token'] is populated before helpers run

Example fix

# before — session-style call without API credentials
get '/api/v2/members/me.json'

# after — full signed request
params = auth_params.merge(access_key: ACCESS_KEY)
params[:tonce] = next_tonce
payload = "GET|/api/v2/members/me.json|#{URI.unescape(params.except(:format).to_query)}"
params[:signature] = OpenSSL::HMAC.hexdigest('SHA256', SECRET_KEY, payload)
get '/api/v2/members/me.json', params: params
Defensive patterns

Strategy: validation

Validate before calling

# Guard: refuse to call protected endpoints unless auth material is complete
def assert_authenticated!(params)
  %w[access_key tonce signature].each do |k|
    raise "missing auth param: #{k}" if params[k].to_s.empty?
  end
end
assert_authenticated!(params)
get '/api/v2/members/me.json', params: params

Try / catch

On 2001, stop the call chain and re-authenticate: dump the params actually sent (access_key present? tonce fresh? signature computed over those exact params?) and check the server log for the preceding 'APIv2 auth failed' line; blind retries with the same params always fail.

Prevention

When it happens

Trigger: Calling an endpoint that invokes authenticate! without access_key/tonce/signature params; a prior auth failure leaving env['api_v2.token'] unset; the auth middleware not mounted before the Grape endpoint; a proxy or serializer dropping query/body params so the authenticator never sees the credentials.

Common situations: Porting a script from the session-cookie web UI to APIv2 without adding HMAC auth params; naming the credential access_token instead of access_key; signing params placed in the body while the endpoint reads the query string (or vice versa); test suites hitting protected endpoints without an auth helper.

Related errors


AI-assisted analysis of hpyhacking/peatio@dab8641137 (2026-08-23). Data as JSON: /api/errors/24e06fa4949f98c5. Report an issue: GitHub.