Merge pull request 'fix/app-attest/production-environment' (#41) from fix/app-attest/production-environment into main
Reviewed-on: Loverde-Company-LTDA/Pedi-Foods-Skip#41
This commit is contained in:
@@ -2,7 +2,11 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>com.apple.developer.devicecheck.app-attest-opt-in</key>
|
||||||
|
<array>
|
||||||
|
<string>CDhash</string>
|
||||||
|
</array>
|
||||||
<key>com.apple.developer.devicecheck.appattest-environment</key>
|
<key>com.apple.developer.devicecheck.appattest-environment</key>
|
||||||
<string>development</string>
|
<string>$(APP_ATTEST_ENVIRONMENT)</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -178,6 +178,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 496EB72F2A6AE4DE00C1253B /* PediFoods.xcconfig */;
|
baseConfigurationReference = 496EB72F2A6AE4DE00C1253B /* PediFoods.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
|
APP_ATTEST_ENVIRONMENT = development;
|
||||||
DEVELOPMENT_TEAM = K4E5BZMM4V;
|
DEVELOPMENT_TEAM = K4E5BZMM4V;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = "Pedi Foods";
|
INFOPLIST_KEY_CFBundleDisplayName = "Pedi Foods";
|
||||||
@@ -196,8 +197,9 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
baseConfigurationReference = 496EB72F2A6AE4DE00C1253B /* PediFoods.xcconfig */;
|
baseConfigurationReference = 496EB72F2A6AE4DE00C1253B /* PediFoods.xcconfig */;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
CODE_SIGN_IDENTITY = "Apple Distribution";
|
APP_ATTEST_ENVIRONMENT = production;
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_IDENTITY = "Apple Development";
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
DEVELOPMENT_TEAM = K4E5BZMM4V;
|
DEVELOPMENT_TEAM = K4E5BZMM4V;
|
||||||
ENABLE_PREVIEWS = YES;
|
ENABLE_PREVIEWS = YES;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = "Pedi Foods";
|
INFOPLIST_KEY_CFBundleDisplayName = "Pedi Foods";
|
||||||
@@ -206,7 +208,7 @@
|
|||||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = UIInterfaceOrientationPortrait;
|
||||||
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
|
LD_RUNPATH_SEARCH_PATHS = "@executable_path/Frameworks";
|
||||||
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
"LD_RUNPATH_SEARCH_PATHS[sdk=macosx*]" = "@executable_path/../Frameworks";
|
||||||
PROVISIONING_PROFILE_SPECIFIER = "com.br.pedifoods.app AppStore";
|
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||||
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
|
||||||
SUPPORTS_MACCATALYST = NO;
|
SUPPORTS_MACCATALYST = NO;
|
||||||
TARGETED_DEVICE_FAMILY = 1;
|
TARGETED_DEVICE_FAMILY = 1;
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ actor GuestSessionService {
|
|||||||
|
|
||||||
#if os(iOS)
|
#if os(iOS)
|
||||||
private func refreshTokenWithAppAttest() async throws -> String {
|
private func refreshTokenWithAppAttest() async throws -> String {
|
||||||
|
print("[GuestSessionService] DCAppAttestService.isSupported = \(DCAppAttestService.shared.isSupported), existingKeyId = \(store.appAttestKeyId ?? "nil")")
|
||||||
guard DCAppAttestService.shared.isSupported else {
|
guard DCAppAttestService.shared.isSupported else {
|
||||||
// Simulator can never support App Attest (hardware limitation,
|
// Simulator can never support App Attest (hardware limitation,
|
||||||
// not environment-specific) — server has its own documented
|
// not environment-specific) — server has its own documented
|
||||||
@@ -112,6 +113,15 @@ actor GuestSessionService {
|
|||||||
// other error (network blip, timeout, decode issue) must
|
// other error (network blip, timeout, decode issue) must
|
||||||
// NOT wipe a perfectly valid registered key.
|
// NOT wipe a perfectly valid registered key.
|
||||||
store.appAttestKeyId = nil
|
store.appAttestKeyId = nil
|
||||||
|
} catch let error as DCError {
|
||||||
|
// DeviceCheck itself rejects the key locally (e.g. the app
|
||||||
|
// was reinstalled and the Secure Enclave key backing this
|
||||||
|
// keyId no longer exists) - distinct from the server
|
||||||
|
// rejecting it, but equally unrecoverable without a fresh
|
||||||
|
// key. Without this, generateAssertion fails the same way
|
||||||
|
// forever since appAttestKeyId is never cleared.
|
||||||
|
print("[GuestSessionService] existing key rejected locally, re-attesting with a fresh key: \(error)")
|
||||||
|
store.appAttestKeyId = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,9 +151,22 @@ actor GuestSessionService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func handshakeWithFreshAttestation(challenge: String) async throws -> String {
|
private func handshakeWithFreshAttestation(challenge: String) async throws -> String {
|
||||||
let keyId = try await DCAppAttestService.shared.generateKey()
|
let keyId: String
|
||||||
|
do {
|
||||||
|
keyId = try await DCAppAttestService.shared.generateKey()
|
||||||
|
} catch {
|
||||||
|
print("[GuestSessionService] generateKey failed: \(error)")
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
let clientDataHash = Data(SHA256.hash(data: Data(challenge.utf8)))
|
let clientDataHash = Data(SHA256.hash(data: Data(challenge.utf8)))
|
||||||
let attestationObject = try await DCAppAttestService.shared.attestKey(keyId, clientDataHash: clientDataHash)
|
let attestationObject: Data
|
||||||
|
do {
|
||||||
|
attestationObject = try await DCAppAttestService.shared.attestKey(keyId, clientDataHash: clientDataHash)
|
||||||
|
} catch {
|
||||||
|
print("[GuestSessionService] attestKey failed: \(error)")
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
let payload = GuestSessionAttestPayload(
|
let payload = GuestSessionAttestPayload(
|
||||||
platform: "ios",
|
platform: "ios",
|
||||||
@@ -175,7 +198,13 @@ actor GuestSessionService {
|
|||||||
|
|
||||||
private func handshakeWithAssertion(keyId: String, challenge: String) async throws -> String {
|
private func handshakeWithAssertion(keyId: String, challenge: String) async throws -> String {
|
||||||
let clientDataHash = Data(SHA256.hash(data: Data(challenge.utf8)))
|
let clientDataHash = Data(SHA256.hash(data: Data(challenge.utf8)))
|
||||||
let assertionObject = try await DCAppAttestService.shared.generateAssertion(keyId, clientDataHash: clientDataHash)
|
let assertionObject: Data
|
||||||
|
do {
|
||||||
|
assertionObject = try await DCAppAttestService.shared.generateAssertion(keyId, clientDataHash: clientDataHash)
|
||||||
|
} catch {
|
||||||
|
print("[GuestSessionService] generateAssertion failed: \(error)")
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
|
||||||
let payload = GuestSessionAttestPayload(
|
let payload = GuestSessionAttestPayload(
|
||||||
platform: "ios",
|
platform: "ios",
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ struct PublicLocationPickerView: View {
|
|||||||
errorMessage = "Nenhum estado disponível no momento."
|
errorMessage = "Nenhum estado disponível no momento."
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
|
print("[PublicLocationPickerView] loadLocations failed: \(error)")
|
||||||
errorMessage = "Não foi possível carregar. Tente novamente."
|
errorMessage = "Não foi possível carregar. Tente novamente."
|
||||||
}
|
}
|
||||||
isLoading = false
|
isLoading = false
|
||||||
|
|||||||
Reference in New Issue
Block a user