Skip to content

Add option to keep Authorization header on requests - #1488

Open
bdunleavy22 wants to merge 3 commits into
cubewise-code:masterfrom
bdunleavy22:patch-6
Open

bdunleavy22 wants to merge 3 commits into
cubewise-code:masterfrom
bdunleavy22:patch-6

Conversation

@bdunleavy22

@bdunleavy22 bdunleavy22 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Two opt-in changes for token-based gateways (e.g. PAW's OAuth route) that check the bearer token on every request,
not only at session start.

 _start_session
   if auth_mode == ACCESS_TOKEN
-    add header "Bearer " + kwargs["access_token"]
+    add header "Bearer " + resolve(access_token)   # str, or callable invoked on every (re)connect
   GET /Configuration/ProductVersion
   re-set TM1SessionId cookie
-  remove Authorization header
+  if not keep_authorization_header               # parsed with translate_to_boolean
+    remove Authorization header

Evidence

Unit tests (offline): Tests/RestService_authorization_header_test.py

access_token="abc"                                   -> sent once, header removed after session start
access_token="abc", keep_authorization_header=True   -> header still set after session start
keep_authorization_header="False"                    -> stays off
access_token=callable, two session starts            -> "Bearer first", then "Bearer second"
access_token=callable returning ""                   -> ValueError

Against real gateways with an OAuth user token (TM1 11.8 on IBM Cloud, TM1 12.5.9 PAaaS):

  • Before (keep_authorization_header off): session starts, next request → 401 ("Failed to verify OAuth information" on v11, bare 401 + WWW-Authenticate: Bearer on v12); logout → 401.
  • After (flag on, callable token): connect → whoami → token forced to expire → re_connect() picks up a
    refreshed token → whoami → logout, all succeed on both.

Merge Danger

Door: two-way

Both are opt-in; a string access_token and the default keep_authorization_header=False behave as before.

Blast Radius: minimal

Only AuthenticationMode.ACCESS_TOKEN sessions are touched. The one new failure mode is a callable access_token
that returns an empty token, which raises a ValueError naming the kwarg.

🤖 Generated with Claude Code

Add option to keep Authorization header on requests
@MariusWirtz

Copy link
Copy Markdown
Collaborator

Thanks for the PR, this makes sense as an opt-in for gateways that validate the token on every request. A few things before we merge:

  1. Please run the value through translate_to_boolean like the other boolean kwargs. At the moment a config.ini entry of keep_authorization_header = False is a non-empty string and would switch the option on.

  2. Can you tighten the docstring so it's clear this is meant for token-based gateways (PAW, etc.)?

  3. A small unit test would be good: one case asserting the header is still there after _start_session when the flag is on, one asserting it's gone when the flag is off. Tests/RestService_cookies_test.py shows how we build a RestService without a live server.

Happy to merge once those are in.

bdunleavy22 and others added 2 commits October 16, 2026 10:04
…oken

- Parse keep_authorization_header with translate_to_boolean, so a config.ini
  value of "False" no longer switches it on.
- Document keep_authorization_header as an option for token-based gateways
  (e.g. PAW's OAuth route), and document access_token.
- Accept a zero-argument callable for access_token. It is resolved on every
  connect and reconnect, so a refreshing OAuth client supplies a fresh token
  after a session timeout instead of the stale one.
- Add offline unit tests for the header being kept/removed, the "False"
  string, and the callable being resolved on each session start.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bdunleavy22

Copy link
Copy Markdown
Contributor Author

Thanks Marius, all three are in:

  1. keep_authorization_header now goes through translate_to_boolean, so keep_authorization_header = False in a
    config.ini stays off. There's a test for exactly that case.
  2. The kwarg docstring now says it's for token-based gateways that validate the token on every request, such as
    PAW's OAuth route.
  3. Tests/RestService_authorization_header_test.py builds a real RestService with connect() and set_version()
    patched out, then runs _start_session against a stubbed GET: header kept with the flag on, removed with it off.

I also merged current master into the branch, and added one related change I'd like your view on: access_token
now also accepts a zero-argument callable, resolved on every connect and reconnect. Without it, a bearer token
that expires mid-session can't be replaced, because the 401 → connect() path reuses the same stale string. A
plain string behaves exactly as before. Happy to split it into its own PR if you'd prefer.

I tested both against real gateways, TM1 11.8 on IBM Cloud (PAW /api/v1/tm1/<db>) and TM1 12.5.9 PAaaS
(/api/<tenant>/v0/tm1/<db>), with an OAuth user token:

  • Flag off: the session starts, then the next request is rejected (401 access_denied: "Failed to verify OAuth information" on v11, a bare 401 with WWW-Authenticate: Bearer … on v12). Logout fails the same way.
  • Flag on: connect, whoami, a forced token refresh with reconnect, and logout all succeed.

@bdunleavy22

Copy link
Copy Markdown
Contributor Author

Linking this to #1491 as this PR addresses and resolves the problem.

This branch has not been deployed

No deployments
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.

2 participants