authentik icon indicating copy to clipboard operation
authentik copied to clipboard

SAML source in combination with OAuth provider loses redirect url

Open corvis opened this issue 1 year ago • 6 comments

Describe the bug When you have OAuth provider to authenticate your application AND saml source user can't complete the flow via SAML because at the very end they will be redirected to Authentik's user home instead of proper callback to complete OAuth on the integrated app side.

To Reproduce Steps to reproduce the behavior:

  1. Setup OAuth provider. Configure integration with your app (use standard flows). Make sure it works.
  2. Setup SAML source, make sure it works (use standard flows).
  3. Logout from Authentik!
  4. Go to your application and initiate login flow
  5. Once you are on Authentik login page select your SAML source. Follow instructions
  6. You will be redirected on a Authentik's user home after SAML flow successful completion so OAuth flow is incomplete and you are not logged into your app.

Expected behavior User is redirected to the app oauth callback url upon SAML flow completion.

Version and Deployment (please complete the following information):

  • authentik version: 2023.10.4
  • Deployment: tried docker-compose and helm

Additional context After a bit of debugging and comparing SAML source behavior to OAuth source I think I figured the root cause. OAuth relies on NEXT_ARG_NAME residing in the session (key SESSION_KEY_GET). However SAML has additional pre-authentication which starts a new flow and resets session SESSION_KEY_GET. Despite the correct URL still exists in a Plan context nobody reads it from there.

I fixed this for myself by adding a bit of logic to SAML's ACSView which reads redirect value from the plan context and sets it into the session[SESSION_KEY_GET]. Here is it:

@method_decorator(csrf_exempt, name="dispatch")
class ACSView(View):
    """AssertionConsumerService, consume assertion and log user in"""

    def post(self, request: HttpRequest, source_slug: str) -> HttpResponse:
        """Handles a POSTed SSO Assertion and logs the user in."""
        source: SAMLSource = get_object_or_404(SAMLSource, slug=source_slug)
        if not source.enabled:
            raise Http404
        processor = ResponseProcessor(source, request)
        try:
            processor.parse()
        except MissingSAMLResponse as exc:
            return bad_request_message(request, str(exc))
        except VerificationError as exc:
            return bad_request_message(request, str(exc))

        try:
            # PATCH START
            if SESSION_KEY_PLAN in request.session:
                plan_redirect = self.request.session[SESSION_KEY_PLAN].context.get(PLAN_CONTEXT_REDIRECT)
                if plan_redirect:
                    self.request.session[SESSION_KEY_GET] = {NEXT_ARG_NAME: plan_redirect}
            # PATCH END
            return processor.prepare_flow_manager().get_flow()
        except (UnsupportedNameIDFormat, ValueError) as exc:
            return bad_request_message(request, str(exc))

corvis avatar Dec 01 '23 11:12 corvis

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

This is actually still a relevant problem. Can someone take a look please?

corvis avatar Feb 01 '24 12:02 corvis

Having a similar issue - SAML Source (Shibboleth) backend directory, OAuth SP (Gitea). Works fine if already logged into Authentik, redirects to authentik_core:if-user after completing.

@corvis - has that patch been working well for you?

breagan1983 avatar Feb 29 '24 00:02 breagan1983

Yep, I still use it

corvis avatar Feb 29 '24 00:02 corvis

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

This is still a problem

corvis avatar Apr 29 '24 08:04 corvis