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

  1. Decode and inspect the payload before blaming the parser: JSON.parse(Base64.decode64(payload.tr("-_", "+/"))) and check the algorithm field.
  2. Make sure the value came from Facebook (canvas POST signed_request param or fbsr_ cookie) and was not re-encoded on the way in.
  3. Rescue OAuthSignatureError and reject the request; never relax the algorithm check.
  4. 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

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


AI-assisted analysis of arsduo/koala@47d052063e (2026-08-23). Data as JSON: /api/errors/f3a3b753531cb818. Report an issue: GitHub.