Skip to content

[IMP] booking_channex: add config parameter for channex webhook secret#19

Open
chga-odoo wants to merge 1 commit into
saas-19.3-booking-channex-main-branch-frvafrom
saas-19.3-booking-channex-webhook-secure-chga
Open

[IMP] booking_channex: add config parameter for channex webhook secret#19
chga-odoo wants to merge 1 commit into
saas-19.3-booking-channex-main-branch-frvafrom
saas-19.3-booking-channex-webhook-secure-chga

Conversation

@chga-odoo

Copy link
Copy Markdown

secure webhook adding a kind of security token to secure this communication.

Task: 6043950

@chga-odoo
chga-odoo force-pushed the saas-19.3-booking-channex-webhook-secure-chga branch from 6a5df29 to 79de7fb Compare July 3, 2026 13:18

@pgu-odoo pgu-odoo left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@chga-odoo Good work. A few remarks are added.

channex_secret_token = payload.get('headers', {}).get('X-Channex-Webhook-Secret')

if not channex_secret_token or channex_secret_token != odoo_secret_token:
raise UserError("Invalid secret token for Channex webhook") # temperary for testing,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
raise UserError("Invalid secret token for Channex webhook") # temperary for testing,
raise UserError("Unauthorized access.") # temperary for testing,

<field name="state">code</field>
<field name="code"><![CDATA[
#TODO: validate secret token in header with booking_channex.x_channex_secret_token in ir.config_parameter
odoo_secret_token = env['ir.config_parameter'].get_str('booking_channex.x_channex_secret_token')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

why get_str() and not get_param()?

@chga-odoo chga-odoo Jul 13, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

We can use get_param() but its return False if we not set default ' '
and get_str() return string always so that i thought better to return string always.
what you think?
get_param() is also check access rights so I think batter to use that 😊

Comment on lines +605 to +606
if not env['ir.config_parameter'].get_str('booking_channex.x_channex_secret_token'):
raise UserError("Error generating secret token for Channex webhook")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

  1. Check if the correct expected value is set or not.
  2. Update msg.
Suggested change
if not env['ir.config_parameter'].get_str('booking_channex.x_channex_secret_token'):
raise UserError("Error generating secret token for Channex webhook")
if env['ir.config_parameter'].get_str('booking_channex.x_channex_secret_token') != token:
raise UserError("Failed to store the Channex webhook secret token.")

"request_params": {},
"headers": {},
"headers": {
"X-Channex-Webhook-Secret": env['ir.config_parameter'].get_str('booking_channex.x_channex_secret_token')

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
"X-Channex-Webhook-Secret": env['ir.config_parameter'].get_str('booking_channex.x_channex_secret_token')
"x-channex-token": env['ir.config_parameter'].get_str('booking_channex.x_channex_token')
  1. You can use either all letters in small or in caps.
  2. You can keep both key and system parameter's name same.

@chga-odoo
chga-odoo force-pushed the saas-19.3-booking-channex-webhook-secure-chga branch 2 times, most recently from fe02859 to 676fa26 Compare July 13, 2026 06:48
@pgu-odoo

Copy link
Copy Markdown

@vava-odoo PR is ready to review.

@chga-odoo
chga-odoo force-pushed the saas-19.3-booking-channex-webhook-secure-chga branch from 676fa26 to b1f1435 Compare July 13, 2026 09:27
headers={'Content-Type': 'application/json'}
)
self.assertTrue(self.env['sale.order.line'].search_count([('product_id', '=', room.id)]), 'The sale order has not been created when webhook received the payload.')
self.assertTrue(not self.env['sale.order.line'].search_count([('product_id', '=', room.id)]), 'The sale order has been created when webhook received the payload with wrong token.')

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
self.assertTrue(not self.env['sale.order.line'].search_count([('product_id', '=', room.id)]), 'The sale order has been created when webhook received the payload with wrong token.')
self.assertFalse(self.env['sale.order.line'].search_count([('product_id', '=', room.id)], limit=1), 'The sale order has been created when webhook received the payload with wrong token.')


payload_receive_booking['headers']['x-channex-token'] = 'MyTestWebhookSecret'
with (
self.assertLogs(level="WARNING"), # Is preventing any warning to be logged, we should replace this to ignore only the Unsafe Error

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

which kind of warning happens here?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

thrown error from called server actions.

Comment on lines +150 to +154
with (
self.assertLogs(level="WARNING"), # Is preventing any warning to be logged, we should replace this to ignore only the Unsafe Error
MockHTTPClient(url="https://staging.channex.io/api/v1/booking_revisions/074cd7f9-df51-4fc6-a8f4-7658573a235d/ack", return_json=booking_ack_answer, return_status=200),
MockHTTPClient(url="https://staging.channex.io/api/v1/bookings/e868f16e-b474-4b95-af12-5b114133e670", return_json=get_booking_answer, return_status=200),
):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

indent issue

Comment on lines +149 to +154
payload_receive_booking['headers']['x-channex-token'] = 'MyTestWebhookSecret'
with (
self.assertLogs(level="WARNING"), # Is preventing any warning to be logged, we should replace this to ignore only the Unsafe Error
MockHTTPClient(url="https://staging.channex.io/api/v1/booking_revisions/074cd7f9-df51-4fc6-a8f4-7658573a235d/ack", return_json=booking_ack_answer, return_status=200),
MockHTTPClient(url="https://staging.channex.io/api/v1/bookings/e868f16e-b474-4b95-af12-5b114133e670", return_json=get_booking_answer, return_status=200),
):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Do you need to escape the with environment?

Suggested change
payload_receive_booking['headers']['x-channex-token'] = 'MyTestWebhookSecret'
with (
self.assertLogs(level="WARNING"), # Is preventing any warning to be logged, we should replace this to ignore only the Unsafe Error
MockHTTPClient(url="https://staging.channex.io/api/v1/booking_revisions/074cd7f9-df51-4fc6-a8f4-7658573a235d/ack", return_json=booking_ack_answer, return_status=200),
MockHTTPClient(url="https://staging.channex.io/api/v1/bookings/e868f16e-b474-4b95-af12-5b114133e670", return_json=get_booking_answer, return_status=200),
):
payload_receive_booking['headers']['x-channex-token'] = 'MyTestWebhookSecret'

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Not really, but functional flow for both cases would be same. so writing it outside clearly expresses the intent

  1. Perform the "wrong token" test.
  2. Prepare the payload for the "correct token" test.
  3. Perform the "correct token" test.

what's your opinion on this?

Comment on lines +605 to +606
if env['ir.config_parameter'].get_str('booking_channex.x_channex_token') != token:
raise UserError("Failed to store the Channex webhook secret token.")

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

how could this happen?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

just for extra check but i think its not needed.

'x_remote_id': existing_webhook.get('attributes', {}).get('id')
})
else:
token = env['ir.attachment']._generate_access_token()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

isn't there a validity limit to this token? What happens then? How can the user easily change the token?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

No, for now no validity exist for token, user can change token only manually but not any separate functionality exist for update token on channex. so for now its become a permanent token 😢
we can discuss on this with @Pierre-savp and @frva-odoo

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@chga-odoo @frva-odoo
ha, we missed this non ARI aspect right?
on channex_webhook_secret change -> update webhook on channex side

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@chga-odoo
I discussed with SAVP about this and we agreed that it was not especially needed and we could keep it as a static value, so you can drop the automation to update on channex idea. We may add it later on if we feel this is needed but let's keep it simple for now

secure webhook adding a kind of security token to secure this communication.

Task: 6043950
@chga-odoo
chga-odoo force-pushed the saas-19.3-booking-channex-webhook-secure-chga branch from b1f1435 to 72cd550 Compare July 15, 2026 11: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.

5 participants