Skip to content

feat: [SDK-5234] set Authorization: Bearer at the fetch chokepoint - #1502

Merged
sherwinski merged 1 commit into
sherwin/sdk-5308from
sherwin/sdk-5234
Sep 22, 2026
Merged

sherwinski merged 1 commit into
sherwin/sdk-5308from
sherwin/sdk-5234

Conversation

@sherwinski

Copy link
Copy Markdown
Contributor

Description

1 Line Summary

call() in src/shared/api/base.ts is the one place that writes Authorization: Bearer, and RequestMetadata carries the token as jwt.

Details

Second pull request of the M3 stack for Identity Verification for Web SDK. Stacked on #1501 (SDK-5308).

Before this change the token had 2 half-built paths and neither worked: RequestMetadata.jwtHeader was never set, and APIHeaders.Authorization was type-only. Now there is 1 mechanism.

src/shared/api/base.ts

  • New exported RequestOptions { headers?: APIHeaders; jwt?: string }. get, post, put, patch and delete take (action, data?, options?).
  • call() appends Authorization: Bearer <jwt> when options.jwt is set. No other code writes that header.
  • No request logging prints headers today (Log._error on a fetch timeout prints the URL only), so there is nothing to redact. The token stays out of the headers object on purpose so a future log line cannot print it by accident.

src/core/types/api.ts

  • RequestMetadata.jwtHeader?: APIHeaders becomes jwt?: string.

src/core/requests/api.ts

  • One requestOptions(requestMetadata) helper builds { headers, jwt }. The 11 user-scoped endpoints pass it. updateSubscriptionById and deleteSubscriptionById are unchanged; SDK-5237 decides those 2.
  • 4 of the old spread sites passed jwtHeader in the data slot of get and delete (getUserByAlias, deleteUserByAlias, getUserIdentity, deleteAlias). Had a token ever been set, a GET would have gone out with a body. The new tests pin that a GET with a token sends no body.
  • requestOptions sets OneSignal-Subscription-Id on every endpoint when subscriptionId is in the metadata. Before, only createNewUser and updateUserByAlias did. No executor passes subscriptionId today, so no request changes.

src/shared/models/APIHeaders.ts

  • Authorization?: string is gone. The index signature narrows from any to string, which is what Headers.append takes.

Test helper. getHandler in __test__/support/helpers/requests.ts records (headers, url) for every request in the exported requestHeadersFn, so tests can assert the bearer. The existing body callbacks are unchanged, so no toHaveBeenCalledWith assertion moves.

Bundle size. page.es6.js shrinks by 10 B gzipped to 44.27 kB. sw.js shares base.ts and grows by 2 B gzipped to 12.53 kB, 2 B over its limit. Both limits move to the measured size (44.27 kB and 12.54 kB).

Systems Affected

  • WebSDK
  • Backend
  • Dashboard

Validation

Tests

Info

New src/core/requests/api.test.ts (22 tests), the web mirror of Android HttpClientTests.kt:263-291:

  • For each of the 10 endpoints that forward the token: the Authorization: Bearer header is present when jwt is given, and absent when it is not. A POST with a token resolves ok.
  • The subscription id header and the bearer travel together on createNewUser.
  • A GET with a token sends no body.

vp check, vp test (706 tests), and vp run build:prod pass.

Checklist

  • All the automated tests pass or I explained why that is not possible
  • I have personally tested this on my machine or explained why that is not possible
  • I have included test coverage for these changes or explained why they are not needed

Programming Checklist
Interfaces:

  • Don't use default export
  • New interfaces are in model files

Functions:

  • Don't use default export
  • All function signatures have return types
  • Helpers should not access any data but rather be given the data to operate on.

Typescript:

  • No Typescript warnings
  • Avoid silencing null/undefined warnings with the exclamation point

Other:

  • Iteration: refrain from using elem of array syntax. Prefer forEach or use map
  • Avoid using global OneSignal accessor for context if possible. Instead, we can pass it to function/constructor so that we don't call OneSignal.context

Screenshots

Info

Not needed. No user-visible change.

Checklist

  • I have included screenshots/recordings of the intended results or explained why they are not needed

Related Tickets

RequestMetadata carries the token as `jwt`. The base API functions
take a RequestOptions object with `headers` and `jwt`, and `call()` is
the only place that writes the Authorization header. The 11 user-scoped
endpoints in requests/api.ts pass the token through one requestOptions
helper. The dead `jwtHeader` spread sites are gone; 4 of them passed
the header object in the body slot of GET and DELETE.

The MSW getHandler helper records request headers in requestHeadersFn
so tests can assert the bearer. Tests cover every forwarding endpoint
with and without a token, the subscription id header next to the
bearer, and a GET with a token that sends no body.

The page bundle shrinks by 10 B gzipped to 44.27 kB. The service worker
bundle grows by 2 B to 12.53 kB. Both limits move to the measured size.
@sherwinski
sherwinski added this pull request to stack #1507 September 22, 2026 02:31
@fadi-george

Copy link
Copy Markdown
Contributor

I assume youll update updateSubscriptionById & updateSubscriptionById later @sherwinski ?

@sherwinski

Copy link
Copy Markdown
Contributor Author

I assume youll update updateSubscriptionById & updateSubscriptionById later @sherwinski ?

Yes, in #1506

@sherwinski
sherwinski merged commit 87288bc into feat/identity-verification Sep 22, 2026
2 checks passed
@sherwinski
sherwinski deleted the sherwin/sdk-5234 branch September 22, 2026 23:37
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