From 1a15b84ecf9901898abb24a9903c20107ca0e9db Mon Sep 17 00:00:00 2001 From: Harsh <6162866+harsh62@users.noreply.github.com> Date: Fri, 26 Jun 2026 10:13:56 -0400 Subject: [PATCH] fix(auth): disable URL caching in FoundationClientEngine The FoundationClientEngine is the base HTTP client used by the AWS SDK service clients (Cognito Identity / Identity Provider, etc.) for credential and token exchange. It previously used URLSession.shared, whose default configuration includes an on-disk URLCache. As a result, responses carrying Cognito tokens and AWS credentials were persisted to the app container's Cache.db, where they could be recovered by inspecting the device. Use a dedicated URLSession with urlCache = nil and a reloadIgnoringLocalCacheData policy so these responses are never written to disk. This mirrors the cache-disabling behavior already applied to the Hosted UI URLSession in AWSCognitoAuthPlugin+Configure. --- .../FoundationClientEngine.swift | 15 +++++++-- .../Utils/FoundationClientEngineTests.swift | 32 +++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 AmplifyPlugins/Core/AmplifyCredentialsTests/Utils/FoundationClientEngineTests.swift diff --git a/AmplifyPlugins/Core/AmplifyCredentials/CustomHttpClientEngine/FoundationClientEngine.swift b/AmplifyPlugins/Core/AmplifyCredentials/CustomHttpClientEngine/FoundationClientEngine.swift index fb6c241bd8..def8d54ca7 100644 --- a/AmplifyPlugins/Core/AmplifyCredentials/CustomHttpClientEngine/FoundationClientEngine.swift +++ b/AmplifyPlugins/Core/AmplifyCredentials/CustomHttpClientEngine/FoundationClientEngine.swift @@ -11,10 +11,12 @@ import SmithyHTTPAPI @_spi(FoundationClientEngine) public struct FoundationClientEngine: HTTPClient { + let urlSession: URLSession + public func send(request: SmithyHTTPAPI.HTTPRequest) async throws -> SmithyHTTPAPI.HTTPResponse { let urlRequest = try await URLRequest(from: request) - let (data, response) = try await URLSession.shared.data(for: urlRequest) + let (data, response) = try await urlSession.data(for: urlRequest) guard let httpURLResponse = response as? HTTPURLResponse else { // This shouldn't be necessary because we're only making HTTP requests. // `URLResponse` should always be a `HTTPURLResponse`. @@ -30,7 +32,16 @@ public struct FoundationClientEngine: HTTPClient { return httpResponse } - public init() {} + public init() { + // These requests carry Cognito tokens and AWS credentials. Disable URL + // caching so that responses are never persisted to disk (e.g. Cache.db), + // where they could be recovered by inspecting the app container. This + // mirrors the cache-disabling behavior used for the Hosted UI session. + let configuration = URLSessionConfiguration.default + configuration.urlCache = nil + configuration.requestCachePolicy = .reloadIgnoringLocalCacheData + self.urlSession = URLSession(configuration: configuration) + } /// no-op func close() async {} diff --git a/AmplifyPlugins/Core/AmplifyCredentialsTests/Utils/FoundationClientEngineTests.swift b/AmplifyPlugins/Core/AmplifyCredentialsTests/Utils/FoundationClientEngineTests.swift new file mode 100644 index 0000000000..d45ab2b027 --- /dev/null +++ b/AmplifyPlugins/Core/AmplifyCredentialsTests/Utils/FoundationClientEngineTests.swift @@ -0,0 +1,32 @@ +// +// Copyright Amazon.com Inc. or its affiliates. +// All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 +// + +@_spi(FoundationClientEngine) +@testable import InternalAmplifyCredentials +import XCTest + +class FoundationClientEngineTests: XCTestCase { + + /// Given: A `FoundationClientEngine`. + /// When: The engine is initialized. + /// Then: Its `URLSession` has URL caching disabled so that responses + /// carrying Cognito tokens / AWS credentials are never persisted + /// to disk (e.g. Cache.db). + func test_urlSession_disablesCaching() { + let engine = FoundationClientEngine() + let configuration = engine.urlSession.configuration + + XCTAssertNil( + configuration.urlCache, + "URLSession must not have a URLCache, otherwise credential responses are persisted to disk." + ) + XCTAssertEqual( + configuration.requestCachePolicy, + .reloadIgnoringLocalCacheData + ) + } +}