Trusted Entitlements: add support for signing POST body#2753
Conversation
There was a problem hiding this comment.
Separating this sped up compilation from 4 seconds to less than 100ms (not sure exactly how long, but that was the threshold I set for the warning).
e6d030e to
d2eb42b
Compare
| func testLogInWithValidSignature() async throws { | ||
| let info = try await Purchases.shared.logIn(UUID().uuidString).customerInfo | ||
| expect(info.entitlements.verification) == .verified | ||
| } | ||
|
|
||
| func testLogInWithInvalidSignature() async throws { | ||
| self.invalidSignature = true | ||
|
|
||
| let info = try await Purchases.shared.logIn(UUID().uuidString).customerInfo | ||
| expect(info.entitlements.verification) == .failed | ||
| } |
There was a problem hiding this comment.
These exposed the fact that LogInOperation wasn't forwarding the verification result.
| expect(completionCalled.value).toEventually(equal(2)) | ||
| } | ||
|
|
||
| func testGetsEntitlementsWithVerifiedResponse() { |
There was a problem hiding this comment.
The diff here is horribly hard to read for no reason.
I simply moved 2 tests into a separate class, which is this:
class BackendPostReceiptWithSignatureVerificationTests: BaseBackendPostReceiptDataTests {
override var verificationMode: Configuration.EntitlementVerificationMode { .informational }
func testGetsEntitlementsWithVerifiedResponse() {
self.httpClient.mock(
requestPath: .postReceiptData,
response: .init(statusCode: .success,
response: Self.validCustomerResponse,
verificationResult: .verified)
)
let result = waitUntilValue { completed in
self.backend.post(receiptData: Self.receiptData,
productData: nil,
transactionData: .init(
appUserID: Self.userID,
presentedOfferingID: nil,
unsyncedAttributes: nil,
storefront: nil,
source: .init(isRestore: false, initiationSource: .purchase)
),
observerMode: false,
completion: { result in
completed(result)
})
}
expect(result).to(beSuccess())
if #available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.2, *) {
expect(result?.value?.entitlements.verification) == .verified
}
}
func testGetsEntitlementsWithFailedVerification() {
self.httpClient.mock(
requestPath: .postReceiptData,
response: .init(statusCode: .success,
response: Self.validCustomerResponse,
verificationResult: .failed)
)
let result = waitUntilValue { completed in
self.backend.post(receiptData: Self.receiptData2,
productData: nil,
transactionData: .init(
appUserID: Self.userID,
presentedOfferingID: nil,
unsyncedAttributes: nil,
storefront: nil,
source: .init(isRestore: false, initiationSource: .purchase)
),
observerMode: false,
completion: { result in
completed(result)
})
}
expect(result).to(beSuccess())
if #available(iOS 13.0, macOS 10.15, tvOS 13.0, watchOS 6.2, *) {
expect(result?.value?.entitlements.verification) == .failed
}
}
}| expect(headers?.keys).toNot(contain(HTTPClient.RequestHeader.postParameters.rawValue)) | ||
| } | ||
|
|
||
| func testPostRequestWithDisabledSignatureVerificationDoesNotContainPostParametersHeader() { |
There was a problem hiding this comment.
A test WITH the header is in SignatureVerificationHTTPClientTests below.
Trusted Entitlements: add support for signing POST bodyTrusted Entitlements: add support for signing POST body
| .map { response in | ||
| (response.body, created: response.statusCode == .createdSuccess) | ||
| ( | ||
| response.body.copy(with: response.verificationResult), |
There was a problem hiding this comment.
fc3fdeb to
5f1cde7
Compare
There was a problem hiding this comment.
I had to refactor these using #2769 because of the change to use HTTPRequestBody
aboedo
left a comment
There was a problem hiding this comment.
approving for now but let's remember to update the signatures of tests with the keys that don't have expiration set
There was a problem hiding this comment.
nitpick: reading this without knowing how we do signature verification, this seems like it'd be confusing and hard to understand why we'd need a specific header for post parameters. maybe something like postParametersHeaderForSigning(with body:? (also changed to "with" since the others use "with" too
| expect(completionCalled.value).toEventually(equal(2)) | ||
| } | ||
|
|
||
| func testGetsEntitlementsWithVerifiedResponse() { |
b0941c0 to
208d482
Compare
Doing that in a separate PR 👍🏻 |
Codecov Report
@@ Coverage Diff @@
## main #2753 +/- ##
==========================================
- Coverage 86.51% 86.50% -0.01%
==========================================
Files 214 216 +2
Lines 15396 15482 +86
==========================================
+ Hits 13320 13393 +73
- Misses 2076 2089 +13
|
|
Verified integration tests are working with the canary 🎉 |
a73bd1e to
9caa66d
Compare
9caa66d to
49eee02
Compare
49eee02 to
99ed6be
Compare
|
Ship it! |
**This is an automatic release.** ### Dependency Updates * Bump fastlane from 2.213.0 to 2.214.0 (#2824) via dependabot[bot] (@dependabot[bot]) ### Other Changes * `MainThreadMonitor`: don't crash if there is no test in progress (#2838) via NachoSoto (@NachoSoto) * `CI`: fixed Fastlane APITester lanes (#2836) via NachoSoto (@NachoSoto) * `Integration Tests`: workaround Swift runtime crash (#2826) via NachoSoto (@NachoSoto) * `@EnsureNonEmptyArrayDecodable` (#2831) via NachoSoto (@NachoSoto) * `iOS 17`: added tests for simulating cancellations (#2597) via NachoSoto (@NachoSoto) * `CI`: make all `Codecov` jobs `informational` (#2828) via NachoSoto (@NachoSoto) * `MainThreadMonitor`: check deadlocks only ever N seconds (#2820) via NachoSoto (@NachoSoto) * New `@NonEmptyStringDecodable` (#2819) via NachoSoto (@NachoSoto) * `MockDeviceCache`: avoid using real `UserDefaults` (#2814) via NachoSoto (@NachoSoto) * `throwAssertion`: fixed Xcode 15 compilation (#2813) via NachoSoto (@NachoSoto) * `CustomEntitlementsComputation`: fixed API testers (#2815) via NachoSoto (@NachoSoto) * `PackageTypeTests`: fixed iOS 12 (#2807) via NachoSoto (@NachoSoto) * `Tests`: avoid race-condition in leak detection (#2806) via NachoSoto (@NachoSoto) * Revert "`Unit Tests`: removed leak detection" (#2805) via NachoSoto (@NachoSoto) * `PackageType: Codable` implementation (#2797) via NachoSoto (@NachoSoto) * `SystemInfo.init` no longer `throws` (#2803) via NachoSoto (@NachoSoto) * `Trusted Entitlements`: add support for signing `POST` body (#2753) via NachoSoto (@NachoSoto) * `Tests`: unified default timeouts (#2801) via NachoSoto (@NachoSoto) * `Tests`: removed forced-unwrap (#2799) via NachoSoto (@NachoSoto) * `Tests`: added missing `super.setUp()` (#2804) via NachoSoto (@NachoSoto) * Replaced `FatalErrorUtil` with `Nimble` (#2802) via NachoSoto (@NachoSoto) * `Tests`: fixed another flaky test (#2795) via NachoSoto (@NachoSoto) * `TimingUtil`: improved tests by using `Clock` (#2794) via NachoSoto (@NachoSoto) * `IgnoreDecodeErrors`: log decoding error (#2778) via NachoSoto (@NachoSoto) * `TestLogHandler`: changed all tests to explicitly deinitialize it (#2784) via NachoSoto (@NachoSoto) * `LocalReceiptParserStoreKitTests`: fixed flaky test failure (#2785) via NachoSoto (@NachoSoto) * `Unit Tests`: removed leak detection (#2792) via NachoSoto (@NachoSoto) * `Tests`: fixed another flaky failure with asynchronous check (#2786) via NachoSoto (@NachoSoto) --------- Co-authored-by: NachoSoto <ignaciosoto90@gmail.com>
Changes:
HTTPClienthas a newX-Post-Params-Hashrequest headerHTTPRequest.Method.post'sEncodablevalue with a more specificHTTPRequestBody(likeHTTPResponseBody)HTTPRequestBodyallows overridingcontentForSignature(it defaults to[]) which thenSigninguses for the hashLogInOperationnot passing theVerificationResultto the resultCustomerInfo. This is captured in unit and integration tests now.POSTrequests inPath.logInandPath.postReceiptDataDepends on https://github.com/RevenueCat/khepri/pull/6246