Skip to content

Commit 5a29ec5

Browse files
authored
Merge pull request #693 from Iterable/evan/MOB-7153-jwt-retry-omni
[MOB-7153] Implement JWT Retry Logic for iOS SDK
2 parents fe446dc + 3091191 commit 5a29ec5

File tree

5 files changed

+111
-2
lines changed

5 files changed

+111
-2
lines changed

swift-sdk.xcodeproj/project.pbxproj

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,13 @@
172172
5B5AA717284F1A6D0093FED4 /* MockNetworkSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B5AA710284F1A6D0093FED4 /* MockNetworkSession.swift */; };
173173
5B6C3C1127CE871F00B9A753 /* NavInboxSessionUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B6C3C1027CE871F00B9A753 /* NavInboxSessionUITests.swift */; };
174174
5B88BC482805D09D004016E5 /* NetworkSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5B88BC472805D09D004016E5 /* NetworkSession.swift */; };
175+
9FF05EAC2AFEA5FA005311F7 /* MockAuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF05EAB2AFEA5FA005311F7 /* MockAuthManager.swift */; };
176+
9FF05EAD2AFEA5FA005311F7 /* MockAuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF05EAB2AFEA5FA005311F7 /* MockAuthManager.swift */; };
177+
9FF05EAE2AFEA5FA005311F7 /* MockAuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF05EAB2AFEA5FA005311F7 /* MockAuthManager.swift */; };
178+
9FF05EAF2AFEA5FA005311F7 /* MockAuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF05EAB2AFEA5FA005311F7 /* MockAuthManager.swift */; };
179+
9FF05EB02AFEA5FA005311F7 /* MockAuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF05EAB2AFEA5FA005311F7 /* MockAuthManager.swift */; };
180+
9FF05EB12AFEA5FA005311F7 /* MockAuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF05EAB2AFEA5FA005311F7 /* MockAuthManager.swift */; };
181+
9FF05EB22AFEA5FA005311F7 /* MockAuthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9FF05EAB2AFEA5FA005311F7 /* MockAuthManager.swift */; };
175182
AC02480822791E2100495FB9 /* IterableInboxNavigationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC02480722791E2100495FB9 /* IterableInboxNavigationViewController.swift */; };
176183
AC02CAA6234E50B5006617E0 /* RegistrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC02CAA5234E50B5006617E0 /* RegistrationTests.swift */; };
177184
AC03094B21E532470003A288 /* InAppPersistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = AC03094A21E532470003A288 /* InAppPersistence.swift */; };
@@ -568,6 +575,7 @@
568575
5B6C3C1027CE871F00B9A753 /* NavInboxSessionUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavInboxSessionUITests.swift; sourceTree = "<group>"; };
569576
5B88BC472805D09D004016E5 /* NetworkSession.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworkSession.swift; sourceTree = "<group>"; };
570577
5BFC7CED27FC9AF300E77479 /* inbox-ui-tests-app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "inbox-ui-tests-app.entitlements"; sourceTree = "<group>"; };
578+
9FF05EAB2AFEA5FA005311F7 /* MockAuthManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MockAuthManager.swift; sourceTree = "<group>"; };
571579
AC02480722791E2100495FB9 /* IterableInboxNavigationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IterableInboxNavigationViewController.swift; sourceTree = "<group>"; };
572580
AC02CAA5234E50B5006617E0 /* RegistrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegistrationTests.swift; sourceTree = "<group>"; };
573581
AC03094A21E532470003A288 /* InAppPersistence.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InAppPersistence.swift; sourceTree = "<group>"; };
@@ -1360,6 +1368,7 @@
13601368
5588DF7D28C04494000697D7 /* MockUrlDelegate.swift */,
13611369
5588DF8D28C044DE000697D7 /* MockUrlOpener.swift */,
13621370
5588DFD528C04683000697D7 /* MockWebView.swift */,
1371+
9FF05EAB2AFEA5FA005311F7 /* MockAuthManager.swift */,
13631372
);
13641373
path = common;
13651374
sourceTree = "<group>";
@@ -2089,6 +2098,7 @@
20892098
ACA2A91A24AB266F001DFD17 /* Mocks.swift in Sources */,
20902099
5588DFAB28C045AE000697D7 /* MockInAppFetcher.swift in Sources */,
20912100
AC29D05C24B5A7E000A9E019 /* CI.swift in Sources */,
2101+
9FF05EB12AFEA5FA005311F7 /* MockAuthManager.swift in Sources */,
20922102
);
20932103
runOnlyForDeploymentPostprocessing = 0;
20942104
};
@@ -2102,6 +2112,7 @@
21022112
AC2C668720D3435700D46CC9 /* ActionRunnerTests.swift in Sources */,
21032113
00CB31B621096129004ACDEC /* TestUtils.swift in Sources */,
21042114
AC89661E2124FBCE0051A6CD /* AutoRegistrationTests.swift in Sources */,
2115+
9FF05EAF2AFEA5FA005311F7 /* MockAuthManager.swift in Sources */,
21052116
ACA8D1A921965B7D001B1332 /* InAppTests.swift in Sources */,
21062117
5588DFB928C045E3000697D7 /* MockInAppDelegate.swift in Sources */,
21072118
5588DFD128C0465E000697D7 /* MockAPNSTypeChecker.swift in Sources */,
@@ -2198,6 +2209,7 @@
21982209
buildActionMask = 2147483647;
21992210
files = (
22002211
5588DFB828C045E3000697D7 /* MockInAppDelegate.swift in Sources */,
2212+
9FF05EAE2AFEA5FA005311F7 /* MockAuthManager.swift in Sources */,
22012213
5588DF7028C0442D000697D7 /* MockDateProvider.swift in Sources */,
22022214
5588DFF028C046FF000697D7 /* MockMessageViewControllerEventTracker.swift in Sources */,
22032215
ACB37AB124026C1E0093A8EA /* SampleInboxViewDelegateImplementations.swift in Sources */,
@@ -2261,6 +2273,7 @@
22612273
ACC6A8502323910D003CC4BE /* UITestsHelper.swift in Sources */,
22622274
5588DFAA28C045AE000697D7 /* MockInAppFetcher.swift in Sources */,
22632275
ACFF4287246569D300FDF10D /* CommonExtensions.swift in Sources */,
2276+
9FF05EB02AFEA5FA005311F7 /* MockAuthManager.swift in Sources */,
22642277
);
22652278
runOnlyForDeploymentPostprocessing = 0;
22662279
};
@@ -2287,6 +2300,7 @@
22872300
5588DFCE28C0465E000697D7 /* MockAPNSTypeChecker.swift in Sources */,
22882301
5588DFDE28C046B7000697D7 /* MockLocalStorage.swift in Sources */,
22892302
ACA8D1A52196309C001B1332 /* Common.swift in Sources */,
2303+
9FF05EAC2AFEA5FA005311F7 /* MockAuthManager.swift in Sources */,
22902304
5588DFB628C045E3000697D7 /* MockInAppDelegate.swift in Sources */,
22912305
5588DF8628C044BE000697D7 /* MockCustomActionDelegate.swift in Sources */,
22922306
AC995F992166EE490099A184 /* CommonMocks.swift in Sources */,
@@ -2325,6 +2339,7 @@
23252339
5588DF7C28C04463000697D7 /* MockNotificationResponse.swift in Sources */,
23262340
5588DFD428C0465E000697D7 /* MockAPNSTypeChecker.swift in Sources */,
23272341
5588DFE428C046B7000697D7 /* MockLocalStorage.swift in Sources */,
2342+
9FF05EB22AFEA5FA005311F7 /* MockAuthManager.swift in Sources */,
23282343
ACC362C924D2CA8C002C67BA /* Common.swift in Sources */,
23292344
ACC362C524D2C190002C67BA /* TaskProcessorTests.swift in Sources */,
23302345
AC2AED4224EBC60C000EE5F3 /* TaskRunnerTests.swift in Sources */,
@@ -2343,6 +2358,7 @@
23432358
5588DFE728C046D7000697D7 /* MockInboxState.swift in Sources */,
23442359
ACFF42A424656CCE00FDF10D /* ViewController.swift in Sources */,
23452360
5588DF7F28C04494000697D7 /* MockUrlDelegate.swift in Sources */,
2361+
9FF05EAD2AFEA5FA005311F7 /* MockAuthManager.swift in Sources */,
23462362
5588DF8728C044BE000697D7 /* MockCustomActionDelegate.swift in Sources */,
23472363
5588DFD728C04683000697D7 /* MockWebView.swift in Sources */,
23482364
5588DFEF28C046FF000697D7 /* MockMessageViewControllerEventTracker.swift in Sources */,

swift-sdk/Internal/RequestProcessorUtil.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ struct RequestProcessorUtil {
1818
.onError { error in
1919
if error.httpStatusCode == 401, error.iterableCode == JsonValue.Code.invalidJwtPayload {
2020
ITBError("invalid JWT token, trying again: \(error.reason ?? "")")
21-
authManager?.requestNewAuthToken(hasFailedPriorAuth: true) { _ in
21+
authManager?.requestNewAuthToken(hasFailedPriorAuth: false) { _ in
2222
requestProvider().onSuccess { json in
2323
reportSuccess(result: result, value: json, successHandler: onSuccess, identifier: identifier)
2424
}.onError { error in

tests/common/MockAuthManager.swift

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
//
2+
// MockAuthManager.swift
3+
// swift-sdk
4+
//
5+
// Created by HARDIK MASHRU on 08/11/23.
6+
// Copyright © 2023 Iterable. All rights reserved.
7+
//
8+
import Foundation
9+
@testable import IterableSDK
10+
11+
class MockAuthManager: IterableAuthManagerProtocol {
12+
var shouldRetry = true
13+
var retryWasRequested = false
14+
15+
func getAuthToken() -> String? {
16+
return "AuthToken"
17+
}
18+
19+
func resetFailedAuthCount() {
20+
21+
}
22+
23+
func requestNewAuthToken(hasFailedPriorAuth: Bool, onSuccess: ((String?) -> Void)?) {
24+
if shouldRetry {
25+
// Simulate the authManager obtaining a new token
26+
retryWasRequested = true
27+
shouldRetry = false
28+
onSuccess?("newAuthToken")
29+
} else {
30+
// Simulate failing to obtain a new token
31+
retryWasRequested = false
32+
onSuccess?(nil)
33+
}
34+
}
35+
36+
func setNewToken(_ newToken: String) {
37+
38+
}
39+
40+
func logoutUser() {
41+
42+
}
43+
}

tests/unit-tests/AuthTests.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,9 @@ class AuthTests: XCTestCase {
525525
XCTAssertNil(internalAPI.auth.authToken)
526526
}
527527

528-
func testAuthTokenRefreshRetryOnlyOnce() {
528+
func testAuthTokenRefreshRetryOnlyOnce() throws {
529+
throw XCTSkip("skipping this test - auth token retries should occur more than once")
530+
529531
let condition1 = expectation(description: "\(#function) - callback not called correctly in some form")
530532
condition1.expectedFulfillmentCount = 2
531533

tests/unit-tests/IterableAPIResponseTests.swift

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,54 @@ class IterableAPIResponseTests: XCTestCase {
100100
wait(for: [xpectation], timeout: testExpectationTimeout)
101101
}
102102

103+
func testRetryOnInvalidJwtPayload() {
104+
let xpectation = expectation(description: "retry on 401 with invalidJWTPayload")
105+
106+
// Mock the dependencies and requestProvider for your test
107+
let authManager = MockAuthManager()
108+
109+
let networkErrorSession = MockNetworkSession() { _ in
110+
MockNetworkSession.MockResponse(statusCode: 401,
111+
data: ["code":"InvalidJwtPayload"].toJsonData(),
112+
delay: 1)
113+
}
114+
115+
let networkSuccessSession = MockNetworkSession() { _ in
116+
MockNetworkSession.MockResponse(statusCode: 200,
117+
data: ["msg": "success"].toJsonData(),
118+
delay: 1)
119+
}
120+
121+
let urlErrorRequest = createApiClient(networkSession: networkErrorSession).convertToURLRequest(iterableRequest: IterableRequest.post(PostRequest(path: "", args: nil, body: [:])))!
122+
123+
124+
let urlSuccessRequest = createApiClient(networkSession: networkSuccessSession).convertToURLRequest(iterableRequest: IterableRequest.post(PostRequest(path: "", args: nil, body: [:])))!
125+
126+
let requestProvider: () -> Pending<SendRequestValue, SendRequestError> = {
127+
if authManager.retryWasRequested {
128+
return RequestSender.sendRequest(urlSuccessRequest, usingSession: networkSuccessSession)
129+
}
130+
return RequestSender.sendRequest(urlErrorRequest, usingSession: networkErrorSession)
131+
}
132+
133+
let result = RequestProcessorUtil.sendRequest(
134+
requestProvider: requestProvider,
135+
authManager: authManager,
136+
requestIdentifier: "TestIdentifier"
137+
)
138+
139+
result.onSuccess { value in
140+
xpectation.fulfill()
141+
XCTAssert(true)
142+
}.onError { error in
143+
if authManager.retryWasRequested {
144+
xpectation.fulfill()
145+
}
146+
}
147+
148+
waitForExpectations(timeout: testExpectationTimeout)
149+
}
150+
103151
func testResponseCode401() { // 401 = unauthorized
104152
let xpectation = expectation(description: "401")
105153
let iterableRequest = IterableRequest.post(PostRequest(path: "", args: nil, body: [:]))

0 commit comments

Comments
 (0)