Skip to content

Commit 5316329

Browse files
nan-liclaude
andcommitted
fix: release auth-pended requests when Identity Verification is turned 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>
1 parent 552890b commit 5316329

6 files changed

Lines changed: 129 additions & 4 deletions

File tree

iOS_SDK/OneSignalSDK/OneSignalInAppMessages/Controller/OSMessagingController.m

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1320,7 +1320,12 @@ - (void)onUserStateDidChangeWithState:(OSUserChangedState * _Nonnull)state {
13201320

13211321
#pragma mark OSUserJwtConfigListener Methods
13221322
- (void)onRequiresUserAuthChangedFrom:(enum OSRequiresUserAuth)from to:(enum OSRequiresUserAuth)to {
1323-
// This callback is unused, the controller will fetch when subscription ID changes
1323+
// Identity Verification was turned off: a fetch deferred waiting for a JWT may never be
1324+
// retried via onJwtUpdated once auth is off, so release it here
1325+
if (to == OSRequiresUserAuthOff && shouldRetryGetInAppMessagesOnJwtUpdated) {
1326+
shouldRetryGetInAppMessagesOnJwtUpdated = false;
1327+
[self getInAppMessagesFromServer];
1328+
}
13241329
}
13251330

13261331
- (void)onJwtUpdatedWithExternalId:(NSString *)externalId token:(NSString *)token {

iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSCustomEventsExecutor.swift

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -391,13 +391,35 @@ extension OSCustomEventsExecutor: OSUserJwtConfigListener {
391391
// If auth changed from false or unknown to true, drop invalid items
392392
if to == .on {
393393
removeInvalidDeltasAndRequests()
394+
} else if to == .off {
395+
// Identity Verification was turned off: release requests parked awaiting a JWT.
396+
reQueueAllPendingRequests()
394397
}
395398
}
396399

397400
func onJwtUpdated(externalId: String, token: String?) {
398401
reQueuePendingRequestsForExternalId(externalId: externalId)
399402
}
400403

404+
/// Identity Verification was turned off: move every auth-pended request, across all
405+
/// external IDs, back into the request queue and flush.
406+
private func reQueueAllPendingRequests() {
407+
self.dispatchQueue.async {
408+
guard !self.pendingAuthRequests.isEmpty else {
409+
return
410+
}
411+
for (_, requests) in self.pendingAuthRequests {
412+
for request in requests {
413+
self.requestQueue.append(request)
414+
}
415+
}
416+
self.pendingAuthRequests = [:]
417+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_CUSTOM_EVENTS_EXECUTOR_REQUEST_QUEUE_KEY, withValue: self.requestQueue)
418+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_CUSTOM_EVENTS_EXECUTOR_PENDING_QUEUE_KEY, withValue: self.pendingAuthRequests)
419+
self.processRequestQueue(inBackground: false)
420+
}
421+
}
422+
401423
private func reQueuePendingRequestsForExternalId(externalId: String) {
402424
self.dispatchQueue.async {
403425
guard let requests = self.pendingAuthRequests[externalId] else {

iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSIdentityOperationExecutor.swift

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -397,16 +397,43 @@ class OSIdentityOperationExecutor: OSOperationExecutor {
397397

398398
extension OSIdentityOperationExecutor: OSUserJwtConfigListener {
399399
func onRequiresUserAuthChanged(from: OSRequiresUserAuth, to: OSRequiresUserAuth) {
400-
// If auth changed from false or unknown to true, process requests
400+
// If auth changed from false or unknown to true, drop now-invalid requests
401401
if to == .on {
402402
removeInvalidDeltasAndRequests()
403+
} else if to == .off {
404+
// Identity Verification was turned off: release requests parked awaiting a JWT.
405+
reQueueAllPendingRequests()
403406
}
404407
}
405408

406409
func onJwtUpdated(externalId: String, token: String?) {
407410
reQueuePendingRequestsForExternalId(externalId: externalId)
408411
}
409412

413+
/// Identity Verification was turned off: move every auth-pended request, across all
414+
/// external IDs, back into the request queue and flush
415+
private func reQueueAllPendingRequests() {
416+
self.dispatchQueue.async {
417+
guard !self.pendingAuthRequests.isEmpty else {
418+
return
419+
}
420+
for (_, requests) in self.pendingAuthRequests {
421+
for request in requests {
422+
if let addRequest = request as? OSRequestAddAliases {
423+
self.addRequestQueue.append(addRequest)
424+
} else if let removeRequest = request as? OSRequestRemoveAlias {
425+
self.removeRequestQueue.append(removeRequest)
426+
}
427+
}
428+
}
429+
self.pendingAuthRequests = [:]
430+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
431+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue)
432+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_IDENTITY_EXECUTOR_PENDING_QUEUE_KEY, withValue: self.pendingAuthRequests)
433+
self.processRequestQueue(inBackground: false)
434+
}
435+
}
436+
410437
private func reQueuePendingRequestsForExternalId(externalId: String) {
411438
self.dispatchQueue.async {
412439
guard let requests = self.pendingAuthRequests[externalId] else {

iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSPropertyOperationExecutor.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -380,16 +380,38 @@ class OSPropertyOperationExecutor: OSOperationExecutor {
380380

381381
extension OSPropertyOperationExecutor: OSUserJwtConfigListener {
382382
func onRequiresUserAuthChanged(from: OSRequiresUserAuth, to: OSRequiresUserAuth) {
383-
// If auth changed from false or unknown to true, process requests
383+
// If auth changed from false or unknown to true, drop now-invalid requests
384384
if to == .on {
385385
removeInvalidDeltasAndRequests()
386+
} else if to == .off {
387+
// Identity Verification was turned off: release requests parked awaiting a JWT.
388+
reQueueAllPendingRequests()
386389
}
387390
}
388391

389392
func onJwtUpdated(externalId: String, token: String?) {
390393
reQueuePendingRequestsForExternalId(externalId: externalId)
391394
}
392395

396+
/// Identity Verification was turned off: move every auth-pended request, across all
397+
/// external IDs, back into the update queue and flush.
398+
private func reQueueAllPendingRequests() {
399+
self.dispatchQueue.async {
400+
guard !self.pendingAuthRequests.isEmpty else {
401+
return
402+
}
403+
for (_, requests) in self.pendingAuthRequests {
404+
for request in requests {
405+
self.updateRequestQueue.append(request)
406+
}
407+
}
408+
self.pendingAuthRequests = [:]
409+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_PROPERTIES_EXECUTOR_UPDATE_REQUEST_QUEUE_KEY, withValue: self.updateRequestQueue)
410+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_PROPERTIES_EXECUTOR_PENDING_QUEUE_KEY, withValue: self.pendingAuthRequests)
411+
self.processRequestQueue(inBackground: false)
412+
}
413+
}
414+
393415
private func reQueuePendingRequestsForExternalId(externalId: String) {
394416
self.dispatchQueue.async {
395417
guard let requests = self.pendingAuthRequests[externalId] else {

iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSSubscriptionOperationExecutor.swift

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -541,13 +541,40 @@ extension OSSubscriptionOperationExecutor: OSUserJwtConfigListener {
541541
func onRequiresUserAuthChanged(from: OneSignalOSCore.OSRequiresUserAuth, to: OneSignalOSCore.OSRequiresUserAuth) {
542542
if to == .on {
543543
removeInvalidDeltasAndRequests()
544+
} else if to == .off {
545+
// Identity Verification was turned off: release requests parked awaiting a JWT.
546+
reQueueAllPendingRequests()
544547
}
545548
}
546549

547550
func onJwtUpdated(externalId: String, token: String?) {
548551
reQueuePendingRequestsForExternalId(externalId: externalId)
549552
}
550553

554+
/// Identity Verification was turned off: move every auth-pended request, across all
555+
/// external IDs, back into the add/remove queues and flush.
556+
private func reQueueAllPendingRequests() {
557+
self.dispatchQueue.async {
558+
guard !self.pendingAuthRequests.isEmpty else {
559+
return
560+
}
561+
for (_, requests) in self.pendingAuthRequests {
562+
for request in requests {
563+
if let addRequest = request as? OSRequestCreateSubscription {
564+
self.addRequestQueue.append(addRequest)
565+
} else if let removeRequest = request as? OSRequestDeleteSubscription {
566+
self.removeRequestQueue.append(removeRequest)
567+
}
568+
}
569+
}
570+
self.pendingAuthRequests = [:]
571+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_ADD_REQUEST_QUEUE_KEY, withValue: self.addRequestQueue)
572+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_REMOVE_REQUEST_QUEUE_KEY, withValue: self.removeRequestQueue)
573+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_SUBSCRIPTION_EXECUTOR_PENDING_QUEUE_KEY, withValue: self.pendingAuthRequests)
574+
self.processRequestQueue(inBackground: false)
575+
}
576+
}
577+
551578
func handleUnauthorizedError(externalId: String, request: OSUserRequest) {
552579
if jwtConfig.isRequired ?? false {
553580
self.pendRequestUntilAuthUpdated(request, externalId: externalId)

iOS_SDK/OneSignalSDK/OneSignalUser/Source/Executors/OSUserExecutor.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -769,9 +769,12 @@ extension OSUserExecutor {
769769

770770
extension OSUserExecutor: OSUserJwtConfigListener {
771771
func onRequiresUserAuthChanged(from: OSRequiresUserAuth, to: OSRequiresUserAuth) {
772-
// If auth changed from false or unknown to true, process requests
772+
// If auth changed from false or unknown to true, drop now-invalid requests
773773
if to == .on {
774774
removeInvalidRequests()
775+
} else if to == .off {
776+
// Identity Verification is turned off: release requests parked awaiting a JWT
777+
reQueueAllPendingRequests()
775778
}
776779
self.executePendingRequests()
777780
}
@@ -780,6 +783,25 @@ extension OSUserExecutor: OSUserJwtConfigListener {
780783
reQueuePendingRequestsForExternalId(externalId: externalId)
781784
}
782785

786+
/// Identity Verification was turned off: move every auth-pended request, across all
787+
/// external IDs, back into the request queue and flush
788+
private func reQueueAllPendingRequests() {
789+
self.dispatchQueue.async {
790+
guard !self.pendingAuthRequests.isEmpty else {
791+
return
792+
}
793+
for (_, requests) in self.pendingAuthRequests {
794+
for request in requests {
795+
self.userRequestQueue.append(request)
796+
}
797+
}
798+
self.pendingAuthRequests = [:]
799+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_USER_EXECUTOR_USER_REQUEST_QUEUE_KEY, withValue: self.userRequestQueue)
800+
OneSignalUserDefaults.initShared().saveCodeableData(forKey: OS_USER_EXECUTOR_PENDING_QUEUE_KEY, withValue: self.pendingAuthRequests)
801+
self.executePendingRequests(withDelay: true)
802+
}
803+
}
804+
783805
private func reQueuePendingRequestsForExternalId(externalId: String) {
784806
self.dispatchQueue.async {
785807
guard let requests = self.pendingAuthRequests[externalId] else {

0 commit comments

Comments
 (0)