{"record":{"id":"9d182cc9cb42a1ac","repo":"arsduo/koala","slug":"you-must-init-realtimeupdates-with-your-app-secret","errorCode":null,"errorMessage":"You must init RealtimeUpdates with your app secret in order to validate updates","messagePattern":"You must init RealtimeUpdates with your app secret in order to validate updates","errorType":"exception","errorClass":"Koala::Facebook::AppSecretNotDefinedError","httpStatus":null,"severity":"error","filePath":"lib/koala/realtime_updates.rb","lineNumber":133,"sourceCode":"          false\n        end\n      end\n\n      # Public: As a security measure, all updates from facebook are signed using\n      # X-Hub-Signature: sha1=XXXX where XXX is the sha1 of the json payload\n      # using your application secret as the key.\n      #\n      # Example:\n      #   # in Rails controller\n      #   # @oauth being a previously defined Koala::Facebook::OAuth instance\n      #   def receive_update\n      #     if @oauth.validate_update(request.body, headers)\n      #       ...\n      #     end\n      #   end\n      def validate_update(body, headers)\n        unless @secret\n          raise AppSecretNotDefinedError, \"You must init RealtimeUpdates with your app secret in order to validate updates\"\n        end\n\n        request_signature = headers['X-Hub-Signature'] || headers['HTTP_X_HUB_SIGNATURE']\n        return unless request_signature\n\n        signature_parts = request_signature.split(\"sha1=\")\n        request_signature = signature_parts[1]\n        calculated_signature = OpenSSL::HMAC.hexdigest('sha1', @secret, body)\n        calculated_signature == request_signature\n      end\n\n      # The Facebook subscription management URL for your application.\n      def subscription_path\n        @subscription_path ||= \"#{@app_id}/subscriptions\"\n      end\n    end\n  end\nend","sourceCodeStart":115,"sourceCodeEnd":151,"githubUrl":"https://github.com/arsduo/koala/blob/47d052063ef8b5644fb59e279da0b52687999f55/lib/koala/realtime_updates.rb#L115-L151","documentation":"RealtimeUpdates#validate_update verifies webhook deliveries by computing HMAC-SHA1 over the raw body keyed with the application secret and comparing it against the X-Hub-Signature header (or HTTP_X_HUB_SIGNATURE). An app access token can manage subscriptions but cannot produce that HMAC, so when the instance was initialized with only :app_access_token and @secret is nil, the method raises Koala::Facebook::AppSecretNotDefinedError before any crypto runs.","triggerScenarios":"RealtimeUpdates.new(app_id: id, app_access_token: token), the token-only setup that suffices for subscribe and list_subscriptions, followed by validate_update(request.body.read, request.headers) in a webhook controller. Also when Koala.config supplies app_access_token but no app_secret for the process handling webhooks.","commonSituations":"Webhook verification added after the subscription code was already written against a token; per-environment config that deliberately withholds the secret from web workers; substituting an OAuth app token where the secret is required.","solutions":["Initialize with the secret in addition to the token: RealtimeUpdates.new(app_id: id, app_access_token: token, secret: ENV[\"FACEBOOK_APP_SECRET\"]); subscriptions keep using the token.","Or ensure Koala.config.app_secret is set for the process that handles webhook callbacks.","Read the raw body into a string once and pass that same string to validate_update; some servers do not rewind request.body."],"exampleFix":"// before\n@rtu = Koala::Facebook::RealtimeUpdates.new(app_id: APP_ID, app_access_token: APP_TOKEN)\nverified = @rtu.validate_update(request.body.read, request.headers)\n\n// after\n@rtu = Koala::Facebook::RealtimeUpdates.new(\n  app_id: APP_ID,\n  app_access_token: APP_TOKEN,\n  secret: ENV.fetch(\"FACEBOOK_APP_SECRET\")\n)\nbody = request.body.read\nverified = @rtu.validate_update(body, request.headers)","handlingStrategy":"validation","validationCode":"def webhook_client\n  secret = ENV[\"FACEBOOK_APP_SECRET\"].to_s\n  raise ArgumentError, \"FACEBOOK_APP_SECRET required for webhook validation\" if secret.empty?\n  Koala::Facebook::RealtimeUpdates.new(app_id: ENV.fetch(\"FACEBOOK_APP_ID\"), secret: secret)\nend","typeGuard":"def can_validate_updates?(rtu)\n  rtu.respond_to?(:secret) && !rtu.secret.to_s.empty?\nend","tryCatchPattern":"begin\n  verified = @rtu.validate_update(body, request.headers)\nrescue Koala::Facebook::AppSecretNotDefinedError\n  head :internal_server_error # config gap: alert; never accept unverified updates\nend","preventionTips":["Always pass :secret alongside :app_access_token when the same instance will validate webhooks; a token cannot sign","Assert the secret is present in a boot-time config check on webhook-serving processes","Remember validate_update returns nil when the header is absent; treat that as unverified, not accepted"],"tags":["webhook","realtime-updates","app-secret","signature","hmac","koala","facebook"],"backgroundTag":"missing-app-secret","analyzedSha":"47d052063ef8b5644fb59e279da0b52687999f55","analyzedAt":"2026-08-23T10:19:03.891Z","schemaVersion":2},"datasetVersion":"2026-08-23T13:39:53.451Z"}