diff --git a/authentik/events/migrations/0002_alter_notificationtransport_mode.py b/authentik/events/migrations/0002_alter_notificationtransport_mode.py
index 5807b42e4..5faa5c457 100644
--- a/authentik/events/migrations/0002_alter_notificationtransport_mode.py
+++ b/authentik/events/migrations/0002_alter_notificationtransport_mode.py
@@ -22,4 +22,8 @@ class Migration(migrations.Migration):
default="local",
),
),
+ migrations.AlterModelOptions(
+ name="notificationwebhookmapping",
+ options={"verbose_name": "Webhook Mapping", "verbose_name_plural": "Webhook Mappings"},
+ ),
]
diff --git a/authentik/events/models.py b/authentik/events/models.py
index 629e9ba3a..f497afaed 100644
--- a/authentik/events/models.py
+++ b/authentik/events/models.py
@@ -560,7 +560,7 @@ class NotificationRule(SerializerModel, PolicyBindingModel):
class NotificationWebhookMapping(PropertyMapping):
- """Modify the schema and layout of the webhook being sent"""
+ """Modify the payload of outgoing webhook requests"""
@property
def component(self) -> str:
@@ -573,9 +573,9 @@ class NotificationWebhookMapping(PropertyMapping):
return NotificationWebhookMappingSerializer
def __str__(self):
- return f"Notification Webhook Mapping {self.name}"
+ return f"Webhook Mapping {self.name}"
class Meta:
- verbose_name = _("Notification Webhook Mapping")
- verbose_name_plural = _("Notification Webhook Mappings")
+ verbose_name = _("Webhook Mapping")
+ verbose_name_plural = _("Webhook Mappings")
diff --git a/authentik/providers/saml/models.py b/authentik/providers/saml/models.py
index 660bc9afe..172ff956c 100644
--- a/authentik/providers/saml/models.py
+++ b/authentik/providers/saml/models.py
@@ -182,7 +182,7 @@ class SAMLProvider(Provider):
class SAMLPropertyMapping(PropertyMapping):
- """Map User/Group attribute to SAML Attribute, which can be used by the Service Provider."""
+ """Map User/Group attribute to SAML Attribute, which can be used by the Service Provider"""
saml_name = models.TextField(verbose_name="SAML Name")
friendly_name = models.TextField(default=None, blank=True, null=True)
diff --git a/authentik/stages/authenticator_sms/api.py b/authentik/stages/authenticator_sms/api.py
index 6e632480d..cf5d39c89 100644
--- a/authentik/stages/authenticator_sms/api.py
+++ b/authentik/stages/authenticator_sms/api.py
@@ -27,6 +27,7 @@ class AuthenticatorSMSStageSerializer(StageSerializer):
"auth_password",
"auth_type",
"verify_only",
+ "mapping",
]
diff --git a/authentik/stages/authenticator_sms/migrations/0005_authenticatorsmsstage_mapping.py b/authentik/stages/authenticator_sms/migrations/0005_authenticatorsmsstage_mapping.py
new file mode 100644
index 000000000..bf9f8d822
--- /dev/null
+++ b/authentik/stages/authenticator_sms/migrations/0005_authenticatorsmsstage_mapping.py
@@ -0,0 +1,26 @@
+# Generated by Django 4.1.2 on 2022-10-13 20:19
+
+import django.db.models.deletion
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ("authentik_events", "0002_alter_notificationtransport_mode"),
+ ("authentik_stages_authenticator_sms", "0004_authenticatorsmsstage_verify_only_and_more"),
+ ]
+
+ operations = [
+ migrations.AddField(
+ model_name="authenticatorsmsstage",
+ name="mapping",
+ field=models.ForeignKey(
+ default=None,
+ null=True,
+ on_delete=django.db.models.deletion.SET_NULL,
+ to="authentik_events.notificationwebhookmapping",
+ help_text="Optionally modify the payload being sent to custom providers.",
+ ),
+ ),
+ ]
diff --git a/authentik/stages/authenticator_sms/models.py b/authentik/stages/authenticator_sms/models.py
index 4ad2e2a5f..70017b96f 100644
--- a/authentik/stages/authenticator_sms/models.py
+++ b/authentik/stages/authenticator_sms/models.py
@@ -15,7 +15,8 @@ from twilio.base.exceptions import TwilioRestException
from twilio.rest import Client
from authentik.core.types import UserSettingSerializer
-from authentik.events.models import Event, EventAction
+from authentik.events.models import Event, EventAction, NotificationWebhookMapping
+from authentik.events.utils import sanitize_item
from authentik.flows.models import ConfigurableStage, Stage
from authentik.lib.models import SerializerModel
from authentik.lib.utils.errors import exception_to_string
@@ -59,6 +60,14 @@ class AuthenticatorSMSStage(ConfigurableStage, Stage):
),
)
+ mapping = models.ForeignKey(
+ NotificationWebhookMapping,
+ null=True,
+ default=None,
+ on_delete=models.SET_NULL,
+ help_text=_("Optionally modify the payload being sent to custom providers."),
+ )
+
def send(self, token: str, device: "SMSDevice"):
"""Send message via selected provider"""
if self.provider == SMSProviders.TWILIO:
@@ -82,24 +91,33 @@ class AuthenticatorSMSStage(ConfigurableStage, Stage):
def send_generic(self, token: str, device: "SMSDevice"):
"""Send SMS via outside API"""
-
- data = {
+ payload = {
"From": self.from_number,
"To": device.phone_number,
"Body": token,
}
+ if self.mapping:
+ payload = sanitize_item(
+ self.mapping.evaluate(
+ user=device.user,
+ request=None,
+ device=device,
+ token=token,
+ stage=self,
+ )
+ )
+
if self.auth_type == SMSAuthTypes.BEARER:
response = get_http_session().post(
f"{self.account_sid}",
- json=data,
+ json=payload,
headers={"Authorization": f"Bearer {self.auth}"},
)
-
elif self.auth_type == SMSAuthTypes.BASIC:
response = get_http_session().post(
f"{self.account_sid}",
- json=data,
+ json=payload,
auth=(self.auth, self.auth_password),
)
else:
diff --git a/schema.yml b/schema.yml
index 89127066f..1fe621123 100644
--- a/schema.yml
+++ b/schema.yml
@@ -13101,7 +13101,7 @@ paths:
schema:
type: string
format: uuid
- description: A UUID string identifying this Notification Webhook Mapping.
+ description: A UUID string identifying this Webhook Mapping.
required: true
tags:
- propertymappings
@@ -13135,7 +13135,7 @@ paths:
schema:
type: string
format: uuid
- description: A UUID string identifying this Notification Webhook Mapping.
+ description: A UUID string identifying this Webhook Mapping.
required: true
tags:
- propertymappings
@@ -13175,7 +13175,7 @@ paths:
schema:
type: string
format: uuid
- description: A UUID string identifying this Notification Webhook Mapping.
+ description: A UUID string identifying this Webhook Mapping.
required: true
tags:
- propertymappings
@@ -13214,7 +13214,7 @@ paths:
schema:
type: string
format: uuid
- description: A UUID string identifying this Notification Webhook Mapping.
+ description: A UUID string identifying this Webhook Mapping.
required: true
tags:
- propertymappings
@@ -13245,7 +13245,7 @@ paths:
schema:
type: string
format: uuid
- description: A UUID string identifying this Notification Webhook Mapping.
+ description: A UUID string identifying this Webhook Mapping.
required: true
tags:
- propertymappings
@@ -18794,6 +18794,11 @@ paths:
name: from_number
schema:
type: string
+ - in: query
+ name: mapping
+ schema:
+ type: string
+ format: uuid
- in: query
name: name
schema:
@@ -25185,6 +25190,11 @@ components:
description: When enabled, the Phone number is only used during enrollment
to verify the users authenticity. Only a hash of the phone number is saved
to ensure it is not re-used in the future.
+ mapping:
+ type: string
+ format: uuid
+ nullable: true
+ description: Optionally modify the payload being sent to custom providers.
required:
- account_sid
- auth
@@ -25233,6 +25243,11 @@ components:
description: When enabled, the Phone number is only used during enrollment
to verify the users authenticity. Only a hash of the phone number is saved
to ensure it is not re-used in the future.
+ mapping:
+ type: string
+ format: uuid
+ nullable: true
+ description: Optionally modify the payload being sent to custom providers.
required:
- account_sid
- auth
@@ -32702,6 +32717,11 @@ components:
description: When enabled, the Phone number is only used during enrollment
to verify the users authenticity. Only a hash of the phone number is saved
to ensure it is not re-used in the future.
+ mapping:
+ type: string
+ format: uuid
+ nullable: true
+ description: Optionally modify the payload being sent to custom providers.
PatchedAuthenticatorStaticStageRequest:
type: object
description: AuthenticatorStaticStage Serializer
diff --git a/web/src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts b/web/src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
index 0ad8a3918..8ae544604 100644
--- a/web/src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
+++ b/web/src/admin/stages/authenticator_sms/AuthenticatorSMSStageForm.ts
@@ -16,6 +16,7 @@ import {
AuthenticatorSMSStage,
FlowsApi,
FlowsInstancesListDesignationEnum,
+ PropertymappingsApi,
ProviderEnum,
StagesApi,
} from "@goauthentik/api";
@@ -91,7 +92,8 @@ export class AuthenticatorSMSStageForm extends ModelForm
+ ${t`Modify the payload sent to the custom provider.`} +
+