Bug Description
Editing a user in the webapp (changing groups, status, Slack ID) fails with "Failed to update user" for every user whose IdP subject is an email address containing capital letters.
With Okta, the gateway stores the access token sub claim as the user subject (gateway/api/login/oidc/login.go, uinfo.Subject = subject after VerifyAccessToken). Okta's default access-token sub is the application username, i.e. the user's login with its original casing, so a user whose Okta login is Jane.Doe@example.com gets:
users.subject=Jane.Doe@example.comusers.email=jane.doe@example.com(the gateway lowercases theemailclaim inparseUserInfo)
The webapp sends the update to PUT /api/users/Jane.Doe@example.com (the subject). The handler in gateway/api/user/user.go (Update) checks isValidMailAddress(emailOrID), which is true, and therefore looks the user up with GetUserByEmailAndOrg, i.e. WHERE org_id = ? AND email = ?. The comparison is case-sensitive, Jane.Doe@example.com != jane.doe@example.com, so the lookup returns nil and the handler answers 404 user Jane.Doe@example.com not found.
Users whose Okta login is all lowercase are unaffected because subject and email are then identical.
GetUserByEmailOrID and the delete handler use the same isValidMailAddress branch and are affected the same way.
Steps to Reproduce
- Configure the gateway with Okta via IDP_ISSUER / IDP_CLIENT_ID / IDP_CLIENT_SECRET (org authorization server, e.g. https://acme.okta.com).
- In Okta, have a user whose login contains capital letters, e.g. Jane.Doe@example.com.
- Let that user log in to hoop once. In the DB,
subjectis Jane.Doe@example.com andemailis jane.doe@example.com. - As an admin, open Users in the webapp, click Edit on that user, add a group, click Update.
Expected Behavior
The user is updated. The lookup should match the user regardless of the casing of the email, or fall back to a subject lookup when the email lookup finds nothing.
Actual Behavior
Toast "Failed to update user". The network tab shows:
PUT /api/users/Jane.Doe@example.com 404 Not Found {"message":"user Jane.Doe@example.com not found"}
Request payload: {"id":"Jane.Doe@example.com","email":"jane.doe@example.com","name":"Jane Doe","status":"active","slack_id":"","groups":["Developers"]}
Workaround: call the endpoint directly with the lowercase email in the path (PUT /api/users/jane.doe@example.com), which hits the email branch with a matching value.
Version
1.247.0
Browser(s)
Chrome
Operating System
Ubuntu
Screenshots
No response
Additional Context
Suggested fix, either one is enough:
- In Update, GetUserByEmailOrID and Delete: when the email lookup returns nil, retry with GetUserBySubjectAndOrg before returning 404.
- Or make GetUserByEmailAndOrg compare case-insensitively (LOWER(email) = LOWER(?)), since email is always stored lowercased.
Changing the Okta side does not help: the org authorization server does not allow customising sub, and LoginCallback reuses dbUser.Subject for existing users anyway, so already-created rows keep the mixed-case subject.
Relevant Log Output
undefinedCode of Conduct
- I agree to follow this project's Code of Conduct
🔗 Synced to Linear: SUP-279