goauthentik / goauthentik/authentik

A race condition in authentication flow causes occasional `Flow does not apply to current user.`

Open
#11,594 7 comments 2 reactions 0 assignees Claimed by @GirlBossRush View on GitHub
bug status/reviewing
Dominant language
Python
Stars
25.6k
Forks
2k
Avg merge
1d 4h
Merged PRs (30d)
634

Description

**Describe the bug**

In the user login stage inside the authentication flow, a user may randomly be unable to log in, receiving an error message, “Flow does not apply to current user,” or encountering other similar issues. We discovered a race condition between frontend requests arriving at the backend that may cause this issue.

**To Reproduce**
Steps to reproduce the behavior:

1. Create an authentication source (e.g., Social Login via OIDC) and enable it, which corresponds to the `default-source-authentication` flow while authenticating.
2. Try to log in via this source multiple times or use tools to slow down requests to `/api/v3/flows/executor/default-source-authentication/`.
3. You will be declined by the flow, showing an error message indicating permission denied.

**Expected behavior**
Users should be able to log in normally.

**Screenshots**

1. Branding request responds with a delete cookie header:

![](https://github.com/user-attachments/assets/b9a8cf94-38af-44ac-a0c7-8f9233cef00d)

2. API request after it will have NO session cookie, causing authentication invalidation:

![](https://github.com/user-attachments/assets/2565844f-b259-4be1-9d34-8b6541877e06)

**Version and Deployment (please complete the following information):**

- authentik version: 2024.8.3
- Deployment: docker-compose

**Additional context**

After debugging, we found the following condition may trigger this issue:
1. Django cycles `session_key` once the user logs in, which purges the old `session_key` in cache storage.
2. Requests sent earlier arrive at the server later with an old session token with a cycled `sid`, causing the cache storage to not find the corresponding `sid`.
3. The server finds the session cookie exists but is not valid since the corresponding key is purged; it returns a `delete_cookie` header which removes the session cookie.
4. Once the request above arrives, the user session will be logged out immediately, even if they have completed the user login stage, which fails the subsequent request to `/api/v3/flows/executor/default-source-authentication/`.

References:
- https://github.com/django/django/blob/6765b6adf924c1bc8792a4a454d5a788c1abc98e/django/contrib/sessions/backends/base.py#L426-L435
- https://github.com/goauthentik/authentik/blob/08041792f22b09600d4286e30555268fc2aa55a5/authentik/root/middleware.py#L84-L91
- https://github.com/goauthentik/authentik/blob/08041792f22b09600d4286e30555268fc2aa55a5/authentik/stages/user_login/stage.py#L97-L102
- https://github.com/django/django/blob/6765b6adf924c1bc8792a4a454d5a788c1abc98e/django/contrib/auth/__init__.py#L114-L126

Currently, the workaround for this issue is under exploration.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the failure with delayed requests to /api/v3/flows/executor/default-source-authentication/, then read authentik/root/middleware.py, authentik/stages/user_login/stage.py, and the linked Django session and authentication code. Done means concurrent or delayed login requests no longer invalidate the active session or cause the flow to reject the current user.

Written by the indexing model from the issue text.

Assessment

Tech stack
django, python
Domain
authentication, backend
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.