From d1b29d3aedf26624bad15507899ac013e5e70ec2 Mon Sep 17 00:00:00 2001 From: Dominic R Date: Fri, 26 Dec 2025 12:14:07 -0500 Subject: [PATCH 1/2] core: fix get_provider returning base Provider instead of subclass --- authentik/core/models.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/authentik/core/models.py b/authentik/core/models.py index 57c221bf9dd2..c04fb6bd1fd6 100644 --- a/authentik/core/models.py +++ b/authentik/core/models.py @@ -754,11 +754,12 @@ def get_provider(self) -> Provider | None: parent = getattr(parent, level) except AttributeError: break + # Skip if we didn't find a subclass (parent is still the base Provider) + if type(parent) is base_class: + continue if parent in candidates: continue - idx = subclass.count(LOOKUP_SEP) - if type(parent) is not base_class: - idx += 1 + idx = subclass.count(LOOKUP_SEP) + 1 candidates.insert(idx, parent) if not candidates: return None From cee3884c23defd50131fb5ab5ca47868b03d2b67 Mon Sep 17 00:00:00 2001 From: Dominic R Date: Fri, 26 Dec 2025 17:23:02 -0500 Subject: [PATCH 2/2] wip --- authentik/core/models.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/authentik/core/models.py b/authentik/core/models.py index c04fb6bd1fd6..d101dab62ffc 100644 --- a/authentik/core/models.py +++ b/authentik/core/models.py @@ -745,7 +745,8 @@ def get_provider(self) -> Provider | None: if not self.provider: return None - candidates = [] + best_candidate = None + best_depth = -1 base_class = Provider for subclass in base_class.objects.get_queryset()._get_subclasses_recurse(base_class): parent = self.provider @@ -757,13 +758,12 @@ def get_provider(self) -> Provider | None: # Skip if we didn't find a subclass (parent is still the base Provider) if type(parent) is base_class: continue - if parent in candidates: - continue - idx = subclass.count(LOOKUP_SEP) + 1 - candidates.insert(idx, parent) - if not candidates: - return None - return candidates[-1] + # Track the most specific (deepest) subclass + depth = subclass.count(LOOKUP_SEP) + if depth > best_depth: + best_depth = depth + best_candidate = parent + return best_candidate def backchannel_provider_for[T: Provider](self, provider_type: type[T], **kwargs) -> T | None: """Get Backchannel provider for a specific type"""