diff --git a/authentik/enterprise/providers/ssf/models.py b/authentik/enterprise/providers/ssf/models.py index 0718d61c2c53..7a18a148bf1f 100644 --- a/authentik/enterprise/providers/ssf/models.py +++ b/authentik/enterprise/providers/ssf/models.py @@ -127,7 +127,7 @@ def prepare_event_payload(self, type: EventTypes, event_data: dict, **kwargs) -> jti = uuid4() return { "uuid": jti, - "stream": self, + "stream_id": str(self.pk), "type": type, "payload": { "jti": jti.hex, diff --git a/authentik/enterprise/providers/ssf/tasks.py b/authentik/enterprise/providers/ssf/tasks.py index e38d5d12e75b..0ad95cdc9c23 100644 --- a/authentik/enterprise/providers/ssf/tasks.py +++ b/authentik/enterprise/providers/ssf/tasks.py @@ -24,7 +24,7 @@ def send_ssf_event( payload = [] if not stream_filter: stream_filter = {} - stream_filter["events_requested__in"] = [event_type] + stream_filter["events_requested__contains"] = [event_type] for stream in Stream.objects.filter(**stream_filter): event_data = stream.prepare_event_payload(event_type, data, **extra_data) payload.append((str(stream.uuid), event_data)) @@ -36,7 +36,7 @@ def _send_ssf_event(event_data: list[tuple[str, dict]]): tasks = [] for stream, data in event_data: event = StreamEvent.objects.create(**data) - tasks.append(send_single_ssf_event.si(str(stream.uuid), str(event.id))) + tasks.append(send_single_ssf_event.si(stream, str(event.uuid))) main_task = group(*tasks) main_task() diff --git a/authentik/enterprise/providers/ssf/tests/test_stream.py b/authentik/enterprise/providers/ssf/tests/test_stream.py index 19cbed0663a6..1398f4f59609 100644 --- a/authentik/enterprise/providers/ssf/tests/test_stream.py +++ b/authentik/enterprise/providers/ssf/tests/test_stream.py @@ -26,11 +26,11 @@ def test_stream_add(self): data={ "iss": "https://screw-fotos-bracelets-longitude.trycloudflare.com/.well-known/ssf-configuration/abm-ssf/5", "aud": [ - "https://federation.apple.com/feeds/business/caep/2034455812/871ada94-90f6-4cdc-9996-a9dd8d62ef14" + "https://app.authentik.company" ], "delivery": { "method": "https://schemas.openid.net/secevent/risc/delivery-method/push", - "endpoint_url": "https://federation.apple.com/feeds/business/caep/2034455812/871ada94-90f6-4cdc-9996-a9dd8d62ef14", + "endpoint_url": "https://app.authentik.company", }, "events_requested": [ "https://schemas.openid.net/secevent/caep/event-type/credential-change", diff --git a/authentik/enterprise/providers/ssf/views/stream.py b/authentik/enterprise/providers/ssf/views/stream.py index c3c3cfca34ec..23d35d2659e7 100644 --- a/authentik/enterprise/providers/ssf/views/stream.py +++ b/authentik/enterprise/providers/ssf/views/stream.py @@ -1,4 +1,5 @@ from django.urls import reverse +from rest_framework.exceptions import PermissionDenied from rest_framework.fields import CharField, ChoiceField, ListField, SerializerMethodField from rest_framework.request import Request from rest_framework.response import Response @@ -32,7 +33,6 @@ class StreamSerializer(ModelSerializer): aud = ListField(child=CharField()) def create(self, validated_data): - # todo: rbac check provider: SSFProvider = validated_data["provider"] iss = self.context["request"].build_absolute_uri( reverse( @@ -42,6 +42,8 @@ def create(self, validated_data): }, ) ) + # Ensure that streams always get SET verification events sent to them + validated_data["events_requested"].append(EventTypes.SET_VERIFICATION) return super().create( { "delivery_method": validated_data["delivery"]["method"], @@ -89,6 +91,10 @@ class StreamView(SSFView): def post(self, request: Request, *args, **kwargs) -> Response: stream = StreamSerializer(data=request.data, context={"request": request}) stream.is_valid(raise_exception=True) + if not request.user.has_perm("authentik_providers_ssf.add_stream", self.provider): + raise PermissionDenied( + "User does not have permission to create stream for this provider." + ) instance: Stream = stream.save(provider=self.provider) send_ssf_event( EventTypes.SET_VERIFICATION,