[bug]: /auth/sign-in/ returns HTTP 500 when the request has no User-Agent header
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 59.6k
- Forks
- 5.8k
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 49
Description
Describe the bug
POST /auth/sign-in/ (email/password) returns an unhandled HTTP 500 when the
request does not send a User-Agent header. The failure happens after the
credentials are verified, so a client with correct credentials still cannot sign in.
Any programmatic client that omits a User-Agent hits this (for example a CLI/API
consumer; Rust's reqwest sends no User-Agent by default).
Root cause
AuthenticationAdapter.save_user_data() reads the header with no default:
# apps/api/plane/authentication/adapter/base.py
user.last_login_uagent = self.request.META.get("HTTP_USER_AGENT")
When the header is absent, .get("HTTP_USER_AGENT") returns None. The field is
declared:
# apps/api/plane/db/models/user.py
last_login_uagent = models.TextField(blank=True)
blank=True but not null=True, so the column is NOT NULL. Saving None raises an
IntegrityError. It is not an AuthenticationException, so it is not caught by the
sign-in view's handler and Django returns a generic 500.
The sibling code path already handles this correctly, which is the inconsistency:
# apps/api/plane/authentication/utils/login.py
"user_agent": request.META.get("HTTP_USER_AGENT", ""),
To reproduce
Sign in with valid credentials but with the User-Agent header removed:
# 1) get a CSRF token and the csrftoken cookie
curl -s -c cookies.txt http://<plane-host>/auth/get-csrf-token/
# -> {"csrf_token": "<token>"}
# 2) sign in with NO User-Agent header (curl removes it when the value is empty)
curl -s -o /dev/null -w '%{http_code}\n' -X POST http://<plane-host>/auth/sign-in/ \
-b cookies.txt -H 'User-Agent:' \
--data-urlencode 'email=<you@example.com>' \
--data-urlencode 'password=<password>' \
--data-urlencode 'csrfmiddlewaretoken=<token>'
# -> 500
The identical request with any User-Agent header succeeds (302 to the dashboard).
Expected behavior
Sign-in should succeed regardless of whether a User-Agent header is present. A
missing header should be treated as an empty string, not None.
Suggested fix
Default the header to an empty string in save_user_data, matching login.py:
user.last_login_uagent = self.request.META.get("HTTP_USER_AGENT", "")
(Alternatively make the field null=True, but the empty-string default is the
smaller change and keeps it consistent with the sibling code.)
Environment
- Plane self-hosted,
v1.4.1(Docker Compose). - Reproduced against the
plane-apiservice (makeplane/plane-backend:v1.4.1). - Endpoint: the app auth API
POST /auth/sign-in/.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with apps/api/plane/authentication/adapter/base.py and compare its User-Agent lookup with apps/api/plane/authentication/utils/login.py. Run the provided curl reproduction without a User-Agent, then verify that POST /auth/sign-in/ succeeds instead of returning HTTP 500 and stores an empty value for the missing header.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- django, python
- Domain
- api, authentication, backend
- Issue type
- Bug
- Difficulty
- 1/5
- Estimated time
- Under an hour
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 92/100