Conversation
b0ba388 to
20d9bbd
Compare
Salazareo
left a comment
There was a problem hiding this comment.
Artisan, handmade, human review
So a lot of these are more stylistic and code structure changes.
however, please do remove noisy logs, bits that make the code footprint larger ( commented out code, pseudo-blocks and boilerplate classes if they can be avoided) and avoid the this.modules.* syntax from before as it breaks support from language servers.
aside from that. 2 things to note:
-
that object outcome success looks suspect
-
lets avoid hard coded X provider configs, like
Google_Scope, and such, ideally we make this class follow spec and just pull config as needed from some storage, whether it be live or via config redeploy.
lastly I had some concerns about the change with gui token and http-only token.
fully in favour of moving to http-only tokens, and giving granular restrictions to tokens, but we'll need to verify to make sure existing features (like switching acocunts from gui) still function with that.
Additionally, and I'll say to take this with a grain of salt, but running codex 5.3 on this flagged some things too. Some I already mentioned in my artisan, human review, but some others I missed and definitely worth looking at:
LLM slop review
Findings (ordered by severity)
-
Critical: OIDC signup linking uses
outcome.successincorrectly, so the link step always executes.
File:src/backend/src/services/auth/OIDCService.js:237
OutcomeObjectexposes asuccess()method and afailedflag. Checkingif (outcome.success)is always truthy (function reference), solinkProviderToUser(...)runs even for failed outcomes. That can attempt linking withuser_id = null, turning expected signup validation failures into DB errors/500s. -
High: Change password request payload is broken for non-OIDC path and can throw in OIDC retry path.
File:src/gui/src/UI/UIWindowChangePassword.js:174
doSubmitexpects an object ({ new_password, current_password }), but code passes a string (doSubmit(current_password)), so both fields serialize asundefined. AlsodoSubmit()is called with no args on revalidation retry (src/gui/src/UI/UIWindowChangePassword.js:183), which throws due destructuring fromundefined. This can break password change for normal users and OIDC users. -
High: Change email OIDC retry can throw at runtime.
File:src/gui/src/UI/Settings/UIWindowChangeEmail.js:167
doSubmitdestructures{ new_email, password }, but retry path callsdoSubmit()with no argument. That throws before the request is sent, so OIDC revalidation flow can fail after popup. -
Medium: Username revalidation flow does not await popup completion before retry.
File:src/gui/src/UI/UIWindowChangeUsername.js:131
andsrc/gui/src/UI/UIWindowChangeUsername.js:151
myOpenRevalidatePopup(...)is invoked withoutawait, and a protected request is sent immediately afterward. The retry can race before cookie issuance and fail spuriously. -
Medium: Sensitive debug logging was added in auth paths.
Files:src/backend/src/middleware/configurable_auth.js:126,src/backend/src/routers/auth/oidc.js:31,src/backend/src/routers/logout.js:54
These log decoded token data, redirect state, and account password/email nullness to stdout. Even if some are gated byDEBUG, this is high-risk auth telemetry and should be removed or replaced with structured/redacted service logs. -
Low: Wrong rate-limit key used for username changes.
File:src/backend/src/routers/user-protected/change-username.js:49
Route checkssvc_edgeRateLimit.check('change-email-start')instead of a username-specific key. This ties username throttling behavior to the email flow by mistake and undermines intended controls.
Open Questions / Assumptions
- I assumed this review target is behavior/correctness/security; I did not run full backend/frontend test suites in this pass.
- I also noticed some incidental cleanup debt (debug comments, unused imports, duplicated utility additions), but I excluded style-only notes from findings.
Last notes
This was all static analysis, so we'll need to test this in depth before deploying after any changes.
extensions/whoami/routes.js
Outdated
| const providers = await svc_oidc.getEnabledProviderIds(); | ||
| const origin = (svc_oidc.global_config?.origin || '').replace(/\/$/, ''); | ||
| const provider = providers && providers[0]; | ||
| return provider |
There was a problem hiding this comment.
nit: can we just do if blocks for clarity?
There was a problem hiding this comment.
Where? Can you give an example? GitHub might be showing the wrong section of code, but this is my argument against what I think you're suggesting:
first rewrite:
let origin;
if ( svc_oidc.global_config?.origin ) {
origin = origin.replace(/\/$/, '');
} else {
origin = '';
}problem: changes a const to a let, fixable by:
cosnt origin = (() => {
if ( svc_oidc.global_config?.origin ) {
return origin.replace(/\/$/, '');
} else {
return '';
}
})();problem: unnecessary IIFE - probably more confusing to read for most
There was a problem hiding this comment.
this is a return, no need for let nor IIFE
There was a problem hiding this comment.
Not seeing how this would be simpler or easier to read. Can you show me using "Add a suggestion"?
There was a problem hiding this comment.
| return provider | |
| if (provider) { | |
| return {oidc_revalidate_url: `${origin}/auth/oidc/${provider}/start?flow=revalidate&user_id=${req.user.id}` | |
| } | |
| return {} | |
There was a problem hiding this comment.
I see now, GitHub wasn't showing the entire section of the code you were referring to as I suspected earlier. For the same reason your suggestion won't replace the entire expression; it will only replace thee return provider of:
return provider
? { oidc_revalidate_url: `${origin}/auth/oidc/${provider}/start?flow=revalidate&user_id=${req.user.id}` }
: {};GitHub allows commenting on a selection of lines of code btw - I would recommend doing that for future PR comments like this one.
I made this change because I agree that it's more clear. I still like the ternary expression better because it's easier to move around the expression as a whole because it's not interlaced with control-flow statements.
This commit is rather monolithic. An attempt to split it up into smaller
changes proved too difficult (as well as frustrating) and I realized it
would absolutely increase the chance of having a broken commit (making
bisects more difficult) unless a lot of testing effort between commits
was performed, which would have very little benefit.
The changes in this commit include:
- Outcome utility used by SignupService for error handling
- SignupService, whichs implements re-usable create_user function
- Signup method in OIDCService
- flow-specific callbacks in OIDC (separates login from signup)
- **SEPARATE SESSION COOKIE AND GUI COOKIE**
- this change "rocks the boat" the most and has the highest likelihood
of causing problems
When users make sensitive changes to their account they are asked to re-enter their password. This prevents a hijacked session from causing futher damage. Users created with the new OIDC flow do not necessarily have a password set on their account, and they need to also be able to make these changes. While removal of the password entry requirement for these users would solve this problem, it would also make their accounts more vulnerable. To solve this problem while maintaining the same security standard for OIDC users, we need them to confirm via either 2FA or re-authentication via OIDC. Since users aren't required to have 2FA, the re-authentication via OIDC approach is also the minimum viable solution. This commit adds OIDC re-authentication support for all endpoints under UserProtectedEndpointsService, and makes updates to the UIWindowChangeUsername dialog for manual testing. Currently this implementation fails at the final submission to change the username because of a separate issue with the correct authentication token not being set; this is related to the separation of GUI tokens vs http-only tokens.
The monthly number of username changes was hardcoded as `2`. Being able to configure this value makes it easier to test the username change flow. Hosters of OSS Puter may also find this configuration beneficial.
The OIDC re-authentication flow, which replaces password confirmation for accounts that were created with OIDC and do not have a password, was previously added to "change username" for manual testing of the backend-side implementation. Add the re-authentication flow to the remaining user-protected endpoints, which are: - change password - change email - disable two-factor authentication When using "change password" on a new account created via OIDC, the account changes state to a passworded account which causes these flows to use password confirmation as before instead of re-authentication.
There is common functionality between all of the GUI code for actions on protected endpoints. Update UIWindowChangeEmail and UIWindowChangeUsername to both use a new utility function called openRevalidatePopup in util/openid.js. This file is called `openid.js` instead of `oidc.js` so that it's more easily recognized by contributors who might be more familiar with the name of the organization than the name of the standard itself. After these changes, UIWindowChangePassword and the "disable 2FA" button in UITabSecurity still need to be updated to use `util/openid.js` instead of duplicating this functionality. The justification for following DRY here instead of leaving the implementation as-is is because these flows are particularly error prone and will be difficult to maintain without this consistency. Some subtle bugs I previously wasn't aware of got fixed in the process.
Use the openRevalidatePopup function in util/openid.js within UIWindowChangePassword instead of re-implementing that functionality. Additionally, normalize some of the code so it is more similar to UIWindowChangeUsername and UIWindowChangePassword.
In implementing OIDC it became necessary to introduce the separation of "GUI Tokens" and "Session Tokens". This breaks QR login because Puter does not set the HTTP-only session cookie when logging in with this flow. Add a middelware to WebServerService to detect QR Code logins and set the appropriate HTTP-only session cookie.
This button was useful during manual testing, but the re-authentication flow for protected endpoints with OIDC users reliably invokes the popup, so this is no longer necessary. Removing this button reduces clutter on these screens and might make the flow easier for users to understand.
A component was removed and an html property was passed to UIComponentWindow. This makes sense because UIWindow accepts an html property, so rather than update the calling code it made more sense to update UIComponentWindow to be more intuitive.
In lieu of knowing exactly what happened (probably more than one thing), the "Disable 2FA" window was very broken. It was blank, but then after fixing that all the actions were broken. There wasn't much value in keeping the implementation though, because it was already inconsistent with other flows - instead of fixing what was there it made more sense to re-use the pattern of UIWindowChangeUsername and UIWindowChangeEmail, creating UIWindowDisable2FA. After testing this, it works much better (it actaully works), but there is a caching issue unrelated to the UI implementation.
During development a property named `success` was inverted to a property named `failed` which resulted in an incorrect accessor reference with a referring piece of code that wasn't updated. This is type error.
These logs were temporary. I have a pre-merge TODO list item that says to remove these. They were caught in review so I'm removing them early.
I forgot that our transpile tooling requires manually gitignoring individual javascript files because we don't actually create a full generated build of backend.
ef7df3e to
4de6d38
Compare
This code was previously lost because I edited `outcomeutil.js` instead of `outcomeutil.ts`. We're not building into a `dist/` directory and `tsc` has a most peculiar lack of generating a comment at the top of output files stating something like "// GENERATED - DO NOT EDIT" as I've seen from every other code generator or transpiler I've worked with. This caused the bug with duplicate confirmed emails and "account not found" during testing on the staging server.
let's not merge on a Friday night, but this is ready for review.
These changes implement login and signup for OIDC flows, as well as consequential changes because of how these changes disrupt other parts of authentication, such as: