Skip to content

HTTPClient: added signature validation and introduced ErrorCode.signatureVerificationFailed#2272

Merged
NachoSoto merged 7 commits into
mainfrom
nacho/signature-integration
Feb 16, 2023
Merged

HTTPClient: added signature validation and introduced ErrorCode.signatureVerificationFailed#2272
NachoSoto merged 7 commits into
mainfrom
nacho/signature-integration

Conversation

@NachoSoto

@NachoSoto NachoSoto commented Feb 8, 2023

Copy link
Copy Markdown
Contributor

Fixes CSDK-634.

Changes:

  • Created HTTPResponseValidationResult
  • Added HTTPResponseValidationResult and HTTPClient.ResponseHeaders to HTTPResponse
  • Added new ErrorCode.signatureVerificationFailed
  • Extracted SigningType to create MockSigning to test HTTPClient without bothering with signatures
  • Refactored ETagManager to use HTTPResponse, making it easier to pass through response headers and verification results
  • Stored HTTPResponseValidationResult in ETagManager cache
  • HTTPClient handles signatures from response based on SystemInfo.responseVerificationLevel
  • Renamed HTTPRequest.createIntegrityEnforcedRequestRequest to HTTPRequest.createWithResponseVerification
  • Added lots of tests for this new behavior in HTTPClient
  • Added lots of new tests for ETagManager

@NachoSoto NachoSoto force-pushed the nacho/signature-integration branch from e224bb7 to 6ea5b98 Compare February 8, 2023 21:15
@NachoSoto NachoSoto requested a review from a team February 8, 2023 21:45
@NachoSoto NachoSoto force-pushed the nacho/signature-integration branch from 7685cad to 131208e Compare February 8, 2023 21:51

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This tests backwards compatibility with old responses. We handle that as a cache miss.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was moved below to SignatureVerificationHTTPClientTests

@NachoSoto NachoSoto marked this pull request as ready for review February 8, 2023 22:01
@codecov

codecov Bot commented Feb 8, 2023

Copy link
Copy Markdown

Codecov Report

Merging #2272 (45b2ea1) into main (6a52a64) will decrease coverage by 0.01%.
The diff coverage is 98.23%.

❗ Current head 45b2ea1 differs from pull request most recent head 7a62e5b. Consider uploading reports for the commit 7a62e5b to get more accurate results

@@            Coverage Diff             @@
##             main    #2272      +/-   ##
==========================================
- Coverage   86.20%   86.20%   -0.01%     
==========================================
  Files         186      187       +1     
  Lines       12306    12407     +101     
==========================================
+ Hits        10609    10696      +87     
- Misses       1697     1711      +14     
Impacted Files Coverage Δ
Sources/Misc/Signing.swift 90.27% <ø> (ø)
Sources/Networking/HTTPClient/HTTPResponse.swift 92.45% <95.65%> (+1.34%) ⬆️
Sources/Misc/Signing+ResponseValidation.swift 97.29% <97.29%> (ø)
Sources/Error Handling/ErrorCode.swift 94.79% <100.00%> (+0.13%) ⬆️
Sources/Error Handling/ErrorUtils.swift 85.83% <100.00%> (+0.41%) ⬆️
Sources/Logging/Strings/SigningStrings.swift 100.00% <100.00%> (ø)
Sources/Networking/HTTPClient/ETagManager.swift 99.14% <100.00%> (+0.12%) ⬆️
Sources/Networking/HTTPClient/HTTPClient.swift 98.29% <100.00%> (+0.30%) ⬆️
Sources/Networking/HTTPClient/HTTPRequest.swift 100.00% <100.00%> (ø)
Sources/Networking/HTTPClient/NetworkError.swift 99.21% <100.00%> (+0.09%) ⬆️
... and 10 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@NachoSoto NachoSoto changed the title [WIP] HTTPClient: added signature validation HTTPClient: added signature validation Feb 8, 2023

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we extend HTTPRequest to have a IntegrityVerifiedHTTPRequest that guarantees contains a Nonce? And then make this signature expect that class in particular. Doesn't make sense to validate a HTTPRequest that is not sending Nonces.

@NachoSoto NachoSoto Feb 8, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's definitely an alternative approach, but that's not very Swift-y. We'd have to move away from it being a struct and lose the value semantics on this type (can't inherit structs)

I think the main issue is this is bad name. It returns HTTPResponseValidationResult.notRequested if the request doesn't need to be verified, so maybe instead of createAndValidate it should just be HTTPResponse.create(with:...).

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively we'd have to make HTTPResponse a protocol and use a generic <Response: HTTPResponseType> everywhere to maintain type safety at compile time instead of doing that at runtime. But at that point it would be an overkill.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hummm... I see... I have no clue about swift :)

And something like createRequestAndValidator() that returns a request with the nonce, and a validator ready to use (contains the nonce)? It feels weird to have this generic create and validate that sometimes will not validate, plus there is not a lot of type safety, there is no way to enforce validation for some kind of request.

That way the request remains generic, you will just build a validator when requesting a request with validation. If not requesting validation, you will just have a create that builds a request.

Again, all this not knowing a thing about swift patterns :)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed this, I think it's clearer now. I do get your point of seemingly validating requests that don't require it.
HTTPResponse always has an HTTPResponseValidationResult (even if it's .notRequested).
So HTTPResponse.create(with:body:request:..) is the new API. It may or may not do any validation, but it'll return an HTTPResponse with the appropriate information. Does that sound less weird?

@NachoSoto

Copy link
Copy Markdown
Contributor Author

Apologies for the big diff 🙏🏻 I couldn't really split the changes here into multiple PRs since they're all connected.
Most of the changes are a lot of new tests though

@NachoSoto NachoSoto added pr:feat A new feature and removed refactor labels Feb 8, 2023
@NachoSoto NachoSoto changed the title HTTPClient: added signature validation HTTPClient: added signature validation and introduced ErrorCode.signatureVerificationFailed Feb 8, 2023
@NachoSoto NachoSoto force-pushed the nacho/signature-integration branch from fbbf8a7 to 45b2ea1 Compare February 8, 2023 22:37

@cadamsdotcom cadamsdotcom left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice change @NachoSoto. Not a swift expert, but looks good to me. The API with the optional requesting of verification is going to prove handy if we decide to do this for more endpoint in future..

PS particularly liked how simple the sign and createSalt test methods got, the simple keypair generation with private let (privateKey, publicKey) = SigningTests.createRandomKey(), and how packing things into test classes creates clean encapsulation. Learned a bunch about Swift reading this, thanks for sending it through!

Comment thread Sources/Networking/HTTPClient/HTTPClient.swift Outdated
Comment thread Tests/UnitTests/Networking/ETagManagerTests.swift Outdated
@NachoSoto

Copy link
Copy Markdown
Contributor Author

I'm thinking of renaming the ErrorCode here instead if we agree with the name in #2277.

@tonidero

Copy link
Copy Markdown
Contributor

I'm thinking of renaming the ErrorCode here instead if we agree with the name in #2277.

I think that name makes sense 👍

Comment on lines 60 to 61

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to be very careful with the case where it wasn't available. I can see us messing this up and breaking things for iOS 12 easily.
I wouldn't even mind having a separate case where for .unsupportedOSVersion or something

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but, when in doubt, I'd just consider it "valid" for older OS versions. You can't "cheat" this check so it's not really a useful hack, and being forced into staying with iOS 12 is probably a dealbreaker for most attackers anyway

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We talked about this offline.
We're going to solve this by making the "validated" APIs only available in iOS 13+, to force users to decide how to handle older versions.

The configuration API is already not available below, so it's also clear that you can't use it on older devices.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this will change in a followup PR I imagine right?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're interchangeably using validation and verification throughout the feature, we should pick one and settle. I think verification is more technically appropriate for this

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also... do we ever clean these up?

It feels like if we have an eTag but it doesn't have validation information and validation has been activated, we should kill the old eTag, but I don't recall what our cleanup mechanism for this was

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, we're not storing when validationResult = failed, so this would never be true, right?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

last question: what are we doing here when validation wasn't requested at all? Like, if validation is disabled, this should behave exactly as it always has

@NachoSoto NachoSoto Feb 15, 2023

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're interchangeably using validation and verification throughout the feature, we should pick one and settle. I think verification is more technically appropriate for this

I fixed those inconsistencies in #2277. I went with validation but we can change it back.

It feels like if we have an eTag but it doesn't have validation information and validation has been activated, we should kill the old eTag

Hmm good point, let me see if we have a test case for that and if not I'll add it.

also, we're not storing when validationResult = failed, so this would never be true, right?

That's correct, it's just an extra safety check. I can add a comment.

what are we doing here when validation wasn't requested at all? Like, if validation is disabled, this should behave exactly as it always has

It does, and all the existing tests still pass.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, updated ETagManager to ignore etags for the case where the stored cache had no validation but the new request requires a signature.

@tonidero tonidero left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still need to review tests but looking good!

Comment thread Tests/UnitTests/Mocks/MockHTTPClient.swift Outdated

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

Comment thread Sources/Networking/HTTPClient/HTTPClient.swift Outdated
@NachoSoto NachoSoto force-pushed the nacho/signature-integration branch from a08492a to 7a62e5b Compare February 15, 2023 21:50
@NachoSoto

Copy link
Copy Markdown
Contributor Author

All comments addressed.

@NachoSoto NachoSoto requested review from aboedo and tonidero February 15, 2023 21:51

@tonidero tonidero left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Comment on lines 60 to 61

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this will change in a followup PR I imagine right?

var statusCode: HTTPStatusCode
var responseHeaders: HTTPClient.ResponseHeaders
var body: Body
var validationResult: HTTPResponseValidationResult

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may be missing something but why did we make these var instead of let?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we can modify the validation result after it's initially created in HTTPClient (just an implementation detail).
Note that structs have value semantics, so this isn't like having mutable data in other languages.

Example:

struct Data {
  // Technically mutable
  var a: Int
  var b: String
}

let d = Data(a: 1, b: "test")
d.a +=1 // Error, `d` is immutable!

func f(_ d: Data) {
  d.a += 1 // Error, d is immutable
}

Additionally, structs get implicitly copied (they have value semantics, not reference), they're passed by value, so you can't lead to shared mutable state.

So basically it doesn't make a difference if these are vars, it just makes creating copies with different values easier without needing to do it manually calling the constructor again.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I asked about this before and I forgot 😅 thanks for explaining again!

struct ETagHeaderRequest {
var urlRequest: URLRequest
var refreshETag: Bool
var signatureVerificationEnabled: Bool

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, could these be let? I don't think callers of this mock would need to modify this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto, it doesn't make a difference, it would only be mutable for a var ETagHeaderRequest anyway.

@NachoSoto NachoSoto merged commit f05aabd into main Feb 16, 2023
@NachoSoto NachoSoto deleted the nacho/signature-integration branch February 16, 2023 11:07
NachoSoto added a commit that referenced this pull request Feb 16, 2023
…2267)

⚠️ 🎉 This also changes integration tests to use
`EntitlementVerificationLevel.enforced` so that integration tests fail
if signatures are invalid.

#### Depends on:
- https://github.com/RevenueCat/khepri/pull/5191
- https://github.com/RevenueCat/khepri/pull/5204
- #2214
- #2215 
- #2216
- #2272

_Marking this as `feat`ure because it contains a new error in
`PurchasesDiagnostics.Error`_
@NachoSoto NachoSoto mentioned this pull request Mar 14, 2023
This was referenced May 12, 2023
NachoSoto added a commit that referenced this pull request May 16, 2023
### New Features
* New `ErrorCode.signatureVerificationFailed` which will be used for an
upcoming feature

### Bugfixes
* `Purchases.deinit`: don't reset `Purchases.proxyURL` (#2346) via
NachoSoto (@NachoSoto)

<details>
<summary><b>Other Changes</b></summary>

* Introduced `Configuration.EntitlementVerificationMode` and
`VerificationResult` (#2277) via NachoSoto (@NachoSoto)
* `PurchasesDiagnostics`: added step to verify signature verification
(#2267) via NachoSoto (@NachoSoto)
* `HTTPClient`: added signature validation and introduced
`ErrorCode.signatureVerificationFailed` (#2272) via NachoSoto
(@NachoSoto)
* `ETagManager`: don't use ETags if response verification failed (#2347)
via NachoSoto (@NachoSoto)
* `Integration Tests`: removed `@preconcurrency import` (#2464) via
NachoSoto (@NachoSoto)
* Clean up: moved `ReceiptParserTests-Info.plist` out of root (#2460)
via NachoSoto (@NachoSoto)
* Update `CHANGELOG` (#2461) via NachoSoto (@NachoSoto)
* Update `SwiftSnapshotTesting` (#2453) via NachoSoto (@NachoSoto)
* Fixed docs (#2432) via Kaunteya Suryawanshi (@kaunteya)
* Remove unnecessary line break (#2435) via Andy Boedo (@aboedo)
* `ProductEntitlementMapping`: enabled entitlement mapping fetching
(#2425) via NachoSoto (@NachoSoto)
* `BackendPostReceiptDataTests`: increased timeout to fix flaky test
(#2426) via NachoSoto (@NachoSoto)
* Updated requirements to drop Xcode 13.x support (#2419) via NachoSoto
(@NachoSoto)
* `Integration Tests`: fixed flaky errors when loading offerings (#2420)
via NachoSoto (@NachoSoto)
* `PurchaseTester`: fixed compilation for `internal` entitlement
verification (#2417) via NachoSoto (@NachoSoto)
* `ETagManager`/`HTTPClient`: sending new `X-RC-Last-Refresh-Time`
header (#2373) via NachoSoto (@NachoSoto)
* `ETagManager`: don't send validation time if not present (#2490) via
NachoSoto (@NachoSoto)
* SwiftUI Sample Project: Refactor Package terms method to a computed
property (#2405) via Joseph Kokenge (@JOyo246)
* Clean up v3 load shedder integration tests (#2402) via Andy Boedo
(@aboedo)
* Fix iOS 12 compilation (#2394) via NachoSoto (@NachoSoto)
* Added new `VerificationResult.verifiedOnDevice` (#2379) via NachoSoto
(@NachoSoto)
* `PurchaseTester`: fix memory leaks (#2392) via Keita Watanabe
(@kitwtnb)
* Integration tests: add scheduled job (#2389) via Andy Boedo (@aboedo)
* Add lane for running iOS v3 load shedder integration tests (#2388) via
Andy Boedo (@aboedo)
* iOS v3 load shedder integration tests (#2387) via Andy Boedo (@aboedo)
* `Offline Entitlements`: created `LoadShedderIntegrationTests` (#2362)
via NachoSoto (@NachoSoto)
* Purchases.configure: log warning if attempting to use a static
appUserID (#2385) via Mark Villacampa (@MarkVillacampa)
* `SubscriberAttributesManagerIntegrationTests`: fixed flaky failures
(#2381) via NachoSoto (@NachoSoto)
* `@DefaultDecodable.Now`: fixed flaky test (#2374) via NachoSoto
(@NachoSoto)
* `PurchaseTesterSwiftUI`: fixed iOS compilation (#2376) via NachoSoto
(@NachoSoto)
* `SubscriberAttributesManagerIntegrationTests`: fixed potential race
condition (#2380) via NachoSoto (@NachoSoto)
* `Offline Entitlements`: create `CustomerInfo` from offline
entitlements (#2358) via NachoSoto (@NachoSoto)
* Added `@DefaultDecodable.Now` (#2372) via NachoSoto (@NachoSoto)
* `HTTPClient`: debug log when performing redirects (#2371) via
NachoSoto (@NachoSoto)
* `HTTPClient`: new flag to force server errors (#2370) via NachoSoto
(@NachoSoto)
* `OfferingsManager`: fixed Xcode 13.x build (#2369) via NachoSoto
(@NachoSoto)
* `Offline Entitlements`: store `ProductEntitlementMapping` in cache
(#2355) via NachoSoto (@NachoSoto)
* `Offline Entitlements`: added support for fetching
`ProductEntitlementMappingResponse` in `OfflineEntitlementsAPI` (#2353)
via NachoSoto (@NachoSoto)
* `Offline Entitlements`: created `ProductEntitlementMapping` (#2365)
via NachoSoto (@NachoSoto)
* Implemented `NetworkError.isServerDown` (#2367) via NachoSoto
(@NachoSoto)
* `ETagManager`: added test for 304 responses with no etag (#2360) via
NachoSoto (@NachoSoto)
* `TestLogHandler`: increased default capacity (#2357) via NachoSoto
(@NachoSoto)
* `OfferingsManager`: moved log to common method to remove hardcoded
string (#2363) via NachoSoto (@NachoSoto)
* `Offline Entitlements`: created `ProductEntitlementMappingResponse`
(#2351) via NachoSoto (@NachoSoto)
* `HTTPClient`: added test for 2xx response for request with etag
(#2361) via NachoSoto (@NachoSoto)
* `PurchaseTesterSwiftUI` improvements (#2345) via NachoSoto
(@NachoSoto)
* `ConfigureStrings`: fixed double-space typo (#2344) via NachoSoto
(@NachoSoto)
* `ETagManagerTests`: fixed tests on iOS 12 (#2349) via NachoSoto
(@NachoSoto)
* `DeviceCache`: simplified constructor (#2354) via NachoSoto
(@NachoSoto)
* `Trusted Entitlements`: changed all APIs to `internal` (#2350) via
NachoSoto (@NachoSoto)
* `VerificationResult.notRequested`: removed caching reference (#2337)
via NachoSoto (@NachoSoto)
* Finished signature verification `HTTPClient` tests (#2333) via
NachoSoto (@NachoSoto)
* `Configuration.Builder.with(entitlementVerificationMode:)`: improved
documentation (#2334) via NachoSoto (@NachoSoto)
* `ETagManager`: don't ignore failed etags with
`Signing.VerificationMode.informational` (#2331) via NachoSoto
(@NachoSoto)
* `IdentityManager`: clear `ETagManager` and `DeviceCache` if
verification is enabled but cached `CustomerInfo` is not (#2330) via
NachoSoto (@NachoSoto)
* Made `Configuration.EntitlementVerificationMode.enforced` unavailable
(#2329) via NachoSoto (@NachoSoto)
* Refactor: reorganized files in new Security and Misc folders (#2326)
via NachoSoto (@NachoSoto)
* `CustomerInfo`: use same grace period logic for active subscriptions
(#2327) via NachoSoto (@NachoSoto)
* `HTTPClient`: don't verify 4xx/5xx responses (#2322) via NachoSoto
(@NachoSoto)
* `EntitlementInfo`: request date is not optional (#2325) via NachoSoto
(@NachoSoto)
* `CustomerInfo`: removed `entitlementVerification` (#2320) via
NachoSoto (@NachoSoto)
* Renamed `VerificationResult.notVerified` to `.notRequested` (#2321)
via NachoSoto (@NachoSoto)
* `EntitlementInfo`: add a grace period limit to outdated entitlements
(#2288) via NachoSoto (@NachoSoto)
* Update `CustomerInfo.requestDate` from 304 responses (#2310) via
NachoSoto (@NachoSoto)
* `Signing`: added request time & eTag to signature verification (#2309)
via NachoSoto (@NachoSoto)
* `HTTPClient`: changed header search to be case-insensitive (#2308) via
NachoSoto (@NachoSoto)
* `HTTPClient`: automatically add `nonce` based on `HTTPRequest.Path`
(#2286) via NachoSoto (@NachoSoto)
* `PurchaseTester`: added ability to reload `CustomerInfo` with a custom
`CacheFetchPolicy` (#2312) via NachoSoto (@NachoSoto)
* Fix issue where underlying error information for product fetch errors
was not printed in log. (#2281) via Chris Vasselli (@chrisvasselli)
* `PurchaseTester`: added ability to set
`Configuration.EntitlementVerificationMode` (#2290) via NachoSoto
(@NachoSoto)
* SwiftUI: Paywall View should respond to changes on the UserView model
(#2297) via ConfusedVorlon (@ConfusedVorlon)
* Deprecate `usesStoreKit2IfAvailable` (#2293) via Andy Boedo (@aboedo)
* `Signing`: updated to use production public key (#2274) via NachoSoto
(@NachoSoto)
</details>

---------

Co-authored-by: RCGitBot <dev+RCGitBot@revenuecat.com>
NachoSoto added a commit to NachoSoto/purchases-ios that referenced this pull request May 17, 2023
### New Features
* New `ErrorCode.signatureVerificationFailed` which will be used for an
upcoming feature

### Bugfixes
* `Purchases.deinit`: don't reset `Purchases.proxyURL` (RevenueCat#2346) via
NachoSoto (@NachoSoto)

<details>
<summary><b>Other Changes</b></summary>

* Introduced `Configuration.EntitlementVerificationMode` and
`VerificationResult` (RevenueCat#2277) via NachoSoto (@NachoSoto)
* `PurchasesDiagnostics`: added step to verify signature verification
(RevenueCat#2267) via NachoSoto (@NachoSoto)
* `HTTPClient`: added signature validation and introduced
`ErrorCode.signatureVerificationFailed` (RevenueCat#2272) via NachoSoto
(@NachoSoto)
* `ETagManager`: don't use ETags if response verification failed (RevenueCat#2347)
via NachoSoto (@NachoSoto)
* `Integration Tests`: removed `@preconcurrency import` (RevenueCat#2464) via
NachoSoto (@NachoSoto)
* Clean up: moved `ReceiptParserTests-Info.plist` out of root (RevenueCat#2460)
via NachoSoto (@NachoSoto)
* Update `CHANGELOG` (RevenueCat#2461) via NachoSoto (@NachoSoto)
* Update `SwiftSnapshotTesting` (RevenueCat#2453) via NachoSoto (@NachoSoto)
* Fixed docs (RevenueCat#2432) via Kaunteya Suryawanshi (@kaunteya)
* Remove unnecessary line break (RevenueCat#2435) via Andy Boedo (@aboedo)
* `ProductEntitlementMapping`: enabled entitlement mapping fetching
(RevenueCat#2425) via NachoSoto (@NachoSoto)
* `BackendPostReceiptDataTests`: increased timeout to fix flaky test
(RevenueCat#2426) via NachoSoto (@NachoSoto)
* Updated requirements to drop Xcode 13.x support (RevenueCat#2419) via NachoSoto
(@NachoSoto)
* `Integration Tests`: fixed flaky errors when loading offerings (RevenueCat#2420)
via NachoSoto (@NachoSoto)
* `PurchaseTester`: fixed compilation for `internal` entitlement
verification (RevenueCat#2417) via NachoSoto (@NachoSoto)
* `ETagManager`/`HTTPClient`: sending new `X-RC-Last-Refresh-Time`
header (RevenueCat#2373) via NachoSoto (@NachoSoto)
* `ETagManager`: don't send validation time if not present (RevenueCat#2490) via
NachoSoto (@NachoSoto)
* SwiftUI Sample Project: Refactor Package terms method to a computed
property (RevenueCat#2405) via Joseph Kokenge (@JOyo246)
* Clean up v3 load shedder integration tests (RevenueCat#2402) via Andy Boedo
(@aboedo)
* Fix iOS 12 compilation (RevenueCat#2394) via NachoSoto (@NachoSoto)
* Added new `VerificationResult.verifiedOnDevice` (RevenueCat#2379) via NachoSoto
(@NachoSoto)
* `PurchaseTester`: fix memory leaks (RevenueCat#2392) via Keita Watanabe
(@kitwtnb)
* Integration tests: add scheduled job (RevenueCat#2389) via Andy Boedo (@aboedo)
* Add lane for running iOS v3 load shedder integration tests (RevenueCat#2388) via
Andy Boedo (@aboedo)
* iOS v3 load shedder integration tests (RevenueCat#2387) via Andy Boedo (@aboedo)
* `Offline Entitlements`: created `LoadShedderIntegrationTests` (RevenueCat#2362)
via NachoSoto (@NachoSoto)
* Purchases.configure: log warning if attempting to use a static
appUserID (RevenueCat#2385) via Mark Villacampa (@MarkVillacampa)
* `SubscriberAttributesManagerIntegrationTests`: fixed flaky failures
(RevenueCat#2381) via NachoSoto (@NachoSoto)
* `@DefaultDecodable.Now`: fixed flaky test (RevenueCat#2374) via NachoSoto
(@NachoSoto)
* `PurchaseTesterSwiftUI`: fixed iOS compilation (RevenueCat#2376) via NachoSoto
(@NachoSoto)
* `SubscriberAttributesManagerIntegrationTests`: fixed potential race
condition (RevenueCat#2380) via NachoSoto (@NachoSoto)
* `Offline Entitlements`: create `CustomerInfo` from offline
entitlements (RevenueCat#2358) via NachoSoto (@NachoSoto)
* Added `@DefaultDecodable.Now` (RevenueCat#2372) via NachoSoto (@NachoSoto)
* `HTTPClient`: debug log when performing redirects (RevenueCat#2371) via
NachoSoto (@NachoSoto)
* `HTTPClient`: new flag to force server errors (RevenueCat#2370) via NachoSoto
(@NachoSoto)
* `OfferingsManager`: fixed Xcode 13.x build (RevenueCat#2369) via NachoSoto
(@NachoSoto)
* `Offline Entitlements`: store `ProductEntitlementMapping` in cache
(RevenueCat#2355) via NachoSoto (@NachoSoto)
* `Offline Entitlements`: added support for fetching
`ProductEntitlementMappingResponse` in `OfflineEntitlementsAPI` (RevenueCat#2353)
via NachoSoto (@NachoSoto)
* `Offline Entitlements`: created `ProductEntitlementMapping` (RevenueCat#2365)
via NachoSoto (@NachoSoto)
* Implemented `NetworkError.isServerDown` (RevenueCat#2367) via NachoSoto
(@NachoSoto)
* `ETagManager`: added test for 304 responses with no etag (RevenueCat#2360) via
NachoSoto (@NachoSoto)
* `TestLogHandler`: increased default capacity (RevenueCat#2357) via NachoSoto
(@NachoSoto)
* `OfferingsManager`: moved log to common method to remove hardcoded
string (RevenueCat#2363) via NachoSoto (@NachoSoto)
* `Offline Entitlements`: created `ProductEntitlementMappingResponse`
(RevenueCat#2351) via NachoSoto (@NachoSoto)
* `HTTPClient`: added test for 2xx response for request with etag
(RevenueCat#2361) via NachoSoto (@NachoSoto)
* `PurchaseTesterSwiftUI` improvements (RevenueCat#2345) via NachoSoto
(@NachoSoto)
* `ConfigureStrings`: fixed double-space typo (RevenueCat#2344) via NachoSoto
(@NachoSoto)
* `ETagManagerTests`: fixed tests on iOS 12 (RevenueCat#2349) via NachoSoto
(@NachoSoto)
* `DeviceCache`: simplified constructor (RevenueCat#2354) via NachoSoto
(@NachoSoto)
* `Trusted Entitlements`: changed all APIs to `internal` (RevenueCat#2350) via
NachoSoto (@NachoSoto)
* `VerificationResult.notRequested`: removed caching reference (RevenueCat#2337)
via NachoSoto (@NachoSoto)
* Finished signature verification `HTTPClient` tests (RevenueCat#2333) via
NachoSoto (@NachoSoto)
* `Configuration.Builder.with(entitlementVerificationMode:)`: improved
documentation (RevenueCat#2334) via NachoSoto (@NachoSoto)
* `ETagManager`: don't ignore failed etags with
`Signing.VerificationMode.informational` (RevenueCat#2331) via NachoSoto
(@NachoSoto)
* `IdentityManager`: clear `ETagManager` and `DeviceCache` if
verification is enabled but cached `CustomerInfo` is not (RevenueCat#2330) via
NachoSoto (@NachoSoto)
* Made `Configuration.EntitlementVerificationMode.enforced` unavailable
(RevenueCat#2329) via NachoSoto (@NachoSoto)
* Refactor: reorganized files in new Security and Misc folders (RevenueCat#2326)
via NachoSoto (@NachoSoto)
* `CustomerInfo`: use same grace period logic for active subscriptions
(RevenueCat#2327) via NachoSoto (@NachoSoto)
* `HTTPClient`: don't verify 4xx/5xx responses (RevenueCat#2322) via NachoSoto
(@NachoSoto)
* `EntitlementInfo`: request date is not optional (RevenueCat#2325) via NachoSoto
(@NachoSoto)
* `CustomerInfo`: removed `entitlementVerification` (RevenueCat#2320) via
NachoSoto (@NachoSoto)
* Renamed `VerificationResult.notVerified` to `.notRequested` (RevenueCat#2321)
via NachoSoto (@NachoSoto)
* `EntitlementInfo`: add a grace period limit to outdated entitlements
(RevenueCat#2288) via NachoSoto (@NachoSoto)
* Update `CustomerInfo.requestDate` from 304 responses (RevenueCat#2310) via
NachoSoto (@NachoSoto)
* `Signing`: added request time & eTag to signature verification (RevenueCat#2309)
via NachoSoto (@NachoSoto)
* `HTTPClient`: changed header search to be case-insensitive (RevenueCat#2308) via
NachoSoto (@NachoSoto)
* `HTTPClient`: automatically add `nonce` based on `HTTPRequest.Path`
(RevenueCat#2286) via NachoSoto (@NachoSoto)
* `PurchaseTester`: added ability to reload `CustomerInfo` with a custom
`CacheFetchPolicy` (RevenueCat#2312) via NachoSoto (@NachoSoto)
* Fix issue where underlying error information for product fetch errors
was not printed in log. (RevenueCat#2281) via Chris Vasselli (@chrisvasselli)
* `PurchaseTester`: added ability to set
`Configuration.EntitlementVerificationMode` (RevenueCat#2290) via NachoSoto
(@NachoSoto)
* SwiftUI: Paywall View should respond to changes on the UserView model
(RevenueCat#2297) via ConfusedVorlon (@ConfusedVorlon)
* Deprecate `usesStoreKit2IfAvailable` (RevenueCat#2293) via Andy Boedo (@aboedo)
* `Signing`: updated to use production public key (RevenueCat#2274) via NachoSoto
(@NachoSoto)
</details>

---------

Co-authored-by: RCGitBot <dev+RCGitBot@revenuecat.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr:feat A new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants