Skip to content

fix(auth): don't re-authenticate a caller-supplied token as the client's user (ISSUE-167) - #508

Merged
dwolfson merged 1 commit into
odpi:mainfrom
dwolfson:fix/external-token-no-auth-retry
Oct 29, 2026
Merged

dwolfson merged 1 commit into
odpi:mainfrom
dwolfson:fix/external-token-no-auth-retry

Conversation

@dwolfson

Copy link
Copy Markdown
Member

Problem

On a bare 401, BaseServerClient._async_make_request minted a new token as self.user_id / self.user_pwd and retried, whatever token was in the headers. A token set with set_bearer_token() for a different user therefore quietly became a token for the client's own user, and the request succeeded as that user with no error. user_pwd falls back to settings.User_Profile.user_pwd, so a client built without a password was exposed too.

Seen in the portal: a user logged in as Peter had Lineage Explorer queries run as erinoverview. Repro on 6.2.14: MyProfile(view, url, "erinoverview", "secret"), then set_bearer_token(<expired token>), then get_my_profile() returns Erin's profile. exec_report_spec(token=..., user=..., user_pass=...) had the same exposure. (The portal already has a workaround on egeria-workspaces branch fix/token-expiry-identity-switch.)

Fix

  • BaseServerClient records the user it minted its current token for (_token_minted_for). The constructor and set_bearer_token() set it to None, because the owner of a caller-supplied token is unknown.
  • The 401 retry runs only when there is no token, or the token was minted for self.user_id. An expired caller-supplied token now raises PyegeriaUnauthorizedException.
  • EgeriaTech and Egeria pass the minting user to their sub-clients, including ones created later. So do the internal helper clients in DataDiscovery, ClassificationExplorer, AutomatedCuration and the format_set_executor fallback. Their own tokens still renew.
  • Recorded as ISSUE-167 under Fixed in PYEGERIA_ISSUES.md.

Behaviour change: a token passed to a client's constructor no longer auto-renews on 401. Code that passes an expired token that way now gets an error instead of a token for the configured user.

Tests

  • New tests/micro-tests/test_external_token_no_auth_retry.py has 7 tests. Four of them fail on the old code: external token, token minted for another user, set_bearer_token after minting, and an external token on EgeriaTech. The other three cover self-renewal and the no-token case, and pass both before and after.
  • The full micro-test suite passes (1643 tests, 0 failures).
  • omvs_audit.py reports the same counts as on main.
  • Not tested against a live server.

🤖 Generated with Claude Code

https://claude.ai/code/session_015pdMuQanRknaXmcpx4LmLb

…t's user (ISSUE-167)

On a bare 401, BaseServerClient._async_make_request minted a new token as
self.user_id and retried, whatever token was in the headers. A token set
with set_bearer_token() for a different user therefore quietly became a
token for the client's own user: the portal ran Lineage Explorer queries
for a user logged in as Peter as erinoverview. exec_report_spec(token=...)
had the same exposure.

The client now records who it minted its current token for. The retry
runs only when there is no token or the token was minted for self.user_id;
an expired caller-supplied token raises PyegeriaUnauthorizedException.
EgeriaTech, Egeria and the internal helper clients pass the minting user
on to sub-clients, so their own tokens still renew.

Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
Claude-Session: https://claude.ai/code/session_015pdMuQanRknaXmcpx4LmLb
Signed-off-by: Dan Wolfson <dan.wolfson@pdr-associates.com>
@dwolfson
dwolfson merged commit 08af28e into odpi:main Oct 29, 2026
5 checks passed
@dwolfson
dwolfson deleted the fix/external-token-no-auth-retry branch October 30, 2026 00:53
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