feat(account): add managed credits and cloud gateway
Introduce optional Apple account-backed credits with scoped gateway access while preserving local and BYOK paths. Refresh assistant behavior, tests, privacy disclosures, docs, and the website for the 2.0 experience.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
// AccountSignInCoordinatorTests.swift
|
||||
// OSGKeyboardTests
|
||||
//
|
||||
// End-to-end orchestration with injected Apple and integrity fakes.
|
||||
|
||||
@testable import OSGKeyboardHostSupport
|
||||
import XCTest
|
||||
|
||||
final class AccountSignInCoordinatorTests: XCTestCase {
|
||||
@MainActor
|
||||
func testSignInPassesHashedNonceToAppleAndRawNonceToServer() async throws {
|
||||
let expectedSession = makeAccountSession()
|
||||
let challengeId = UUID(uuidString: "dddddddd-dddd-dddd-dddd-dddddddddddd")!
|
||||
let transport = QueueAccountTransport([
|
||||
.init(
|
||||
statusCode: 201,
|
||||
body: Data(
|
||||
"""
|
||||
{"challengeId":"\(challengeId.uuidString)","challenge":"AQID","expiresAtEpochSeconds":4000000000}
|
||||
""".utf8
|
||||
)
|
||||
),
|
||||
.init(statusCode: 200, body: try sessionEnvelopeData(expectedSession))
|
||||
])
|
||||
let store = InMemoryAccountSecurityStore(
|
||||
keyState: AppAttestKeyState(keyId: "registered-key", isRegistered: true)
|
||||
)
|
||||
let client = AccountAPIClient(
|
||||
baseURL: URL(string: "https://account.test")!,
|
||||
transport: transport,
|
||||
sessionVault: store
|
||||
)
|
||||
let appAttestState = FakeAppAttestState()
|
||||
let integrity = DeviceIntegrityCoordinator(
|
||||
apiClient: client,
|
||||
deviceCheck: FakeDeviceCheckProvider(
|
||||
isSupported: true,
|
||||
token: Data([0x01])
|
||||
),
|
||||
appAttest: FakeAppAttestProvider(
|
||||
isSupported: true,
|
||||
state: appAttestState,
|
||||
keyId: "registered-key",
|
||||
attestationObject: Data(),
|
||||
assertion: Data([0x02])
|
||||
),
|
||||
keyStateStore: store
|
||||
)
|
||||
let apple = FakeAppleAuthorizationProvider(
|
||||
credential: AppleSignInCredential(
|
||||
identityToken: "identity-token",
|
||||
authorizationCode: "authorization-code"
|
||||
)
|
||||
)
|
||||
let nonce = AppleSignInNonce(
|
||||
rawValue: "raw-nonce",
|
||||
sha256Hex: "0123456789abcdef"
|
||||
)
|
||||
let coordinator = AccountSignInCoordinator(
|
||||
apiClient: client,
|
||||
appleAuthorization: apple,
|
||||
nonceGenerator: FixedNonceGenerator(nonce: nonce),
|
||||
integrity: integrity
|
||||
)
|
||||
|
||||
let session = try await coordinator.signIn()
|
||||
|
||||
XCTAssertEqual(session, expectedSession)
|
||||
XCTAssertEqual(apple.receivedNonceHash, nonce.sha256Hex)
|
||||
let requests = await transport.requests
|
||||
let signInRequest = try XCTUnwrap(
|
||||
requests.first { $0.url?.path == "/v1/auth/apple" }
|
||||
)
|
||||
let body = try XCTUnwrap(signInRequest.httpBody)
|
||||
let json = try XCTUnwrap(
|
||||
JSONSerialization.jsonObject(with: body) as? [String: Any]
|
||||
)
|
||||
XCTAssertEqual(json["nonce"] as? String, nonce.rawValue)
|
||||
XCTAssertEqual(json["deviceCheckToken"] as? String, "AQ==")
|
||||
let appAttest = try XCTUnwrap(json["appAttest"] as? [String: Any])
|
||||
XCTAssertEqual(appAttest["keyId"] as? String, "registered-key")
|
||||
XCTAssertEqual(appAttest["assertion"] as? String, "Ag==")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user