authentik.enterprise.providers.microsoft_entra.models
Microsoft Entra sync provider
1"""Microsoft Entra sync provider""" 2 3from typing import Any, Self 4from uuid import uuid4 5 6from azure.identity.aio import ClientSecretCredential 7from django.db import models 8from django.db.models import QuerySet 9from django.templatetags.static import static 10from django.utils.translation import gettext_lazy as _ 11from dramatiq.actor import Actor 12from rest_framework.serializers import Serializer 13 14from authentik.core.models import ( 15 BackchannelProvider, 16 Group, 17 PropertyMapping, 18 User, 19 UserTypes, 20) 21from authentik.lib.models import InternallyManagedMixin, SerializerModel 22from authentik.lib.sync.outgoing.base import BaseOutgoingSyncClient 23from authentik.lib.sync.outgoing.models import OutgoingSyncDeleteAction, OutgoingSyncProvider 24 25 26class MicrosoftEntraProviderUser(InternallyManagedMixin, SerializerModel): 27 """Mapping of a user and provider to a Microsoft user ID""" 28 29 id = models.UUIDField(primary_key=True, editable=False, default=uuid4) 30 microsoft_id = models.TextField() 31 user = models.ForeignKey(User, on_delete=models.CASCADE) 32 provider = models.ForeignKey("MicrosoftEntraProvider", on_delete=models.CASCADE) 33 attributes = models.JSONField(default=dict) 34 35 @property 36 def serializer(self) -> type[Serializer]: 37 from authentik.enterprise.providers.microsoft_entra.api.users import ( 38 MicrosoftEntraProviderUserSerializer, 39 ) 40 41 return MicrosoftEntraProviderUserSerializer 42 43 class Meta: 44 verbose_name = _("Microsoft Entra Provider User") 45 verbose_name_plural = _("Microsoft Entra Provider User") 46 unique_together = (("microsoft_id", "user", "provider"),) 47 48 def __str__(self) -> str: 49 return f"Microsoft Entra Provider User {self.user_id} to {self.provider_id}" 50 51 52class MicrosoftEntraProviderGroup(InternallyManagedMixin, SerializerModel): 53 """Mapping of a group and provider to a Microsoft group ID""" 54 55 id = models.UUIDField(primary_key=True, editable=False, default=uuid4) 56 microsoft_id = models.TextField() 57 group = models.ForeignKey(Group, on_delete=models.CASCADE) 58 provider = models.ForeignKey("MicrosoftEntraProvider", on_delete=models.CASCADE) 59 attributes = models.JSONField(default=dict) 60 61 @property 62 def serializer(self) -> type[Serializer]: 63 from authentik.enterprise.providers.microsoft_entra.api.groups import ( 64 MicrosoftEntraProviderGroupSerializer, 65 ) 66 67 return MicrosoftEntraProviderGroupSerializer 68 69 class Meta: 70 verbose_name = _("Microsoft Entra Provider Group") 71 verbose_name_plural = _("Microsoft Entra Provider Groups") 72 unique_together = (("microsoft_id", "group", "provider"),) 73 74 def __str__(self) -> str: 75 return f"Microsoft Entra Provider Group {self.group_id} to {self.provider_id}" 76 77 78class MicrosoftEntraProvider(OutgoingSyncProvider, BackchannelProvider): 79 """Sync users from authentik into Microsoft Entra.""" 80 81 client_id = models.TextField() 82 client_secret = models.TextField() 83 tenant_id = models.TextField() 84 85 exclude_users_service_account = models.BooleanField(default=False) 86 user_delete_action = models.TextField( 87 choices=OutgoingSyncDeleteAction.choices, default=OutgoingSyncDeleteAction.DELETE 88 ) 89 group_delete_action = models.TextField( 90 choices=OutgoingSyncDeleteAction.choices, default=OutgoingSyncDeleteAction.DELETE 91 ) 92 filter_group = models.ForeignKey( 93 "authentik_core.group", on_delete=models.SET_DEFAULT, default=None, null=True 94 ) 95 96 property_mappings_group = models.ManyToManyField( 97 PropertyMapping, 98 default=None, 99 blank=True, 100 help_text=_("Property mappings used for group creation/updating."), 101 ) 102 103 @property 104 def sync_actor(self) -> Actor: 105 from authentik.enterprise.providers.microsoft_entra.tasks import microsoft_entra_sync 106 107 return microsoft_entra_sync 108 109 def client_for_model( 110 self, 111 model: type[User | Group | MicrosoftEntraProviderUser | MicrosoftEntraProviderGroup], 112 ) -> BaseOutgoingSyncClient[User | Group, Any, Any, Self]: 113 if issubclass(model, User | MicrosoftEntraProviderUser): 114 from authentik.enterprise.providers.microsoft_entra.clients.users import ( 115 MicrosoftEntraUserClient, 116 ) 117 118 return MicrosoftEntraUserClient(self) 119 if issubclass(model, Group | MicrosoftEntraProviderGroup): 120 from authentik.enterprise.providers.microsoft_entra.clients.groups import ( 121 MicrosoftEntraGroupClient, 122 ) 123 124 return MicrosoftEntraGroupClient(self) 125 raise ValueError(f"Invalid model {model}") 126 127 def get_object_qs(self, type: type[User | Group], **kwargs) -> QuerySet[User | Group]: 128 if type == User: 129 # Get queryset of all users with consistent ordering 130 # according to the provider's settings 131 base = User.objects.all().exclude_anonymous().filter(**kwargs) 132 if self.exclude_users_service_account: 133 base = base.exclude(type=UserTypes.SERVICE_ACCOUNT).exclude( 134 type=UserTypes.INTERNAL_SERVICE_ACCOUNT 135 ) 136 if self.filter_group: 137 base = base.filter(groups__in=[self.filter_group]) 138 return base.order_by("pk") 139 if type == Group: 140 # Get queryset of all groups with consistent ordering 141 return Group.objects.all().filter(**kwargs).order_by("pk") 142 raise ValueError(f"Invalid type {type}") 143 144 @classmethod 145 def get_object_mappings(cls, obj: User | Group) -> list[tuple[str, str]]: 146 if isinstance(obj, User): 147 return list( 148 obj.microsoftentraprovideruser_set.values_list("provider__pk", "microsoft_id") 149 ) 150 if isinstance(obj, Group): 151 return list( 152 obj.microsoftentraprovidergroup_set.values_list("provider__pk", "microsoft_id") 153 ) 154 raise ValueError(f"Invalid type {type(obj)}") 155 156 def microsoft_credentials(self): 157 return { 158 "credentials": ClientSecretCredential( 159 self.tenant_id, self.client_id, self.client_secret 160 ) 161 } 162 163 @property 164 def icon_url(self) -> str | None: 165 return static("authentik/sources/azuread.svg") 166 167 @property 168 def component(self) -> str: 169 return "ak-provider-microsoft-entra-form" 170 171 @property 172 def serializer(self) -> type[Serializer]: 173 from authentik.enterprise.providers.microsoft_entra.api.providers import ( 174 MicrosoftEntraProviderSerializer, 175 ) 176 177 return MicrosoftEntraProviderSerializer 178 179 def __str__(self): 180 return f"Microsoft Entra Provider {self.name}" 181 182 class Meta: 183 verbose_name = _("Microsoft Entra Provider") 184 verbose_name_plural = _("Microsoft Entra Providers") 185 186 187class MicrosoftEntraProviderMapping(PropertyMapping): 188 """Map authentik data to outgoing Microsoft requests""" 189 190 @property 191 def component(self) -> str: 192 return "ak-property-mapping-provider-microsoft-entra-form" 193 194 @property 195 def serializer(self) -> type[Serializer]: 196 from authentik.enterprise.providers.microsoft_entra.api.property_mappings import ( 197 MicrosoftEntraProviderMappingSerializer, 198 ) 199 200 return MicrosoftEntraProviderMappingSerializer 201 202 def __str__(self): 203 return f"Microsoft Entra Provider Mapping {self.name}" 204 205 class Meta: 206 verbose_name = _("Microsoft Entra Provider Mapping") 207 verbose_name_plural = _("Microsoft Entra Provider Mappings")
27class MicrosoftEntraProviderUser(InternallyManagedMixin, SerializerModel): 28 """Mapping of a user and provider to a Microsoft user ID""" 29 30 id = models.UUIDField(primary_key=True, editable=False, default=uuid4) 31 microsoft_id = models.TextField() 32 user = models.ForeignKey(User, on_delete=models.CASCADE) 33 provider = models.ForeignKey("MicrosoftEntraProvider", on_delete=models.CASCADE) 34 attributes = models.JSONField(default=dict) 35 36 @property 37 def serializer(self) -> type[Serializer]: 38 from authentik.enterprise.providers.microsoft_entra.api.users import ( 39 MicrosoftEntraProviderUserSerializer, 40 ) 41 42 return MicrosoftEntraProviderUserSerializer 43 44 class Meta: 45 verbose_name = _("Microsoft Entra Provider User") 46 verbose_name_plural = _("Microsoft Entra Provider User") 47 unique_together = (("microsoft_id", "user", "provider"),) 48 49 def __str__(self) -> str: 50 return f"Microsoft Entra Provider User {self.user_id} to {self.provider_id}"
Mapping of a user and provider to a Microsoft user ID
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Child.parent is a ForwardManyToOneDescriptor instance.
Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Child.parent is a ForwardManyToOneDescriptor instance.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
36 @property 37 def serializer(self) -> type[Serializer]: 38 from authentik.enterprise.providers.microsoft_entra.api.users import ( 39 MicrosoftEntraProviderUserSerializer, 40 ) 41 42 return MicrosoftEntraProviderUserSerializer
Get serializer for this model
Inherited Members
The requested object does not exist
The query returned multiple objects when only one was expected.
53class MicrosoftEntraProviderGroup(InternallyManagedMixin, SerializerModel): 54 """Mapping of a group and provider to a Microsoft group ID""" 55 56 id = models.UUIDField(primary_key=True, editable=False, default=uuid4) 57 microsoft_id = models.TextField() 58 group = models.ForeignKey(Group, on_delete=models.CASCADE) 59 provider = models.ForeignKey("MicrosoftEntraProvider", on_delete=models.CASCADE) 60 attributes = models.JSONField(default=dict) 61 62 @property 63 def serializer(self) -> type[Serializer]: 64 from authentik.enterprise.providers.microsoft_entra.api.groups import ( 65 MicrosoftEntraProviderGroupSerializer, 66 ) 67 68 return MicrosoftEntraProviderGroupSerializer 69 70 class Meta: 71 verbose_name = _("Microsoft Entra Provider Group") 72 verbose_name_plural = _("Microsoft Entra Provider Groups") 73 unique_together = (("microsoft_id", "group", "provider"),) 74 75 def __str__(self) -> str: 76 return f"Microsoft Entra Provider Group {self.group_id} to {self.provider_id}"
Mapping of a group and provider to a Microsoft group ID
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Child.parent is a ForwardManyToOneDescriptor instance.
Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Child.parent is a ForwardManyToOneDescriptor instance.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
62 @property 63 def serializer(self) -> type[Serializer]: 64 from authentik.enterprise.providers.microsoft_entra.api.groups import ( 65 MicrosoftEntraProviderGroupSerializer, 66 ) 67 68 return MicrosoftEntraProviderGroupSerializer
Get serializer for this model
Inherited Members
The requested object does not exist
The query returned multiple objects when only one was expected.
79class MicrosoftEntraProvider(OutgoingSyncProvider, BackchannelProvider): 80 """Sync users from authentik into Microsoft Entra.""" 81 82 client_id = models.TextField() 83 client_secret = models.TextField() 84 tenant_id = models.TextField() 85 86 exclude_users_service_account = models.BooleanField(default=False) 87 user_delete_action = models.TextField( 88 choices=OutgoingSyncDeleteAction.choices, default=OutgoingSyncDeleteAction.DELETE 89 ) 90 group_delete_action = models.TextField( 91 choices=OutgoingSyncDeleteAction.choices, default=OutgoingSyncDeleteAction.DELETE 92 ) 93 filter_group = models.ForeignKey( 94 "authentik_core.group", on_delete=models.SET_DEFAULT, default=None, null=True 95 ) 96 97 property_mappings_group = models.ManyToManyField( 98 PropertyMapping, 99 default=None, 100 blank=True, 101 help_text=_("Property mappings used for group creation/updating."), 102 ) 103 104 @property 105 def sync_actor(self) -> Actor: 106 from authentik.enterprise.providers.microsoft_entra.tasks import microsoft_entra_sync 107 108 return microsoft_entra_sync 109 110 def client_for_model( 111 self, 112 model: type[User | Group | MicrosoftEntraProviderUser | MicrosoftEntraProviderGroup], 113 ) -> BaseOutgoingSyncClient[User | Group, Any, Any, Self]: 114 if issubclass(model, User | MicrosoftEntraProviderUser): 115 from authentik.enterprise.providers.microsoft_entra.clients.users import ( 116 MicrosoftEntraUserClient, 117 ) 118 119 return MicrosoftEntraUserClient(self) 120 if issubclass(model, Group | MicrosoftEntraProviderGroup): 121 from authentik.enterprise.providers.microsoft_entra.clients.groups import ( 122 MicrosoftEntraGroupClient, 123 ) 124 125 return MicrosoftEntraGroupClient(self) 126 raise ValueError(f"Invalid model {model}") 127 128 def get_object_qs(self, type: type[User | Group], **kwargs) -> QuerySet[User | Group]: 129 if type == User: 130 # Get queryset of all users with consistent ordering 131 # according to the provider's settings 132 base = User.objects.all().exclude_anonymous().filter(**kwargs) 133 if self.exclude_users_service_account: 134 base = base.exclude(type=UserTypes.SERVICE_ACCOUNT).exclude( 135 type=UserTypes.INTERNAL_SERVICE_ACCOUNT 136 ) 137 if self.filter_group: 138 base = base.filter(groups__in=[self.filter_group]) 139 return base.order_by("pk") 140 if type == Group: 141 # Get queryset of all groups with consistent ordering 142 return Group.objects.all().filter(**kwargs).order_by("pk") 143 raise ValueError(f"Invalid type {type}") 144 145 @classmethod 146 def get_object_mappings(cls, obj: User | Group) -> list[tuple[str, str]]: 147 if isinstance(obj, User): 148 return list( 149 obj.microsoftentraprovideruser_set.values_list("provider__pk", "microsoft_id") 150 ) 151 if isinstance(obj, Group): 152 return list( 153 obj.microsoftentraprovidergroup_set.values_list("provider__pk", "microsoft_id") 154 ) 155 raise ValueError(f"Invalid type {type(obj)}") 156 157 def microsoft_credentials(self): 158 return { 159 "credentials": ClientSecretCredential( 160 self.tenant_id, self.client_id, self.client_secret 161 ) 162 } 163 164 @property 165 def icon_url(self) -> str | None: 166 return static("authentik/sources/azuread.svg") 167 168 @property 169 def component(self) -> str: 170 return "ak-provider-microsoft-entra-form" 171 172 @property 173 def serializer(self) -> type[Serializer]: 174 from authentik.enterprise.providers.microsoft_entra.api.providers import ( 175 MicrosoftEntraProviderSerializer, 176 ) 177 178 return MicrosoftEntraProviderSerializer 179 180 def __str__(self): 181 return f"Microsoft Entra Provider {self.name}" 182 183 class Meta: 184 verbose_name = _("Microsoft Entra Provider") 185 verbose_name_plural = _("Microsoft Entra Providers")
Sync users from authentik into Microsoft Entra.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Accessor to the related object on the forward side of a many-to-one or one-to-one (via ForwardOneToOneDescriptor subclass) relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Child.parent is a ForwardManyToOneDescriptor instance.
Accessor to the related objects manager on the forward and reverse sides of a many-to-many relation.
In the example::
class Pizza(Model):
toppings = ManyToManyField(Topping, related_name='pizzas')
Pizza.toppings and Topping.pizzas are ManyToManyDescriptor
instances.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
110 def client_for_model( 111 self, 112 model: type[User | Group | MicrosoftEntraProviderUser | MicrosoftEntraProviderGroup], 113 ) -> BaseOutgoingSyncClient[User | Group, Any, Any, Self]: 114 if issubclass(model, User | MicrosoftEntraProviderUser): 115 from authentik.enterprise.providers.microsoft_entra.clients.users import ( 116 MicrosoftEntraUserClient, 117 ) 118 119 return MicrosoftEntraUserClient(self) 120 if issubclass(model, Group | MicrosoftEntraProviderGroup): 121 from authentik.enterprise.providers.microsoft_entra.clients.groups import ( 122 MicrosoftEntraGroupClient, 123 ) 124 125 return MicrosoftEntraGroupClient(self) 126 raise ValueError(f"Invalid model {model}")
128 def get_object_qs(self, type: type[User | Group], **kwargs) -> QuerySet[User | Group]: 129 if type == User: 130 # Get queryset of all users with consistent ordering 131 # according to the provider's settings 132 base = User.objects.all().exclude_anonymous().filter(**kwargs) 133 if self.exclude_users_service_account: 134 base = base.exclude(type=UserTypes.SERVICE_ACCOUNT).exclude( 135 type=UserTypes.INTERNAL_SERVICE_ACCOUNT 136 ) 137 if self.filter_group: 138 base = base.filter(groups__in=[self.filter_group]) 139 return base.order_by("pk") 140 if type == Group: 141 # Get queryset of all groups with consistent ordering 142 return Group.objects.all().filter(**kwargs).order_by("pk") 143 raise ValueError(f"Invalid type {type}")
145 @classmethod 146 def get_object_mappings(cls, obj: User | Group) -> list[tuple[str, str]]: 147 if isinstance(obj, User): 148 return list( 149 obj.microsoftentraprovideruser_set.values_list("provider__pk", "microsoft_id") 150 ) 151 if isinstance(obj, Group): 152 return list( 153 obj.microsoftentraprovidergroup_set.values_list("provider__pk", "microsoft_id") 154 ) 155 raise ValueError(f"Invalid type {type(obj)}")
Get a list of mapping between User/Group and ProviderUser/Group: [("provider_pk", "obj_pk")]
172 @property 173 def serializer(self) -> type[Serializer]: 174 from authentik.enterprise.providers.microsoft_entra.api.providers import ( 175 MicrosoftEntraProviderSerializer, 176 ) 177 178 return MicrosoftEntraProviderSerializer
Get serializer for this model
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
A wrapper for a deferred-loading field. When the value is read from this object the first time, the query is executed.
Accessor to the related objects manager on the one-to-many relation created by GenericRelation.
In the example::
class Post(Model):
comments = GenericRelation(Comment)
post.comments is a ReverseGenericManyToOneDescriptor instance.
Accessor to the related objects manager on the one-to-many relation created by GenericRelation.
In the example::
class Post(Model):
comments = GenericRelation(Comment)
post.comments is a ReverseGenericManyToOneDescriptor instance.
Method descriptor with partial application of the given arguments and keywords.
Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.
Method descriptor with partial application of the given arguments and keywords.
Supports wrapping existing descriptors and handles non-descriptor callables as instance methods.
Accessor to the related object on the forward side of a one-to-one relation.
In the example::
class Restaurant(Model):
place = OneToOneField(Place, related_name='restaurant')
Restaurant.place is a ForwardOneToOneDescriptor instance.
Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Parent.children is a ReverseManyToOneDescriptor instance.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Accessor to the related objects manager on the reverse side of a many-to-one relation.
In the example::
class Child(Model):
parent = ForeignKey(Parent, related_name='children')
Parent.children is a ReverseManyToOneDescriptor instance.
Most of the implementation is delegated to a dynamically defined manager
class built by create_forward_many_to_many_manager() defined below.
Inherited Members
- authentik.lib.sync.outgoing.models.OutgoingSyncProvider
- Meta
- get_paginator
- get_object_sync_time_limit_ms
- get_sync_time_limit_ms
- sync_lock
- sync_dispatch
- schedule_specs
- authentik.core.models.Provider
- name
- authentication_flow
- invalidation_flow
- property_mappings
- backchannel_application
- is_backchannel
- objects
- launch_url
- authentication_flow_id
- invalidation_flow_id
- backchannel_application_id
- id
- application
- outpost_set
- oauth2provider
- ldapprovider
- racprovider
- radiusprovider
- samlprovider
- scimprovider
- googleworkspaceprovider
- microsoftentraprovider
- ssfprovider
The requested object does not exist
The query returned multiple objects when only one was expected.
188class MicrosoftEntraProviderMapping(PropertyMapping): 189 """Map authentik data to outgoing Microsoft requests""" 190 191 @property 192 def component(self) -> str: 193 return "ak-property-mapping-provider-microsoft-entra-form" 194 195 @property 196 def serializer(self) -> type[Serializer]: 197 from authentik.enterprise.providers.microsoft_entra.api.property_mappings import ( 198 MicrosoftEntraProviderMappingSerializer, 199 ) 200 201 return MicrosoftEntraProviderMappingSerializer 202 203 def __str__(self): 204 return f"Microsoft Entra Provider Mapping {self.name}" 205 206 class Meta: 207 verbose_name = _("Microsoft Entra Provider Mapping") 208 verbose_name_plural = _("Microsoft Entra Provider Mappings")
Map authentik data to outgoing Microsoft requests
191 @property 192 def component(self) -> str: 193 return "ak-property-mapping-provider-microsoft-entra-form"
Return component used to edit this object
195 @property 196 def serializer(self) -> type[Serializer]: 197 from authentik.enterprise.providers.microsoft_entra.api.property_mappings import ( 198 MicrosoftEntraProviderMappingSerializer, 199 ) 200 201 return MicrosoftEntraProviderMappingSerializer
Get serializer for this model
Accessor to the related object on the forward side of a one-to-one relation.
In the example::
class Restaurant(Model):
place = OneToOneField(Place, related_name='restaurant')
Restaurant.place is a ForwardOneToOneDescriptor instance.
Inherited Members
- authentik.core.models.PropertyMapping
- pm_uuid
- name
- expression
- objects
- evaluate
- managed
- provider_set
- source_userpropertymappings_set
- source_grouppropertymappings_set
- notificationwebhookmapping
- oauthsourcepropertymapping
- scopemapping
- endpoint_set
- racpropertymapping
- radiusproviderpropertymapping
- samlsourcepropertymapping
- samlpropertymapping
- scimprovider_set
- scimmapping
- kerberossourcepropertymapping
- ldapsourcepropertymapping
- plexsourcepropertymapping
- scimsourcepropertymapping
- telegramsourcepropertymapping
- googleworkspaceprovider_set
- googleworkspaceprovidermapping
- microsoftentraprovider_set
- microsoftentraprovidermapping
The requested object does not exist
The query returned multiple objects when only one was expected.