Repository: goauthentik/authentik

Issue:
When group added, SCIM throws error trying to append to Optional list field
**Describe the bug**
I've been using Authentik for SAML and Oauth/OIDC SSO for a few weeks now, with great success thus far. Today, I attempted to enable a SCIM Provider (targeting a Bitwarden self-hosted install that works great with Authentik OIDC for SSO). 

The initial setup seemed to work fine - existing Authentik users and groups were populated in Bitwarden.

I then added a group manually to Authentik, and the SCIM task started failing with the error below - my amateur reading is as follows, though I'm not super deeply read into Authentik source yet, or SCIM in general:

1. The scim_group variable is an instance of the class defined at https://github.com/chalk-ai/pydantic-scim/blob/330a13d5b5bc28a501123ed97498140963d45251/pydanticscim/group.py#L11 in the pydantic-scim library
3. The class defines the members property as Optional[List[GroupMember]]
4. The code at https://github.com/goauthentik/authentik/blob/4b0566c9d18b075f9dde0878687840ca95d8ef89/authentik/providers/scim/clients/group.py#L85 expects a members property of type List, rather than List|None, as seems possible given scim_group's class

Again, I'm not super familiar with this code or SCIM in general, so I don't have a great recommendation to fix - my first instinct is to start testing by throwing something like "scim_group.members = scim_group.members or []" at line ~81, though my second instinct is that this doesn't feel like the right place to test / set that.

**To Reproduce**
Steps to reproduce the behavior:
1. Set up a SCIM provider (in my case, with Bitwarden)
2. Observe your existing users and groups sync as expected
3. Manually add a new group to Authentik, and add a user to that group
5. Wait for or force a sync
6. See error below

My level of confidence that this is exhaustive is... low :) I am testing further to determine what other variables may be at play.

**Expected behavior**
I expect the new group to be added to the external system via SCIM.

**Logs**
<details>
    <summary>Stacktrace from authentik</summary>

```
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/celery/app/trace.py", line 451, in trace_task
    R = retval = fun(*args, **kwargs)
                 ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/celery/app/trace.py", line 734, in __protected_call__
    return self.run(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/authentik/providers/scim/tasks.py", line 117, in scim_sync_group
    client.write(group)
  File "/authentik/providers/scim/clients/group.py", line 26, in write
    scim_group = self.to_scim(obj)
                 ^^^^^^^^^^^^^^^^^
  File "/authentik/providers/scim/clients/group.py", line 85, in to_scim
    scim_group.members.append(
    ^^^^^^^^^^^^^^^^^^^^^^^^^
builtins.AttributeError: 'NoneType' object has no attribute 'append'
```
</details>


**Version and Deployment (please complete the following information):**
- authentik version: 2023.4.1
- Deployment: docker (uses separate deployments of redis/postgres)


Discussion:

Resolving patch:
diff --git a/authentik/lib/sentry.py b/authentik/lib/sentry.py
--- a/authentik/lib/sentry.py
+++ b/authentik/lib/sentry.py
@@ -15,6 +15,7 @@
 from ldap3.core.exceptions import LDAPException
 from redis.exceptions import ConnectionError as RedisConnectionError
 from redis.exceptions import RedisError, ResponseError
+from requests_mock.exceptions import NoMockAddress
 from rest_framework.exceptions import APIException
 from sentry_sdk import HttpTransport
 from sentry_sdk import init as sentry_sdk_init
@@ -140,6 +141,8 @@ def before_send(event: dict, hint: dict) -> Optional[dict]:
         Http404,
         # AsyncIO
         CancelledError,
+        # Requests
+        NoMockAddress,
     )
     exc_value = None
     if "exc_info" in hint:
diff --git a/authentik/providers/scim/clients/group.py b/authentik/providers/scim/clients/group.py
--- a/authentik/providers/scim/clients/group.py
+++ b/authentik/providers/scim/clients/group.py
@@ -81,12 +81,15 @@ def to_scim(self, obj: Group) -> SCIMGroupSchema:
 
         users = list(obj.users.order_by("id").values_list("id", flat=True))
         connections = SCIMUser.objects.filter(provider=self.provider, user__pk__in=users)
+        members = []
         for user in connections:
-            scim_group.members.append(
+            members.append(
                 GroupMember(
                     value=user.id,
                 )
             )
+        if members:
+            scim_group.members = members
         return scim_group
 
     def _create(self, group: Group):


Test patch: