arsduo/koala · error · Koala::Facebook::OAuthSignatureError
Unsupported algorithm #{envelope['algorithm']}
Error message
Unsupported algorithm #{envelope['algorithm']} What it means
After base64-decoding the payload half of a signed_request, OAuth#parse_signed_request requires envelope["algorithm"] to be exactly HMAC-SHA256, the only algorithm Facebook uses for signed requests. Anything else (including a missing algorithm key) raises OAuthSignatureError with the received value embedded in the message. This is a deliberate safety stop in the same family as JWT alg-confusion: verifying a payload under an unexpected algorithm would let the sender choose how the signature is checked.
Source
Thrown at lib/koala/oauth.rb:245
info["access_token"]
end
end
# Parses a signed request string provided by Facebook to canvas apps or in a secure cookie.
#
# @param input the signed request from Facebook
#
# @raise OAuthSignatureError if the signature is incomplete, invalid, or using an unsupported algorithm
#
# @return a hash of the validated request information
def parse_signed_request(input)
encoded_sig, encoded_envelope = input.split('.', 2)
raise OAuthSignatureError, 'Invalid (incomplete) signature data' unless encoded_sig && encoded_envelope
signature = base64_url_decode(encoded_sig).unpack("H*").first
envelope = JSON.parse(base64_url_decode(encoded_envelope))
raise OAuthSignatureError, "Unsupported algorithm #{envelope['algorithm']}" if envelope['algorithm'] != 'HMAC-SHA256'
# now see if the signature is valid (digest, key, data)
hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::SHA256.new, @app_secret, encoded_envelope)
raise OAuthSignatureError, 'Invalid signature' if (signature != hmac)
envelope
end
protected
def get_token_from_server(args, post = false, options = {})
# fetch the result from Facebook's servers
response = fetch_token_string(args, post, "access_token", options)
parse_access_token(response)
end
def parse_access_token(response_text)
JSON.parse(response_text)View on GitHub (pinned to 47d052063e)
Solutions
- Decode and inspect the payload before blaming the parser: JSON.parse(Base64.decode64(payload.tr("-_", "+/"))) and check the algorithm field.
- Make sure the value came from Facebook (canvas POST signed_request param or fbsr_ cookie) and was not re-encoded on the way in.
- Rescue OAuthSignatureError and reject the request; never relax the algorithm check.
- Rebuild test fixtures from a real captured signed_request.
Example fix
// before
auth = @oauth.parse_signed_request(params[:signed_request])
// after
begin
auth = @oauth.parse_signed_request(params[:signed_request])
rescue Koala::Facebook::OAuthSignatureError => e
Rails.logger.warn("rejected signed_request: #{e.message}")
auth = nil
end Defensive patterns
Strategy: try-catch
Validate before calling
def facebook_signed_request?(raw)
sig, payload = raw.to_s.split(".", 2)
return false unless sig && payload
envelope = JSON.parse(Base64.decode64(payload.tr("-_", "+/"))) rescue nil
envelope.is_a?(Hash) && envelope["algorithm"] == "HMAC-SHA256"
end Try / catch
begin auth = @oauth.parse_signed_request(raw) rescue Koala::Facebook::OAuthSignatureError => e report_security_event(e.message) # unexpected algorithm deserves alerting head :unauthorized end
Prevention
- Capture real signed_request values from Facebook for tests instead of synthesizing JWT-like tokens
- Label tokens per provider so a non-Facebook token never reaches the Facebook parser
- Treat any algorithm other than HMAC-SHA256 as a security signal, not just a login failure
When it happens
Trigger: parse_signed_request (or get_user_info_from_cookies via parse_signed_cookie) receives a syntactically valid signature.envelope string whose decoded JSON names a different algorithm (HMAC-SHA1, RS256, a lowercase variant) or has no algorithm field: signed requests minted by another provider or a test tool, a corrupted envelope that still parses as JSON, or a hand-written fixture.
Common situations: Sharing JWT-style fixtures across provider test suites; routing a Google or Apple token into the Facebook parser in a multi-provider login; base64 mishandling that shifts the payload so fields land wrong; Facebook-side payload experiments.
Related errors
- Invalid (incomplete) signature data
- Invalid signature
- generate_client_code received an error: empty response body
- Koala::Utils.logger.warn("Signed cookie didn't contain Faceb
- ServerError.new(response.status, response.body)
AI-assisted analysis of arsduo/koala@47d052063e (2026-08-23).
Data as JSON: /api/errors/f3a3b753531cb818.
Report an issue: GitHub.