diff --git a/InvenTree/common/api.py b/InvenTree/common/api.py index ea363fa394..e307d5485f 100644 --- a/InvenTree/common/api.py +++ b/InvenTree/common/api.py @@ -6,6 +6,9 @@ Provides a JSON API for common components. from __future__ import unicode_literals import json +import hmac +import hashlib +import base64 from secrets import compare_digest from django.utils.decorators import method_decorator @@ -75,6 +78,7 @@ class WebhookView(CsrfExemptMixin, APIView): # To be overridden def init(self, request, *args, **kwargs): self.token = '' + self.secret = '' self.verify = self.VERIFICATION_METHOD def get_webhook(self, endpoint): @@ -90,6 +94,10 @@ class WebhookView(CsrfExemptMixin, APIView): self.token = self.webhook.token self.verify = VerificationMethod.TOKEN # TODO make a object-setting + if self.webhook.secret: + self.secret = self.webhook.secret + self.verify = VerificationMethod.HMAC + # TODO make a object-setting return True def validate_token(self, payload, headers): @@ -106,6 +114,10 @@ class WebhookView(CsrfExemptMixin, APIView): # hmac token elif self.verify == VerificationMethod.HMAC: + digest = hmac.new(self.secret, payload.encode('utf-8'), hashlib.sha256).digest() + computed_hmac = base64.b64encode(digest) + if not hmac.compare_digest(computed_hmac, token.encode('utf-8')): + raise PermissionDenied(self.MESSAGE_TOKEN_ERROR) return True diff --git a/InvenTree/common/migrations/0013_auto_20210912_1443.py b/InvenTree/common/migrations/0013_auto_20210912_1443.py new file mode 100644 index 0000000000..f9c05fe05f --- /dev/null +++ b/InvenTree/common/migrations/0013_auto_20210912_1443.py @@ -0,0 +1,18 @@ +# Generated by Django 3.2.4 on 2021-09-12 14:43 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('common', '0012_webhookendpoint'), + ] + + operations = [ + migrations.AddField( + model_name='webhookendpoint', + name='secret', + field=models.CharField(blank=True, help_text='Shared secret for HMAC', max_length=255, null=True, verbose_name='Secret'), + ), + ] diff --git a/InvenTree/common/models.py b/InvenTree/common/models.py index df64cd5cbc..ca13e84357 100644 --- a/InvenTree/common/models.py +++ b/InvenTree/common/models.py @@ -1177,6 +1177,7 @@ class WebhookEndpoint(models.Model): active: Is this webhook active?, user: User associated with webhook, token: Token for sending a webhook, + secret: Shared secret for HMAC verification, """ endpoint_id = models.CharField( @@ -1215,3 +1216,10 @@ class WebhookEndpoint(models.Model): help_text=_('Token for access'), default=uuid.uuid4, ) + + secret = models.CharField( + max_length=255, + blank=True, null=True, + verbose_name=_('Secret'), + help_text=_('Shared secret for HMAC'), + )