Skip to content

Feat/auth provider interface#266

Open
Justy116 wants to merge 12 commits into
logtide-dev:developfrom
Justy116:feat/auth-provider-interface
Open

Feat/auth provider interface#266
Justy116 wants to merge 12 commits into
logtide-dev:developfrom
Justy116:feat/auth-provider-interface

Conversation

@Justy116

Copy link
Copy Markdown

Summary

Tenant safety

LogTide is multi-tenant. Confirm the following for any new/changed query, endpoint,
or background job (see docs/security/tenant-isolation-audit.md):

  • Tenant tables are filtered by organization_id (and project_id where relevant).
  • Joins enforce scoping at every level, not just the outer query.
  • Updates/deletes verify scope before executing, not just trusting the filter to match.
  • Cache keys include the organization id.
  • Background jobs carry the org id and the consumer re-validates it.
  • Ids from a URL parameter or request body are verified to belong to the requesting tenant before use.
  • New data-access paths are added to the audit doc.
  • npm run check:tenant-scoping passes (run from packages/backend).

Testing

@CLAassistant

Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you all sign our Contributor License Agreement before we can accept your contribution.
1 out of 2 committers have signed the CLA.

✅ Polliog
❌ Giustino Gragnaniello


Giustino Gragnaniello seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

Resolves conflicts in projects restore flow: incorporates upstream
name/slug conflict pre-check in restoreProject() and corresponding
409 error handlers in the restore route.
@codecov

codecov Bot commented Jun 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.88889% with 2 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
packages/backend/src/modules/users/routes.ts 88.23% 2 Missing ⚠️

📢 Thoughts on this report? Let us know!

@Polliog Polliog linked an issue Jun 28, 2026 that may be closed by this pull request
5 tasks

@Polliog Polliog left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two findings from reviewing the auth-provider routing changes. The first is a security regression I'd like fixed before merge; the second is a minor robustness note.

1. User enumeration: disabled-account status is now disclosed without a valid password (blocking).
2. Non-atomic registration (minor, non-blocking).

Inline details below.

error: 'Internal server error',
});
}
const { user, session } = await authenticationService.authenticateWithProvider('local', parsedBody);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Routing local login through LocalProvider.authenticate changes the order of the security checks and introduces a user-enumeration issue.

usersService.login verified the password (service.ts:173) before checking disabled (service.ts:179), so a disabled account with a wrong password returned Invalid email or password, indistinguishable from a non-existent user. LocalProvider.authenticate checks disabled (local-provider.ts:65) before bcrypt.compare (local-provider.ts:74), so a disabled account now returns This account has been disabled for any password. That message is sent to the client at routes.ts:162 and shown verbatim in the login UI, so anyone can probe which emails belong to disabled accounts without knowing the password. Skipping bcrypt for disabled accounts also adds a timing side-channel.

Two things that make this easy to miss: usersService.login no longer has any production callers after this change (the safe ordering now lives only in dead code), and the existing disabled-account tests (users-service.test.ts:258, local-provider.test.ts:114) both use the correct password, so they pass under either ordering.

Please restore the old ordering in LocalProvider.authenticate (run bcrypt.compare before the password_hash/disabled checks); the post-auth disabled re-check in findOrCreateUser (authentication-service.ts:260) still prevents a disabled user from getting a session. Please also add a test for 'disabled account + wrong password -> Invalid email or password' to lock the behavior in.

const session = await usersService.login({
// Automatically log in the new user through the provider registry
// This also creates the user_identities link for the local provider
const { session } = await authenticationService.authenticateWithProvider('local', {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor / non-blocking: createUser commits the user in its own transaction (service.ts:115) and does not create the user_identities row; the identity is created only here, during auto-login, which runs outside that transaction. If this call fails for a transient reason (DB or provider-cache error), the user row is already committed but /register returns a 500 (the catch only handles ZodError and already exists), with no session returned. The account is recoverable via a later /login (the identity is backfilled on the next successful auth), so severity is low, but consider catching an auto-login failure here and returning 201 with the created user and no session instead of propagating a 500.

For the record, disabling the local provider is not a viable trigger for this: it is explicitly blocked at provider-service.ts:250.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Pluggable authentication provider interface

3 participants