Skip to content

Commit c9b0a94

Browse files
committed
Modify getting IAM to use alias and jwt
* All methods that trigger fetching IAM from server will no longer pass the push subscription ID. * The method to fetch IAM will itself handle the requirements. * To get IAMs from the server, the following requirements are necessary: - A subscription ID - An appropriate alias (depending on Identity Verification enabled) for the subscription - A valid JWT token for the user if Identity Verification is enabled * OSMessagingController will observe user and jwt
1 parent 90a08f7 commit c9b0a94

File tree

9 files changed

+107
-25
lines changed

9 files changed

+107
-25
lines changed

iOS_SDK/OneSignalSDK/OneSignalInAppMessages/Controller/OSMessagingController.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#import "OSInAppMessageInternal.h"
3030
#import "OSInAppMessageViewController.h"
3131
#import "OSTriggerController.h"
32+
#import <OneSignalOSCore/OneSignalOSCore.h>
3233
#import <OneSignalUser/OneSignalUser.h>
3334

3435
NS_ASSUME_NONNULL_BEGIN
@@ -39,7 +40,7 @@ NS_ASSUME_NONNULL_BEGIN
3940

4041
@end
4142

42-
@interface OSMessagingController : NSObject <OSInAppMessageViewControllerDelegate, OSTriggerControllerDelegate, OSMessagingControllerDelegate, OSPushSubscriptionObserver>
43+
@interface OSMessagingController : NSObject <OSInAppMessageViewControllerDelegate, OSTriggerControllerDelegate, OSMessagingControllerDelegate, OSPushSubscriptionObserver, OSUserStateObserver, OSUserJwtConfigListener>
4344

4445
@property (class, readonly) BOOL isInAppMessagingPaused;
4546

@@ -52,7 +53,7 @@ NS_ASSUME_NONNULL_BEGIN
5253
+ (void)removeInstance;
5354
- (void)presentInAppMessage:(OSInAppMessageInternal *)message;
5455
- (void)updateInAppMessagesFromCache;
55-
- (void)getInAppMessagesFromServer:(NSString * _Nullable)subscriptionId;
56+
- (void)getInAppMessagesFromServer;
5657
- (void)messageViewImpressionRequest:(OSInAppMessageInternal *)message;
5758
- (void)messageViewPageImpressionRequest:(OSInAppMessageInternal *)message withPageId:(NSString *)pageId;
5859

iOS_SDK/OneSignalSDK/OneSignalInAppMessages/Controller/OSMessagingController.m

Lines changed: 81 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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
147147
static 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+
148163
static OSMessagingController *sharedInstance = nil;
149164
static 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

172189
static 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 {

iOS_SDK/OneSignalSDK/OneSignalInAppMessages/OSInAppMessagingDefines.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@
2828
#ifndef OSInAppMessagingDefines_h
2929
#define OSInAppMessagingDefines_h
3030

31+
// OSMessagingController name
32+
#define OS_MESSAGING_CONTROLLER @"OSMessagingController"
3133

3234
// IAM display position enums
3335
typedef NS_ENUM(NSUInteger, OSInAppMessageDisplayPosition) {

iOS_SDK/OneSignalSDK/OneSignalInAppMessages/OneSignalInAppMessages.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
+ (Class<OSInAppMessages>_Nonnull)InAppMessages;
3434
+ (void)start;
35-
+ (void)getInAppMessagesFromServer:(NSString * _Nullable)subscriptionId;
35+
+ (void)getInAppMessagesFromServer;
3636
+ (void)onApplicationDidBecomeActive;
3737
+ (void)migrate;
3838
@end

iOS_SDK/OneSignalSDK/OneSignalInAppMessages/OneSignalInAppMessages.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ + (void)start {
4040
[OSMessagingController start];
4141
}
4242

43-
+ (void)getInAppMessagesFromServer:(NSString * _Nullable)subscriptionId {
44-
[OSMessagingController.sharedInstance getInAppMessagesFromServer:subscriptionId];
43+
+ (void)getInAppMessagesFromServer {
44+
[OSMessagingController.sharedInstance getInAppMessagesFromServer];
4545
}
4646

4747
+ (void)onApplicationDidBecomeActive {

iOS_SDK/OneSignalSDK/OneSignalInAppMessages/Requests/OSInAppMessagingRequests.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
#import "OSInAppMessageClickResult.h"
3030

3131
@interface OSRequestGetInAppMessages : OneSignalRequest
32-
+ (instancetype _Nonnull)withSubscriptionId:(NSString * _Nonnull)subscriptionId;
32+
+ (instancetype _Nonnull)withSubscriptionId:(NSString * _Nonnull)subscriptionId withAliasLabel:(NSString * _Nonnull)aliasLabel withAliasId:(NSString * _Nonnull)aliasId withHeader:(NSDictionary<NSString *, NSString *> * _Nonnull)header;
3333
@end
3434

3535
@interface OSRequestInAppMessageViewed : OneSignalRequest

iOS_SDK/OneSignalSDK/OneSignalInAppMessages/Requests/OSInAppMessagingRequests.m

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,15 @@ of this software and associated documentation files (the "Software"), to deal
2828
#import "OSInAppMessagingRequests.h"
2929

3030
@implementation OSRequestGetInAppMessages
31-
+ (instancetype _Nonnull)withSubscriptionId:(NSString * _Nonnull)subscriptionId {
31+
+ (instancetype _Nonnull)withSubscriptionId:(NSString * _Nonnull)subscriptionId
32+
withAliasLabel:(NSString * _Nonnull)aliasLabel
33+
withAliasId:(NSString * _Nonnull)aliasId
34+
withHeader:(NSDictionary<NSString *, NSString *> * _Nonnull)header {
3235
let request = [OSRequestGetInAppMessages new];
3336
request.method = GET;
3437
NSString *appId = [OneSignalConfigManager getAppId];
35-
request.path = [NSString stringWithFormat:@"apps/%@/subscriptions/%@/iams", appId, subscriptionId];
38+
request.additionalHeaders = header;
39+
request.path = [NSString stringWithFormat:@"apps/%@/users/by/%@/%@/subscriptions/%@/iams", appId, aliasLabel, aliasId, subscriptionId];
3640
return request;
3741
}
3842
@end

iOS_SDK/OneSignalSDK/OneSignalOSCore/Source/Jwt/OSAliasPair.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@
2929
An alias label and alias ID pair to represent a user.
3030
*/
3131
@objc public class OSAliasPair: NSObject {
32-
public let label: String
33-
public let id: String
32+
@objc public let label: String
33+
@objc public let id: String
3434

3535
public init(_ label: String, _ id: String) {
3636
self.label = label

iOS_SDK/OneSignalSDK/Source/OneSignal.m

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -416,16 +416,8 @@ + (void)startNewSessionInternal {
416416

417417
// TODO: Figure out if Create User also sets session_count automatically on backend
418418
[OneSignalUserManagerImpl.sharedInstance startNewSession];
419-
420-
// This is almost always going to be nil the first time.
421-
// The OSMessagingController is an OSPushSubscriptionObserver so that we pull IAMs once we have the sub id
422-
NSString *subscriptionId = OneSignalUserManagerImpl.sharedInstance.pushSubscriptionId;
423-
if (subscriptionId) {
424-
let oneSignalInAppMessages = NSClassFromString(ONE_SIGNAL_IN_APP_MESSAGES_CLASS_NAME);
425-
if (oneSignalInAppMessages != nil && [oneSignalInAppMessages respondsToSelector:@selector(getInAppMessagesFromServer:)]) {
426-
[oneSignalInAppMessages performSelector:@selector(getInAppMessagesFromServer:) withObject:subscriptionId];
427-
}
428-
}
419+
420+
[self fetchInAppMessages];
429421

430422
// The below means there are NO IAMs until on_session returns
431423
// because they can be ended, paused, or deleted from the server, or your segment has changed and you're no longer eligible
@@ -440,6 +432,13 @@ + (void)startNewSessionInternal {
440432
// [OSMessagingController.sharedInstance updateInAppMessagesFromCache]; // go to controller
441433
}
442434

435+
+ (void)fetchInAppMessages {
436+
let oneSignalInAppMessages = NSClassFromString(ONE_SIGNAL_IN_APP_MESSAGES_CLASS_NAME);
437+
if (oneSignalInAppMessages != nil && [oneSignalInAppMessages respondsToSelector:@selector(getInAppMessagesFromServer)]) {
438+
[oneSignalInAppMessages performSelector:@selector(getInAppMessagesFromServer)];
439+
}
440+
}
441+
443442
+ (void)startInAppMessages {
444443
let oneSignalInAppMessages = NSClassFromString(ONE_SIGNAL_IN_APP_MESSAGES_CLASS_NAME);
445444
if (oneSignalInAppMessages != nil && [oneSignalInAppMessages respondsToSelector:@selector(start)]) {

0 commit comments

Comments
 (0)