security(membership): end a member's sessions only in the organization that acted (#831) - #846
Open
alex-dembele wants to merge 2 commits into
Open
alex-dembele wants to merge 2 commits into
alex-dembele wants to merge 2 commits into
Conversation
…t acted (#831) Changing a member's role or withdrawing their access in organization A called RevokeAllUserTokens, which deleted every refresh token the person held, so A's decision signed them out of organization B as well. The membership service now revokes through RevokeUserTokensInTenant, which deletes only the refresh tokens whose tenant_id is A. Sessions in other organizations are unaffected, and are still re-checked against their own membership on every refresh by the org session resolver. Password change and reset keep revoking everything. Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
…e others alive (#831) Signed-off-by: alex-dembele <alexandredembele16@gmail.com>
This was referenced Sep 29, 2026
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #831
Problem
When an organization changed a member's role or withdrew their access,
membership.ServicecalledRevokeAllUserTokens(userID), which deleted every refresh token the person held. So a decision taken in A signed them out of B.Change
internal/auth/token.go: newRevokeUserTokensInTenant(ctx, userID, tenantID), which deletesWHERE user_id = ? AND tenant_id = ?.internal/application/membership: theSessionRevokerport now takes the tenant.SetStatusandChangeRolerevoke only in the organization that acted.RevokeAllUserTokens(criterion 3). They are untouched.Why no gap opens. Every refresh already re-checks the membership in the token's own organization and re-derives the role (
RefreshTokenPair→orgResolver, wired atcmd/server/main.go:592viaSetOrgSessionResolver). A session in B is never renewed on the strength of A, and a session in A dies with its tokens.Review note. The issue asked for a tech-lead review of the approach before implementation. The owner asked for it to be done directly. The approach is a scoping fix that reuses the existing
tenant_idcolumn. It does not change the session model. A review of this PR serves as that review.Verification
With the old behavior (revocation by
user_idonly), the test fails:the B session must survive a deactivate in A, refresh failed: invalid refresh token.Honest remainders
resolveSessionForOrg(active membership required), because that function lives inpackage main. Production wiring is not exercised by this test.DELETE.