From de81cdc8f667a0b07d1865b6c16f2852d5d8424d Mon Sep 17 00:00:00 2001 From: Marek Stransky Date: Tue, 5 Mar 2024 11:16:05 +0100 Subject: [PATCH 1/5] Remove `currentServerDate` from `WMTOperations` as there is more precise powerAuthSDK timeService with its timeSynchronization --- .../Service/WMTOperationsImpl.swift | 47 +++---------------- .../Operations/WMTOperations.swift | 12 ----- 2 files changed, 7 insertions(+), 52 deletions(-) diff --git a/WultraMobileTokenSDK/Operations/Service/WMTOperationsImpl.swift b/WultraMobileTokenSDK/Operations/Service/WMTOperationsImpl.swift index 5e9e186..d056440 100644 --- a/WultraMobileTokenSDK/Operations/Service/WMTOperationsImpl.swift +++ b/WultraMobileTokenSDK/Operations/Service/WMTOperationsImpl.swift @@ -118,13 +118,12 @@ class WMTOperationsImpl: WMTOperations, WMTService { set { networking.acceptLanguage = newValue } } - /// Calculated difference between server and device time - private var serverDateShiftInSeconds: TimeInterval? - var currentServerDate: Date? { - if let serverDateShiftInSeconds { - return Date().addingTimeInterval(serverDateShiftInSeconds) + private var currentDate: Date { + let timeService = powerAuth.timeSynchronizationService + if timeService.isTimeSynchronized { + return Date(timeIntervalSince1970: timeService.currentTime()) } - return nil + return Date() } private var tasks = [GetOperationsTask]() // Task that are waiting for operation fetch @@ -282,8 +281,7 @@ class WMTOperationsImpl: WMTOperations, WMTService { guard validateActivation(completion) else { return nil } - - let data = WMTAuthorizationData(operation: operation, timestampSent: currentServerDate ?? Date()) + let data = WMTAuthorizationData(operation: operation, timestampSent: currentDate) return networking.post(data: .init(data), signedWith: authentication, to: WMTOperationEndpoints.Authorize.endpoint) { response, error in self.processResult(response: response, error: error) { result in @@ -403,11 +401,7 @@ class WMTOperationsImpl: WMTOperations, WMTService { networking.post(data: .init(), signedWith: .possession(), to: WMTOperationEndpoints.List.endpoint) { response, error in assert(Thread.isMainThread) - - if let response { - self.processServerTime(response: response, requestStarted: requestStartDate) - } - + // if all tasks were canceled, just ignore the result. guard self.tasks.contains(where: { $0.isCanceled == false }) else { completion(.failure(WMTError(reason: .unknown))) @@ -430,33 +424,6 @@ class WMTOperationsImpl: WMTOperations, WMTService { } } - private func processServerTime(response: WMTOperationListResponse, requestStarted: Date) { - - let now = Date() - let requestDelay = now.timeIntervalSince1970 - requestStarted.timeIntervalSince1970 - - // server does not support this feature - guard var serverTime = response.currentTimestamp else { - return - } - - // Reject the value if the request took too long and we already have a server date. - // This is to avoid volatility of the value - if currentServerDate != nil && requestDelay > 1 { - return - } - - // We're adding half of the time that the request took to compensate for the network delay - serverTime = serverTime.addingTimeInterval(requestDelay/2) - - // If the difference is under 0.3 seconds, we ignore the new value to avoid unnecesary changes that might be due to network delay. - if let currentServerDate, abs(currentServerDate.timeIntervalSince1970 - serverTime.timeIntervalSince1970) < 0.3 { - return - } - - serverDateShiftInSeconds = serverTime.timeIntervalSince1970 - now.timeIntervalSince1970 - } - /// If request for operation fails at known error code, then this private function adjusts description of given AuthError. private func adjustOperationError(_ error: WMTError, auth: Bool) -> WMTError { diff --git a/WultraMobileTokenSDK/Operations/WMTOperations.swift b/WultraMobileTokenSDK/Operations/WMTOperations.swift index 7d19638..3ebc6a1 100644 --- a/WultraMobileTokenSDK/Operations/WMTOperations.swift +++ b/WultraMobileTokenSDK/Operations/WMTOperations.swift @@ -39,18 +39,6 @@ public protocol WMTOperations: AnyObject { /// Last cached operation result for easy access. var lastFetchResult: GetOperationsResult? { get } - /// Current server date - /// - /// This is calculated property based on the difference between phone date - /// and date on the server. - /// - /// This property is available after the first successful operation list request. - /// It might be nil if the server doesn't provide such a feature. - /// - /// Note that this value might be incorrent when the user decide to - /// change the system time during the runtime of the application. - var currentServerDate: Date? { get } - /// If operation loading is currently in progress. var isLoadingOperations: Bool { get } From 408e8a46805a4746cca7d96a37da5b413b1c6a1c Mon Sep 17 00:00:00 2001 From: Marek Stransky Date: Tue, 5 Mar 2024 13:23:34 +0100 Subject: [PATCH 2/5] Updated currentServerDate test - to show how to use PA timeService --- .../IntegrationTests.swift | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/WultraMobileTokenSDKTests/IntegrationTests.swift b/WultraMobileTokenSDKTests/IntegrationTests.swift index 137fdaf..73ddeb6 100644 --- a/WultraMobileTokenSDKTests/IntegrationTests.swift +++ b/WultraMobileTokenSDKTests/IntegrationTests.swift @@ -171,24 +171,16 @@ class IntegrationTests: XCTestCase { waitForExpectations(timeout: 20, handler: nil) } - /// `currentServerDate` is nil by default and after ops fetch, it should be set + /// `currentServerDate` was removed from WMTOperations in favor of more precise powerAuth timeService func testCurrentServerDate() { - let exp = expectation(description: "Server date should be set after operation fetch") + var synchronizedServerDate: Date? = nil - XCTAssertNil(self.ops.currentServerDate) - - _ = ops.getOperations { result in - - switch result { - case .success: - XCTAssertNotNil(self.ops.currentServerDate) - case .failure(let err): - XCTFail(err.description) - } - exp.fulfill() + let timeService = pa.timeSynchronizationService + if timeService.isTimeSynchronized { + synchronizedServerDate = Date(timeIntervalSince1970: timeService.currentTime()) } - waitForExpectations(timeout: 20, handler: nil) + XCTAssertNotNil(synchronizedServerDate) } /// Test of Login operation approval (1FA) From 0553b3c151db1b795fe7b84200b5ccef3b0c2ace Mon Sep 17 00:00:00 2001 From: Marek Stransky Date: Fri, 8 Mar 2024 11:41:52 +0100 Subject: [PATCH 3/5] Update docs --- docs/Changelog.md | 4 ++++ docs/Readme.md | 6 ++++++ docs/SDK-Integration.md | 1 + 3 files changed, 11 insertions(+) diff --git a/docs/Changelog.md b/docs/Changelog.md index 528067f..44b4e88 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -1,5 +1,9 @@ # Changelog +## 1.10.0 + +- Removed `currentServerTime` method [(#148)](https://github.com/wultra/mtoken-sdk-android/pull/139) + ## 1.9.0 (Jan 24, 2024) - Added possibility for custom reject reason [(#143)](https://github.com/wultra/mtoken-sdk-ios/pull/143) diff --git a/docs/Readme.md b/docs/Readme.md index bfeb1f7..90a99ec 100644 --- a/docs/Readme.md +++ b/docs/Readme.md @@ -15,6 +15,12 @@ Remarks: - This library does not contain any UI. - We also provide an [Android version of this library](https://github.com/wultra/mtoken-sdk-android). +## Migration Guides + +If you need to upgrade the Wultra Mobile Token SDK for iOS to a newer version, you can check the following migration guides: + +- [Migration from version `1.9.x` to `1.10.x`](Migration-1.10.md) + ## Integration Tutorials - [SDK Integration](SDK-Integration.md) diff --git a/docs/SDK-Integration.md b/docs/SDK-Integration.md index 6eb5668..f0d1a26 100644 --- a/docs/SDK-Integration.md +++ b/docs/SDK-Integration.md @@ -63,6 +63,7 @@ Note: If you want to use only operations, you can omit the Push dependency and i | `1.7.x` | `1.7.x` | | `1.8.x` | `1.8.x` | | `1.9.x` | `1.8.x` | +| `1.10.x` | `1.8.x` | ## Xcode Compatibility From 9c9b1f376fda3ebb7c1a58730e3dcc9593a101c0 Mon Sep 17 00:00:00 2001 From: Marek Stransky Date: Fri, 8 Mar 2024 11:44:45 +0100 Subject: [PATCH 4/5] Fix wording --- docs/Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 44b4e88..298d58c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -2,7 +2,7 @@ ## 1.10.0 -- Removed `currentServerTime` method [(#148)](https://github.com/wultra/mtoken-sdk-android/pull/139) +- Removed `currentServerTime` property [(#148)](https://github.com/wultra/mtoken-sdk-android/pull/139) ## 1.9.0 (Jan 24, 2024) From d86330425c2c4aa65fb24cc3ff678e2450c996d3 Mon Sep 17 00:00:00 2001 From: Marek Stransky Date: Fri, 8 Mar 2024 11:45:22 +0100 Subject: [PATCH 5/5] Add migration file --- docs/Migration-1.10.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 docs/Migration-1.10.md diff --git a/docs/Migration-1.10.md b/docs/Migration-1.10.md new file mode 100644 index 0000000..3cd4ade --- /dev/null +++ b/docs/Migration-1.10.md @@ -0,0 +1,34 @@ +# Migration from 1.9.x to 1.10.x + +This guide contains instructions for migration from Wultra Mobile Token SDK for iOS version `1.9.x` to version `1.10.x`. + +## Current Server Date + +### Removed Functionality + +The following calculated property was removed from the `WMTOperations` protocol: + +```swift +var currentServerDate: Date? { get } +``` + +The `currentServerDate` is a calculated property based on the difference between the phone's date and the date on the server. However, it had limitations and could be incorrect under certain circumstances, such as when the user decided to change the system time during the runtime of the application. + +### Replace with + +The new time synchronization directly from `PowerAuthSDK.timeSynchronizationService` is more precise and reliable. + +Here is the updated test method for reference: + +```swift +/// `currentServerDate` was removed from WMTOperations in favor of more precise powerAuth timeService +func testCurrentServerDate() { + var synchronizedServerDate: Date? = nil + let timeService = pa.timeSynchronizationService + if timeService.isTimeSynchronized { + synchronizedServerDate = Date(timeIntervalSince1970: timeService.currentTime()) + } + + XCTAssertNotNil(synchronizedServerDate) +} +```