@@ -145,6 +145,21 @@ @implementation OSMessagingController
145145@dynamic isInAppMessagingPaused;
146146// Maximum time decided to save IAM with redisplay on cache - current value: six months in seconds
147147static long OS_IAM_MAX_CACHE_TIME = 6 * 30 * 24 * 60 * 60 ;
148+
149+ /* *
150+ If an attempt to get IAMs from the server returns an Unauthorized response,
151+ the controller should re-attempt once the JWT token is updated.
152+ */
153+ static BOOL shouldRetryGetInAppMessagesOnJwtUpdated = false ;
154+
155+ /* *
156+ If an attempt to get IAMs from the server is blocked by incomplete alias information,
157+ the controller should re-attempt once the user state changes.
158+ An example of when this can happen occurs when users are switching with Identity Verification turned off -
159+ the SDK has a push subscription ID but no onesignal ID for the current user.
160+ */
161+ static BOOL shouldRetryGetInAppMessagesOnUserChange = false ;
162+
148163static OSMessagingController *sharedInstance = nil ;
149164static dispatch_once_t once;
150165+ (OSMessagingController *)sharedInstance {
@@ -167,6 +182,8 @@ + (void)removeInstance {
167182+ (void )start {
168183 OSMessagingController *shared = OSMessagingController.sharedInstance ;
169184 [OneSignalUserManagerImpl.sharedInstance.pushSubscriptionImpl addObserver: shared];
185+ [OneSignalUserManagerImpl.sharedInstance addObserver: shared];
186+ [OneSignalUserManagerImpl.sharedInstance subscribeToJwtConfig: shared key: OS_MESSAGING_CONTROLLER];
170187}
171188
172189static BOOL _isInAppMessagingPaused = false ;
@@ -236,15 +253,48 @@ - (void)updateInAppMessagesFromCache {
236253 [self evaluateMessages ];
237254}
238255
239- - (void )getInAppMessagesFromServer : (NSString *)subscriptionId {
240- [OneSignalLog onesignalLog: ONE_S_LL_VERBOSE message: @" getInAppMessagesFromServer" ];
241-
256+ /* *
257+ To get IAMs from the server, the following requirements are necessary:
258+ - A subscription ID
259+ - An appropriate alias (depending on Identity Verification enabled) for the subscription
260+ - A valid JWT token for the user if Identity Verification is enabled
261+
262+ This current implementation is not completely correct, as it will always use the current subscription ID and the current user.
263+ The SDK would need to consider if the current user owns the subscription on the server.
264+ */
265+ - (void )getInAppMessagesFromServer {
266+ [OneSignalLog onesignalLog: ONE_S_LL_VERBOSE message: @" getInAppMessagesFromServer attempted" ];
267+
268+ NSString *subscriptionId = OneSignalUserManagerImpl.sharedInstance .pushSubscriptionId ;
242269 if (!subscriptionId) {
270+ // When the subscription observer fires, it will drive a re-fetch
271+ [OneSignalLog onesignalLog: ONE_S_LL_VERBOSE message: @" getInAppMessagesFromServer blocked by null subscriptionId" ];
272+ [self updateInAppMessagesFromCache ];
273+ return ;
274+ }
275+
276+ OSAliasPair *alias = [OneSignalUserManagerImpl.sharedInstance getAliasForCurrentUser ];
277+ if (!alias) {
278+ // When the user observer fires, it will drive a re-fetch
279+ [OneSignalLog onesignalLog: ONE_S_LL_VERBOSE message: @" getInAppMessagesFromServer blocked by null alias" ];
280+ shouldRetryGetInAppMessagesOnUserChange = true ;
281+ [self updateInAppMessagesFromCache ];
282+ return ;
283+ }
284+
285+ NSDictionary <NSString *, NSString *> *header = [OneSignalUserManagerImpl.sharedInstance getCurrentUserFullHeader ];
286+ if (!header) {
287+ // When the JWT updated listener fires, it will drive a re-fetch
288+ [OneSignalLog onesignalLog: ONE_S_LL_VERBOSE message: @" getInAppMessagesFromServer blocked by missing header" ];
289+ shouldRetryGetInAppMessagesOnJwtUpdated = true ;
243290 [self updateInAppMessagesFromCache ];
244291 return ;
245292 }
246293
247- OSRequestGetInAppMessages *request = [OSRequestGetInAppMessages withSubscriptionId: subscriptionId];
294+ OSRequestGetInAppMessages *request = [OSRequestGetInAppMessages withSubscriptionId: subscriptionId
295+ withAliasLabel: alias.label
296+ withAliasId: alias.id
297+ withHeader: header];
248298 [OneSignalCoreImpl.sharedClient executeRequest: request onSuccess: ^(NSDictionary *result) {
249299 dispatch_async (dispatch_get_main_queue (), ^{
250300 [OneSignalLog onesignalLog: ONE_S_LL_VERBOSE message: @" getInAppMessagesFromServer success" ];
@@ -270,6 +320,10 @@ - (void)getInAppMessagesFromServer:(NSString *)subscriptionId {
270320 });
271321 } onFailure: ^(NSError *error) {
272322 [OneSignalLog onesignalLog: ONE_S_LL_VERBOSE message: [NSString stringWithFormat: @" getInAppMessagesFromServer failure: %@ " , error.localizedDescription]];
323+ OSResponseStatusType responseType = [OSNetworkingUtils getResponseStatusType: error.code];
324+ if (responseType == OSResponseStatusUnauthorized) {
325+ shouldRetryGetInAppMessagesOnJwtUpdated = true ;
326+ }
273327 [self updateInAppMessagesFromCache ];
274328 }];
275329}
@@ -1087,7 +1141,29 @@ - (void)onPushSubscriptionDidChangeWithState:(OSPushSubscriptionChangedState * _
10871141
10881142 // Pull new IAMs when the subscription id changes to a new valid subscription id
10891143 [OneSignalLog onesignalLog: ONE_S_LL_VERBOSE message: @" OSMessagingController onPushSubscriptionDidChange: changed to new valid subscription id" ];
1090- [self getInAppMessagesFromServer: state.current.id ];
1144+ [self getInAppMessagesFromServer ];
1145+ }
1146+
1147+ #pragma mark OSUserStateObserver Methods
1148+ - (void )onUserStateDidChangeWithState : (OSUserChangedState * _Nonnull)state {
1149+ NSLog (@" ❌ OSMessagingController onUserStateDidChangeWithState: %@ " , [state jsonRepresentation ]);
1150+ if (state.current .onesignalId && shouldRetryGetInAppMessagesOnUserChange) {
1151+ shouldRetryGetInAppMessagesOnUserChange = false ;
1152+ [self getInAppMessagesFromServer ];
1153+ }
1154+ }
1155+
1156+ #pragma mark OSUserJwtConfigListener Methods
1157+ - (void )onRequiresUserAuthChangedFrom : (enum OSRequiresUserAuth)from to : (enum OSRequiresUserAuth)to {
1158+ // This callback is unused, the controller will fetch when subscription ID changes
1159+ }
1160+
1161+ - (void )onJwtUpdatedWithExternalId : (NSString *)externalId token : (NSString *)token {
1162+ NSLog (@" ❌ OSMessagingController onJwtUpdatedWithExternalId: %@ token: %@ " , externalId, token);
1163+ if (![token isEqual: OS_JWT_TOKEN_INVALID] && shouldRetryGetInAppMessagesOnJwtUpdated) {
1164+ shouldRetryGetInAppMessagesOnJwtUpdated = false ;
1165+ [self getInAppMessagesFromServer ];
1166+ }
10911167}
10921168
10931169- (void )dealloc {
0 commit comments