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
- 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
- Look at the server log immediately above: an 'APIv2 auth failed: ...' line names the real reason (unknown key, bad signature) the token never attached
- 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
- Route every APIv2 call through one signed-request helper so no endpoint can be hit bare
- Name the credential access_key, not access_token or api_key
- Keep credentials in one config source and fail fast at startup if either half of the pair is missing
- In tests, wrap protected endpoints with the same signing helper as production
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.