Skip to content

fix: detect when Identity verification becomes turned off#1674

Merged
nan-li merged 9 commits into
identity_verification_betafrom
fix/detect_iv_turned_off
Jun 26, 2026
Merged

fix: detect when Identity verification becomes turned off#1674
nan-li merged 9 commits into
identity_verification_betafrom
fix/detect_iv_turned_off

Conversation

@nan-li

@nan-li nan-li commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Description

One Line Summary

Detect when Identity Verification is turned off and release any requests that were waiting on a JWT.

Details

Motivation

The SDK detected Identity Verification (IV) turning on but never handled it turning off. Two gaps:

  1. A missing jwt_required field in remote params only set IV off when the value was previously unknown, so an app that had IV on stayed on after it was disabled remotely — the on→off transition was never even produced.
  2. No OSUserJwtConfigListener acted on the off transition, so requests parked per-external-id awaiting a JWT (each executor's pendingAuthRequests) were stranded forever — once IV is off, no JWT will ever arrive to release them.

Scope

  • A missing jwt_required remote param now always resolves IV to off (including the previously-on case).
  • On the off transition, each executor (User, Identity, Subscription, Property, CustomEvents) re-queues its auth-pended requests and flushes them without a JWT; the IAM controller re-fires a deferred fetch.
  • Not changed: the on/unknown transitions, the deferral of requests while IV status is unknown, and OSOperationRepo (deltas still flush on the normal poll cadence).
  • Also fixes a pre-existing bug where removeInvalidDeltasAndRequests persisted updateRequestQueue under the add/remove subscription queue keys.

Testing

Unit testing

Added per-executor tests asserting parked requests are released and sent without auth on the off transition, plus OSUserJwtConfig tests verifying a missing jwt_required resolves to off (including previously-on) and that an unchanged value does not re-fire listeners. All pass in OneSignalUserTests.

Manual testing

Not tested on a physical device; behavior is covered by the unit tests above.

Affected code checklist

  • Notifications
    • Display
    • Open
    • Push Processing
    • Confirm Deliveries
  • Outcomes
  • Sessions
  • In-App Messaging
  • REST API requests
  • Public API changes

Checklist

Overview

  • I have filled out all REQUIRED sections above
  • PR does one thing
  • Any Public API changes are explained in the PR details and conform to existing APIs

Testing

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

Final pass

  • Code is as readable as possible.
  • I have reviewed this PR myself, ensuring it meets each checklist item

@nan-li

nan-li commented Jun 11, 2026

Copy link
Copy Markdown
Contributor Author

@claude review

@nan-li nan-li changed the title Fix/detect iv turned off fix: detect when Identity verification becomes turned off Jun 11, 2026
@nan-li nan-li force-pushed the fix/detect_iv_turned_off branch from b000fdc to aef1699 Compare June 11, 2026 01:35
@nan-li

nan-li commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

@claude review

nan-li and others added 5 commits June 17, 2026 23:07
fix unsynchronized reads of OSIdentityModel state (jwtBearerToken in particular)
Two follow-on JWT concurrency issues exposed while reviewing the prior fix.

1. OSIdentityModelRepo.updateJwtToken fired the model's change notifier
   synchronously (→ onModelUpdated → onJwtTokenChanged → executor listeners)
   while still holding the repo's NSLock. Today nothing re-enters the repo
   lock so it doesn't deadlock by luck, but it's a trap for any future
   listener. The fix collects matching models under the lock and mutates
   them outside, so the notifier fires lock-free.

2. invalidateJwtForExternalId had a TOCTOU between its "is it already
   invalid?" read and the "set to invalid" write. A concurrent valid-token
   write landing between them would be overwritten with INVALID and trigger
   a needless re-auth. The transition is now an atomic compare-and-set on
   the model (invalidateJwtBearerToken); only the thread that wins the
   transition fires fireJwtExpired.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
renaming a variable and cleaning up comments
@nan-li nan-li force-pushed the fix/identity_verification_crashes branch from 4d9f72f to 7699bbd Compare June 18, 2026 06:07
nan-li and others added 4 commits June 17, 2026 23:08
A missing jwt_required field previously set the flag off only when it was still unknown, so an app that had Identity Verification on stayed on after it was disabled remotely. Treat a missing field as off unconditionally so the on->off transition is actually detected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…d off

While auth is required, requests without a valid JWT are parked per external ID awaiting a token. Once Identity Verification is turned off no token will arrive, so each JWT listener (User, Identity, Subscription, Property, and CustomEvents executors, plus the IAM controller) now releases the parked work and flushes it on the off transition.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
removeInvalidDeltasAndRequests saved updateRequestQueue under both the add and remove request queue keys, corrupting those caches when Identity Verification is enabled. Persist the matching addRequestQueue and removeRequestQueue instead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add per-executor tests asserting parked requests are released and sent without auth once Identity Verification is turned off, plus OSUserJwtConfig tests verifying a missing jwt_required remote param resolves to off (including the previously-on case) and that an unchanged value does not re-fire listeners.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@nan-li nan-li force-pushed the fix/detect_iv_turned_off branch from aef1699 to d4d113e Compare June 18, 2026 17:21

/// Identity Verification was turned off: move every auth-pended request, across all
/// external IDs, back into the request queue and flush.
private func reQueueAllPendingRequests() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so even though the calls originated with JWT and now JWT is off, we want to reQueue the requests?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, we could decide to drop but this would come from something like:

  1. login(userA) - addTag(userA)
  2. SDK tries to send it but the token for userA has since expired
  3. login(userB) - addTag(userB)
  4. SDK tries to send but the token for userB has expires
  5. All these requests go into a pending queue until an updated token is provided for one or both of them
  6. When IV resolves to false, we can send these requests without a token

Base automatically changed from fix/identity_verification_crashes to identity_verification_beta June 26, 2026 00:52
@nan-li nan-li merged commit be973cf into identity_verification_beta Jun 26, 2026
1 of 2 checks passed
@nan-li nan-li deleted the fix/detect_iv_turned_off branch June 26, 2026 15:57
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