Skip to content

Conversation

habara-k
Copy link
Contributor

Changes

  • Allow skipping signature verification for webhooks

Motivation

The signature returned with webhooks is calculated using a single channel secret. If the bot owner changes their channel secret, the signature for webhooks starts being calculated using the new channel secret. To avoid signature verification failures, the bot owner must update the channel secret on their server, which is used for signature verification. However, if there is a timing mismatch in the update—and such a mismatch is almost unavoidable—verification will fail during that period.

In such cases, having an option to skip signature verification for webhooks would be a convenient way to avoid these issues.

@habara-k habara-k requested a review from a team September 18, 2025 08:15
Comment on lines 8 to 10
@skip_signature_verification: Proc?

def initialize: (channel_secret: String) -> void
def initialize: (channel_secret: String, ?skip_signature_verification: Proc?) -> void
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we address this by writing like this, so as not to ignore in RBS? Type errors should be pointing out issues, so I'd like to avoid adding # steep:ignore as much as possible.

like

interface SkipSignatureValidationPredicate
  def call: () -> bool
end
...
@skip_signature_verification: SkipSignatureValidationPredicate?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines 18 to 22
# @param skip_signature_verification [Proc, nil]
# A function that determines whether to skip webhook signature verification.
# If the function returns true, the signature verification step is skipped.
# This can be useful in scenarios such as when you're in the process of updating
# the channel secret and need to temporarily bypass verification to avoid disruptions.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably it's more explicit if this document explains "the function must returns boolean value", though this already says "If the function returns true"?

Copy link
Contributor

@Yang-33 Yang-33 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

code in current patch seems good, but could you address #652 too?

@habara-k
Copy link
Contributor Author

Understood. I will also handle that issue, but for the sake of keeping this PR independent, I will address it in a follow-up PR.

Copy link
Contributor

@Yang-33 Yang-33 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave it to you, but it's just about moving the private keyword down...

@habara-k habara-k requested a review from Yang-33 September 19, 2025 09:19
Copy link
Contributor

@Yang-33 Yang-33 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! After releasing this change, please inform the participants of that issue about the released version in the issue!

Comment on lines +18 to +25
# @param skip_signature_verification [() -> bool, nil]
# A callable object with type `() -> bool` that determines whether to skip
# webhook signature verification. Signature verification is skipped if and
# only if this callable is provided and returns `true`.
# This can be useful in scenarios such as when you're in the process of
# updating the channel secret and need to temporarily bypass verification
# to avoid disruptions.
def initialize(channel_secret:, skip_signature_verification: nil)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be better if skip_signature_verification accepts not only Procs but also boolean values. It is possible to pass Procs like -> { true } or -> { false } but just checking boolean (without calling) would be more efficient.

for example:

def should_skip_verification?
  if @skip_signature_verification.respond_to?(:call)
    @skip_signature_verification.call
  else
    @skip_signature_verification
  end
end

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much for your suggestion. Allowing boolean values could certainly be convenient in some cases. However, having both ()-> bool and bool in the same field would increase type complexity.

This feature is primarily intended for use cases where the decision to skip signature verification may change dynamically—for example, when controlled by environment variables.

Since the same behavior can be achieved by passing a function that simply returns a fixed true or false, we have decided not to adopt direct boolean support at this time.

@habara-k habara-k added this pull request to the merge queue Sep 22, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Sep 22, 2025
@habara-k habara-k added this pull request to the merge queue Sep 22, 2025
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Sep 22, 2025
@habara-k habara-k added this pull request to the merge queue Sep 24, 2025
Merged via the queue into master with commit 9eb91a6 Sep 24, 2025
10 checks passed
@habara-k habara-k deleted the allow-to-skip-signature-verification branch September 24, 2025 01:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants