OneSignal / OneSignal-iOS-SDK

OneSignal is a free push notification service for mobile apps. This plugin makes it easy to integrate your native iOS app with OneSignal. https://onesignal.com
Other
496 stars 263 forks source link

[JWT] Improve management of multiple users + finalize API #1487

Closed nan-li closed 1 month ago

nan-li commented 1 month ago

Description

One Line Summary

Improve handling of multiple users when Identity Verification is enabled, since future logins can succeed without previous logins succeeding.

Details

Motivation

Scope

Changes also affects when Identity Verification is off.

API

Objective C

@interface MyListener: NSObject<OSUserJwtInvalidatedListener>
@end

@implementation MyListener
- (void)onUserJwtInvalidatedWithEvent:(OSUserJwtInvalidatedEvent * _Nonnull)event { 
    NSLog(@"onUserJwtInvalidatedWithEvent: %@", [event jsonRepresentation]);
    NSLog(@"externalId: %@", event.externalId);
}

- (void)api {
    [OneSignal login:externalUserId withToken:token];
    [OneSignal updateUserJwt:externalUserId withToken:token];
    [OneSignal addUserJwtInvalidatedListener:myListener];
    [OneSignal removeUserJwtInvalidatedListener:myListener];
}

Swift

class MyListener: OSUserJwtInvalidatedListener {
    func onUserJwtInvalidated(event: OSUserJwtInvalidatedEvent) {
        print("event: \(event.jsonRepresentation())")
        print("externalId: \(event.externalId)")
    }
}

func api() {
    OneSignal.login(externalId: "eid", token: "token")
    OneSignal.updateUserJwt(externalId: "eid", token: "token")
    OneSignal.addUserJwtInvalidatedListener(myListener)
    OneSignal.removeUserJwtInvalidatedListener(myListener)
}

Testing

Unit testing

❗️ TODO

Manual testing

iPhone 15 pro simulator, iOS 17.2

JWT off, handling multiple repeated users cached 1. Wifi off, new install, no remote params received 2. Call `login(a)`, `login(b)`, `login(a)`, `login(b)` 3. The cached requests are: ``` Create anon user Identify user by EID a // The Create user EID b that would be here is removed once the second Create user EID b is enqueued Create user EID a Create user EID b ``` 4. Re-open app with wifi on 5. Remote params returns with JWT off 6. Appropriate requests are sent, state in the SDK is correct
JWT on, handling multiple repeated users cached ❗️ Fleshing out the details for this 1. Wifi off, new install, no remote params received 2. Call `login(a)`, `login(b)`, `login(a)`, `login(b)` 3. The cached requests are: ``` Create anon user Identify user by EID a // The Create user EID b that would be here is removed once the second Create user EID b is enqueued Create user EID a Create user EID b ``` 4. Re-open app with wifi on 5. Remote params returns with JWT on 6. Appropriate requests are sent, state in the SDK is correct
Upgrade from main with multiple users cached, JWT is on 1. On `main`, turn off wifi and run a new install 2. Call `login(a)`, `login(b)`, `logout`, `login(c)` 3. See these operations cached: ``` Create anonymous user Identify user by external ID a Create user external ID b Create anonymous user Identify user by external ID c ``` 4. Upgrade to this branch, turn on wifi and open app 5. The request are uncached, anon users dropped, and Identifies are converted so the state is now: ``` Create user external ID a Create user external ID b Create user external ID c ``` 6. Remote params returns with JWT on, nothing happens as there is no JWT token for any of these 7. Update JWT token for user c 8. Create user c is sent, IAM is fetched, state seems correct 9. Now update token for user b 10. Create user b is sent without the push subscription 11. Kill app, reopen, everything seems correct, user in SDK is still user c 12. Update token for user a 13. Create user a is sent without the push subscription

Affected code checklist

Checklist

Overview

Testing

Final pass


This change is Reviewable