Skip to content

fix: keep the session when browsing a group repository - #46

Merged
TheMeinerLP merged 3 commits into
mainfrom
fix/group-browse-logout
Oct 17, 2026
Merged

TheMeinerLP merged 3 commits into
mainfrom
fix/group-browse-logout

Conversation

@TheMeinerLP

Copy link
Copy Markdown

Description

Signed-in users were logged out when they opened a group repository in the dashboard, for example a group that mirrors private members through loopback references.

The details card of a group requests /<group>/maven-metadata.xml. Maven metadata is mirror first under the default storage policy, so that request goes to the loopback members. A member that refused the mirror identity answered 401, and the instance relayed that 401 to the browser. A loopback reference with the BASIC method never uses its credentials, so the member was read anonymously and refused. The dashboard then refreshed the session, retried the request, got the same 401 and ended the session, although the refresh had just proven that the session is valid.

Changes:

  • Backend: a loopback member that refuses the mirror identity is answered as not found. A remote mirror that refuses its configured credentials is answered as 502 Bad Gateway. Neither is relayed as 401 or 403 any more.
  • Frontend: a 401 that is refused again after a successful refresh no longer ends the session. In token mode a 401 ends the session only when GET /api/auth/me refuses the same credentials. A refused refresh still ends the session.

Deliberately not changed:

  • Loopback members are still read with the configured mirror identity only. The browsing user's own identity is not forwarded, because a copy stored by the group would then be made under that user's rights.
  • A loopback authorization with the BASIC method is ignored and only LOOPBACK_LINK takes effect. Changing that is a configuration decision and is left to a separate change.

Type of change

  • fix - bug fix
  • feat - new feature
  • refactor - internal change without behaviour change
  • perf - performance improvement
  • docs - documentation only
  • test - tests only
  • build / ci / chore - tooling, dependencies, pipelines
  • Breaking change (configuration, API or behaviour that existing deployments rely on)

How was this tested?

  • ./gradlew :reposilite-backend:test --tests com.reposilite.maven.RepositoryLoopbackRefusalTest: four new tests. Three fail without the backend change: the metadata of a group whose member the mirror cannot read, for a signed in and for an anonymous caller, and the bad gateway for a refusing remote. The fourth keeps a member that the mirror identity can read served.
  • The same run with RepositoryMembersTest, MavenFacadeTest, ResolutionCacheTest, ResolutionCacheIntegrationTest, MirrorCacheServiceTest and UpstreamSourceHostTest: all green.
  • npx vitest run on client.test.js, client-cookie.test.js, session-cookie.test.js, session.test.js and the other client and session specs: 184 tests pass. New tests cover a refused content request that keeps the session, a refused refresh that ends it, and the token mode session check.
  • Replay against the nightly image with a signed in user and a group over private members, then against this branch built into the same image:
Request with the session cookie of a signed in user Nightly This branch
GET /onelitefeather/maven-metadata.xml 401 404
GET /api/auth/me after a successful refresh 200 200
group root details, members, repository list 200 200
GET /public/<artifact>/maven-metadata.xml for a public member 200 200

Checklist

  • Commit messages follow the Conventional Commits convention documented in CLAUDE.md (English, imperative, one of feat, fix, docs, refactor, test, build, ci, chore, perf)
  • Tests cover the change, or the change is not testable and I explained why above
  • ./gradlew build passes locally - not run. Only the touched test classes were run, as listed above, because a full build was out of scope for this change
  • Documentation and configuration samples are updated if the change is user-facing - nothing user-facing changed; the documented 401 and 404 answers of the routes still hold
  • Existing copyright headers are preserved; new files carry the appropriate header
  • No credentials, tokens or personal data are included in the diff - the test fixtures use placeholder secrets only

TheMeinerLP and others added 3 commits October 17, 2026 18:37
A group that mirrors private members through loopback references
answered 401 when a member refused the mirror identity, and a remote
mirror relayed its own 401 or 403. Maven metadata is mirror first under
the default storage policy, so that refusal reached the caller as it
was. The dashboard reads a 401 as a rejected session, so a signed in
user was logged out by the details card of such a group.

A loopback member that refuses the mirror identity is answered as not
found: the refusal concerns the instance and not the caller, and the
member is not part of the answer. A remote host that refuses its
configured credentials is answered as bad gateway for the same reason.
A 401 on a listing or content request ended the signed in session. In
cookie mode the request was refreshed and retried once, and a second
401 ended a session that the refresh had just proved valid. A token
session ended on the first 401 without asking the server.

A refused retry after a successful refresh is now treated as the
server refusing that one request. In token mode a 401 ends the session
only when GET /api/auth/me refuses the same credentials. A refused
refresh still ends the session, and so does a request that carries no
credentials of its own, as before.
@github-actions

Copy link
Copy Markdown

Test results

  264 files    264 suites   46m 33s ⏱️
2 354 tests 2 353 ✅ 1 💤 0 ❌
2 420 runs  2 419 ✅ 1 💤 0 ❌

Results for commit a72d6a6.

@TheMeinerLP
TheMeinerLP merged commit 5cba28a into main Oct 17, 2026
8 checks passed
@TheMeinerLP
TheMeinerLP deleted the fix/group-browse-logout branch October 17, 2026 17:23
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.

1 participant