Selaa lähdekoodia

Add SPM sample project for App Check (#339)

mdmathias 2 vuotta sitten
vanhempi
sitoutus
cc7491f6d8

+ 32 - 0
.github/workflows/integration_tests.yml

@@ -40,3 +40,35 @@ jobs:
           -destination 'platform=iOS Simulator,name=iPhone 11' \
           EMAIL_SECRET=$EMAIL_SECRET \
           PASSWORD_SECRET=$PASSWORD_SECRET
+
+  app-check-api-token-tests:
+    runs-on: macOS-12
+    # Don't run if triggered by a PR from a fork since our Secrets won't be provided to the runner.
+    if: "!github.event.pull_request.head.repo.fork"
+    defaults:
+      run:
+        working-directory: Samples/Swift/AppAttestExample
+    steps:
+    - name: Checkout
+      uses: actions/checkout@v3
+    - name: Build test target for App Check Example
+      run: |
+        xcodebuild \
+          -project AppAttestExample.xcodeproj \
+          build-for-testing \
+          -scheme AppAttestExample \
+          -sdk iphonesimulator \
+          -destination 'platform=iOS Simulator,name=iPhone 11'
+    - name: Run test target for App Check Example
+      env:
+        AppCheckDebugToken : ${{ secrets.APP_CHECK_DEBUG_TOKEN }}
+        APP_CHECK_WEB_API_KEY : ${{ secrets.APP_CHECK_WEB_API_KEY }}
+      run: |
+        xcodebuild \
+          -project AppAttestExample.xcodeproj \
+          test-without-building \
+          -scheme AppAttestExample \
+          -sdk iphonesimulator \
+          -destination 'platform=iOS Simulator,name=iPhone 11' \
+          AppCheckDebugToken=$AppCheckDebugToken \
+          APP_CHECK_WEB_API_KEY=$APP_CHECK_WEB_API_KEY

+ 0 - 1
.gitignore

@@ -19,4 +19,3 @@ Podfile.lock
 
 # Firebase App Check Example
 **/GoogleService-Info.plist
-**/AppCheckSecrets.xcconfig

+ 1 - 1
Package.swift

@@ -48,7 +48,7 @@ let package = Package(
     .package(
       name: "AppCheck",
       url: "https://github.com/google/app-check.git",
-      .branch("CocoaPods-0.1.0-alpha.6")),
+      .branch("CocoaPods-0.1.0-alpha.9")),
     .package(
       name: "GTMAppAuth",
       url: "https://github.com/google/GTMAppAuth.git",

+ 168 - 55
Samples/Swift/AppAttestExample/AppAttestExample.xcodeproj/project.pbxproj

@@ -7,18 +7,32 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
-		4D8DB53AAE2F7D0055DCEA7F /* Pods_AppAttestExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 91F3A930BB86D9E0648046BC /* Pods_AppAttestExample.framework */; };
+		73080B2B2AAF9BDE00DEF667 /* AppAttestExampleTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73080B2A2AAF9BDE00DEF667 /* AppAttestExampleTests.swift */; };
+		73080B392AAF9F1400DEF667 /* GoogleSignIn in Frameworks */ = {isa = PBXBuildFile; productRef = 73080B382AAF9F1400DEF667 /* GoogleSignIn */; };
 		738B4A322AA8FE800056885D /* AppCheckSecretReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 738B4A312AA8FE800056885D /* AppCheckSecretReader.swift */; };
 		738D5F732A26BC3B00A7F11B /* BirthdayLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 738D5F722A26BC3B00A7F11B /* BirthdayLoader.swift */; };
 		73A464042A1C3B3400BA8528 /* AppAttestExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73A464032A1C3B3400BA8528 /* AppAttestExampleApp.swift */; };
 		73A464062A1C3B3400BA8528 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73A464052A1C3B3400BA8528 /* ContentView.swift */; };
 		73A4640B2A1C3B3500BA8528 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 73A4640A2A1C3B3500BA8528 /* Preview Assets.xcassets */; };
+		73CD4AB22AAF915900642462 /* GoogleSignIn in Frameworks */ = {isa = PBXBuildFile; productRef = 73CD4AB12AAF915900642462 /* GoogleSignIn */; };
+		73CD4AB42AAF915F00642462 /* GoogleSignInSwift in Frameworks */ = {isa = PBXBuildFile; productRef = 73CD4AB32AAF915F00642462 /* GoogleSignInSwift */; };
 /* End PBXBuildFile section */
 
+/* Begin PBXContainerItemProxy section */
+		73080B352AAF9EAD00DEF667 /* PBXContainerItemProxy */ = {
+			isa = PBXContainerItemProxy;
+			containerPortal = 73A463F82A1C3B3400BA8528 /* Project object */;
+			proxyType = 1;
+			remoteGlobalIDString = 73A463FF2A1C3B3400BA8528;
+			remoteInfo = AppAttestExample;
+		};
+/* End PBXContainerItemProxy section */
+
 /* Begin PBXFileReference section */
-		1C96B5B2B34E31F1A1CEE95E /* Pods-AppAttestExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppAttestExample.release.xcconfig"; path = "Target Support Files/Pods-AppAttestExample/Pods-AppAttestExample.release.xcconfig"; sourceTree = "<group>"; };
+		73080B282AAF9BDE00DEF667 /* AppAttestExampleTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AppAttestExampleTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
+		73080B2A2AAF9BDE00DEF667 /* AppAttestExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAttestExampleTests.swift; sourceTree = "<group>"; };
 		73443A232A55F56900A4932E /* AppAttestExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AppAttestExample.entitlements; sourceTree = "<group>"; };
-		738B4A302AA7EB840056885D /* AppCheckSecrets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppCheckSecrets.xcconfig; sourceTree = "<group>"; };
+		734555752AB167B80068F2B0 /* AppCheckDefaultSecrets.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppCheckDefaultSecrets.xcconfig; sourceTree = "<group>"; };
 		738B4A312AA8FE800056885D /* AppCheckSecretReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCheckSecretReader.swift; sourceTree = "<group>"; };
 		738D5F722A26BC3B00A7F11B /* BirthdayLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BirthdayLoader.swift; sourceTree = "<group>"; };
 		73A065612A786D10007BC7FC /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -26,37 +40,56 @@
 		73A464032A1C3B3400BA8528 /* AppAttestExampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAttestExampleApp.swift; sourceTree = "<group>"; };
 		73A464052A1C3B3400BA8528 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
 		73A4640A2A1C3B3500BA8528 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
-		7D9832F2FFAF408698660CA8 /* Pods-AppAttestExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppAttestExample.debug.xcconfig"; path = "Target Support Files/Pods-AppAttestExample/Pods-AppAttestExample.debug.xcconfig"; sourceTree = "<group>"; };
+		73CD4AB02AAF8C8500642462 /* GoogleSignIn-iOS */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = "GoogleSignIn-iOS"; path = ../../..; sourceTree = "<group>"; };
+		73D87D512AAFE0FE002D841C /* AppAttestExample.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = AppAttestExample.xctestplan; sourceTree = "<group>"; };
 		91F3A930BB86D9E0648046BC /* Pods_AppAttestExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AppAttestExample.framework; sourceTree = BUILT_PRODUCTS_DIR; };
 /* End PBXFileReference section */
 
 /* Begin PBXFrameworksBuildPhase section */
+		73080B252AAF9BDE00DEF667 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				73080B392AAF9F1400DEF667 /* GoogleSignIn in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
 		73A463FD2A1C3B3400BA8528 /* Frameworks */ = {
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				4D8DB53AAE2F7D0055DCEA7F /* Pods_AppAttestExample.framework in Frameworks */,
+				73CD4AB22AAF915900642462 /* GoogleSignIn in Frameworks */,
+				73CD4AB42AAF915F00642462 /* GoogleSignInSwift in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
 /* End PBXFrameworksBuildPhase section */
 
 /* Begin PBXGroup section */
-		6B1005926777EEB3C903F93A /* Pods */ = {
+		73080B292AAF9BDE00DEF667 /* AppAttestExampleTests */ = {
 			isa = PBXGroup;
 			children = (
-				7D9832F2FFAF408698660CA8 /* Pods-AppAttestExample.debug.xcconfig */,
-				1C96B5B2B34E31F1A1CEE95E /* Pods-AppAttestExample.release.xcconfig */,
+				73080B2A2AAF9BDE00DEF667 /* AppAttestExampleTests.swift */,
 			);
-			path = Pods;
+			path = AppAttestExampleTests;
+			sourceTree = "<group>";
+		};
+		7345556B2AB127B00068F2B0 /* Secrets */ = {
+			isa = PBXGroup;
+			children = (
+				734555752AB167B80068F2B0 /* AppCheckDefaultSecrets.xcconfig */,
+			);
+			path = Secrets;
 			sourceTree = "<group>";
 		};
 		73A463F72A1C3B3400BA8528 = {
 			isa = PBXGroup;
 			children = (
+				73D87D512AAFE0FE002D841C /* AppAttestExample.xctestplan */,
+				73CD4AAF2AAF8C8500642462 /* Packages */,
 				73A464022A1C3B3400BA8528 /* AppAttestExample */,
+				73080B292AAF9BDE00DEF667 /* AppAttestExampleTests */,
 				73A464012A1C3B3400BA8528 /* Products */,
-				6B1005926777EEB3C903F93A /* Pods */,
 				A73FBC2B93918F4B411815A1 /* Frameworks */,
 			);
 			sourceTree = "<group>";
@@ -65,6 +98,7 @@
 			isa = PBXGroup;
 			children = (
 				73A464002A1C3B3400BA8528 /* AppAttestExample.app */,
+				73080B282AAF9BDE00DEF667 /* AppAttestExampleTests.xctest */,
 			);
 			name = Products;
 			sourceTree = "<group>";
@@ -77,7 +111,7 @@
 				73A464052A1C3B3400BA8528 /* ContentView.swift */,
 				738D5F722A26BC3B00A7F11B /* BirthdayLoader.swift */,
 				738B4A312AA8FE800056885D /* AppCheckSecretReader.swift */,
-				738B4A302AA7EB840056885D /* AppCheckSecrets.xcconfig */,
+				7345556B2AB127B00068F2B0 /* Secrets */,
 				73A065612A786D10007BC7FC /* Info.plist */,
 				73A464092A1C3B3500BA8528 /* Preview Content */,
 			);
@@ -92,6 +126,14 @@
 			path = "Preview Content";
 			sourceTree = "<group>";
 		};
+		73CD4AAF2AAF8C8500642462 /* Packages */ = {
+			isa = PBXGroup;
+			children = (
+				73CD4AB02AAF8C8500642462 /* GoogleSignIn-iOS */,
+			);
+			name = Packages;
+			sourceTree = "<group>";
+		};
 		A73FBC2B93918F4B411815A1 /* Frameworks */ = {
 			isa = PBXGroup;
 			children = (
@@ -103,21 +145,44 @@
 /* End PBXGroup section */
 
 /* Begin PBXNativeTarget section */
+		73080B272AAF9BDE00DEF667 /* AppAttestExampleTests */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 73080B302AAF9BDE00DEF667 /* Build configuration list for PBXNativeTarget "AppAttestExampleTests" */;
+			buildPhases = (
+				73080B242AAF9BDE00DEF667 /* Sources */,
+				73080B252AAF9BDE00DEF667 /* Frameworks */,
+				73080B262AAF9BDE00DEF667 /* Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+				73080B362AAF9EAD00DEF667 /* PBXTargetDependency */,
+			);
+			name = AppAttestExampleTests;
+			packageProductDependencies = (
+				73080B382AAF9F1400DEF667 /* GoogleSignIn */,
+			);
+			productName = AppAttestExampleTests;
+			productReference = 73080B282AAF9BDE00DEF667 /* AppAttestExampleTests.xctest */;
+			productType = "com.apple.product-type.bundle.unit-test";
+		};
 		73A463FF2A1C3B3400BA8528 /* AppAttestExample */ = {
 			isa = PBXNativeTarget;
 			buildConfigurationList = 73A4640E2A1C3B3500BA8528 /* Build configuration list for PBXNativeTarget "AppAttestExample" */;
 			buildPhases = (
-				D6AEC62E9810AEFD4C28F50F /* [CP] Check Pods Manifest.lock */,
 				73A463FC2A1C3B3400BA8528 /* Sources */,
 				73A463FD2A1C3B3400BA8528 /* Frameworks */,
 				73A463FE2A1C3B3400BA8528 /* Resources */,
-				C031D9D83F25CB0CD2512F23 /* [CP] Copy Pods Resources */,
 			);
 			buildRules = (
 			);
 			dependencies = (
 			);
 			name = AppAttestExample;
+			packageProductDependencies = (
+				73CD4AB12AAF915900642462 /* GoogleSignIn */,
+				73CD4AB32AAF915F00642462 /* GoogleSignInSwift */,
+			);
 			productName = AppAttestExample;
 			productReference = 73A464002A1C3B3400BA8528 /* AppAttestExample.app */;
 			productType = "com.apple.product-type.application";
@@ -132,6 +197,10 @@
 				LastSwiftUpdateCheck = 1430;
 				LastUpgradeCheck = 1430;
 				TargetAttributes = {
+					73080B272AAF9BDE00DEF667 = {
+						CreatedOnToolsVersion = 14.3;
+						TestTargetID = 73A463FF2A1C3B3400BA8528;
+					};
 					73A463FF2A1C3B3400BA8528 = {
 						CreatedOnToolsVersion = 14.3;
 					};
@@ -151,64 +220,38 @@
 			projectRoot = "";
 			targets = (
 				73A463FF2A1C3B3400BA8528 /* AppAttestExample */,
+				73080B272AAF9BDE00DEF667 /* AppAttestExampleTests */,
 			);
 		};
 /* End PBXProject section */
 
 /* Begin PBXResourcesBuildPhase section */
-		73A463FE2A1C3B3400BA8528 /* Resources */ = {
+		73080B262AAF9BDE00DEF667 /* Resources */ = {
 			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				73A4640B2A1C3B3500BA8528 /* Preview Assets.xcassets in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXShellScriptBuildPhase section */
-		C031D9D83F25CB0CD2512F23 /* [CP] Copy Pods Resources */ = {
-			isa = PBXShellScriptBuildPhase;
+		73A463FE2A1C3B3400BA8528 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-			);
-			inputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-AppAttestExample/Pods-AppAttestExample-resources-${CONFIGURATION}-input-files.xcfilelist",
-			);
-			name = "[CP] Copy Pods Resources";
-			outputFileListPaths = (
-				"${PODS_ROOT}/Target Support Files/Pods-AppAttestExample/Pods-AppAttestExample-resources-${CONFIGURATION}-output-files.xcfilelist",
+				73A4640B2A1C3B3500BA8528 /* Preview Assets.xcassets in Resources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AppAttestExample/Pods-AppAttestExample-resources.sh\"\n";
-			showEnvVarsInLog = 0;
 		};
-		D6AEC62E9810AEFD4C28F50F /* [CP] Check Pods Manifest.lock */ = {
-			isa = PBXShellScriptBuildPhase;
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		73080B242AAF9BDE00DEF667 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-			);
-			inputFileListPaths = (
-			);
-			inputPaths = (
-				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
-				"${PODS_ROOT}/Manifest.lock",
-			);
-			name = "[CP] Check Pods Manifest.lock";
-			outputFileListPaths = (
-			);
-			outputPaths = (
-				"$(DERIVED_FILE_DIR)/Pods-AppAttestExample-checkManifestLockResult.txt",
+				73080B2B2AAF9BDE00DEF667 /* AppAttestExampleTests.swift in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
-			shellPath = /bin/sh;
-			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
-			showEnvVarsInLog = 0;
 		};
-/* End PBXShellScriptBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
 		73A463FC2A1C3B3400BA8528 /* Sources */ = {
 			isa = PBXSourcesBuildPhase;
 			buildActionMask = 2147483647;
@@ -222,10 +265,54 @@
 		};
 /* End PBXSourcesBuildPhase section */
 
+/* Begin PBXTargetDependency section */
+		73080B362AAF9EAD00DEF667 /* PBXTargetDependency */ = {
+			isa = PBXTargetDependency;
+			target = 73A463FF2A1C3B3400BA8528 /* AppAttestExample */;
+			targetProxy = 73080B352AAF9EAD00DEF667 /* PBXContainerItemProxy */;
+		};
+/* End PBXTargetDependency section */
+
 /* Begin XCBuildConfiguration section */
+		73080B2E2AAF9BDE00DEF667 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				CODE_SIGN_STYLE = Automatic;
+				CURRENT_PROJECT_VERSION = 1;
+				GENERATE_INFOPLIST_FILE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
+				MARKETING_VERSION = 1.0;
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.AppAttestExampleTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_EMIT_LOC_STRINGS = NO;
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AppAttestExample.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/AppAttestExample";
+			};
+			name = Debug;
+		};
+		73080B2F2AAF9BDE00DEF667 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				BUNDLE_LOADER = "$(TEST_HOST)";
+				CODE_SIGN_STYLE = Automatic;
+				CURRENT_PROJECT_VERSION = 1;
+				GENERATE_INFOPLIST_FILE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
+				MARKETING_VERSION = 1.0;
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.AppAttestExampleTests;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				SWIFT_EMIT_LOC_STRINGS = NO;
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = "1,2";
+				TEST_HOST = "$(BUILT_PRODUCTS_DIR)/AppAttestExample.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/AppAttestExample";
+			};
+			name = Release;
+		};
 		73A4640C2A1C3B3500BA8528 /* Debug */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 738B4A302AA7EB840056885D /* AppCheckSecrets.xcconfig */;
+			baseConfigurationReference = 734555752AB167B80068F2B0 /* AppCheckDefaultSecrets.xcconfig */;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
 				CLANG_ANALYZER_NONNULL = YES;
@@ -275,7 +362,7 @@
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				INFOPLIST_FILE = "";
-				IPHONEOS_DEPLOYMENT_TARGET = 16.4;
+				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
 				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
 				MTL_FAST_MATH = YES;
 				ONLY_ACTIVE_ARCH = YES;
@@ -330,7 +417,7 @@
 				GCC_WARN_UNUSED_FUNCTION = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				INFOPLIST_FILE = "";
-				IPHONEOS_DEPLOYMENT_TARGET = 16.4;
+				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
 				MTL_ENABLE_DEBUG_INFO = NO;
 				MTL_FAST_MATH = YES;
 				SDKROOT = iphoneos;
@@ -342,7 +429,6 @@
 		};
 		73A4640F2A1C3B3500BA8528 /* Debug */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 7D9832F2FFAF408698660CA8 /* Pods-AppAttestExample.debug.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
@@ -355,6 +441,7 @@
 				DEVELOPMENT_TEAM = "";
 				"DEVELOPMENT_TEAM[sdk=iphoneos*]" = EQHXZ8M8AV;
 				ENABLE_PREVIEWS = YES;
+				ENABLE_TESTING_SEARCH_PATHS = NO;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AppAttestExample/Info.plist;
 				INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
@@ -362,6 +449,7 @@
 				INFOPLIST_KEY_UILaunchScreen_Generation = YES;
 				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
 				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
 					"@executable_path/Frameworks",
@@ -379,7 +467,6 @@
 		};
 		73A464102A1C3B3500BA8528 /* Release */ = {
 			isa = XCBuildConfiguration;
-			baseConfigurationReference = 1C96B5B2B34E31F1A1CEE95E /* Pods-AppAttestExample.release.xcconfig */;
 			buildSettings = {
 				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
 				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
@@ -392,6 +479,7 @@
 				DEVELOPMENT_TEAM = "";
 				"DEVELOPMENT_TEAM[sdk=iphoneos*]" = EQHXZ8M8AV;
 				ENABLE_PREVIEWS = YES;
+				ENABLE_TESTING_SEARCH_PATHS = NO;
 				GENERATE_INFOPLIST_FILE = YES;
 				INFOPLIST_FILE = AppAttestExample/Info.plist;
 				INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
@@ -399,6 +487,7 @@
 				INFOPLIST_KEY_UILaunchScreen_Generation = YES;
 				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
 				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
 				LD_RUNPATH_SEARCH_PATHS = (
 					"$(inherited)",
 					"@executable_path/Frameworks",
@@ -417,6 +506,15 @@
 /* End XCBuildConfiguration section */
 
 /* Begin XCConfigurationList section */
+		73080B302AAF9BDE00DEF667 /* Build configuration list for PBXNativeTarget "AppAttestExampleTests" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				73080B2E2AAF9BDE00DEF667 /* Debug */,
+				73080B2F2AAF9BDE00DEF667 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
 		73A463FB2A1C3B3400BA8528 /* Build configuration list for PBXProject "AppAttestExample" */ = {
 			isa = XCConfigurationList;
 			buildConfigurations = (
@@ -436,6 +534,21 @@
 			defaultConfigurationName = Release;
 		};
 /* End XCConfigurationList section */
+
+/* Begin XCSwiftPackageProductDependency section */
+		73080B382AAF9F1400DEF667 /* GoogleSignIn */ = {
+			isa = XCSwiftPackageProductDependency;
+			productName = GoogleSignIn;
+		};
+		73CD4AB12AAF915900642462 /* GoogleSignIn */ = {
+			isa = XCSwiftPackageProductDependency;
+			productName = GoogleSignIn;
+		};
+		73CD4AB32AAF915F00642462 /* GoogleSignInSwift */ = {
+			isa = XCSwiftPackageProductDependency;
+			productName = GoogleSignInSwift;
+		};
+/* End XCSwiftPackageProductDependency section */
 	};
 	rootObject = 73A463F82A1C3B3400BA8528 /* Project object */;
 }

+ 20 - 2
Samples/Swift/AppAttestExample/AppAttestExample.xcodeproj/xcshareddata/xcschemes/AppAttestExample.xcscheme

@@ -26,8 +26,26 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      shouldUseLaunchSchemeArgsEnv = "YES"
-      shouldAutocreateTestPlan = "YES">
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <TestPlans>
+         <TestPlanReference
+            reference = "container:AppAttestExample.xctestplan"
+            default = "YES">
+         </TestPlanReference>
+      </TestPlans>
+      <Testables>
+         <TestableReference
+            skipped = "NO"
+            parallelizable = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "73080B272AAF9BDE00DEF667"
+               BuildableName = "AppAttestExampleTests.xctest"
+               BlueprintName = "AppAttestExampleTests"
+               ReferencedContainer = "container:AppAttestExample.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+      </Testables>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"

+ 40 - 0
Samples/Swift/AppAttestExample/AppAttestExample.xctestplan

@@ -0,0 +1,40 @@
+{
+  "configurations" : [
+    {
+      "id" : "BE893D88-5ECF-4AF1-95E1-CE186B02A525",
+      "name" : "Test Scheme Action",
+      "options" : {
+
+      }
+    }
+  ],
+  "defaultOptions" : {
+    "codeCoverage" : false,
+    "environmentVariableEntries" : [
+      {
+        "key" : "AppCheckDebugToken",
+        "value" : "$(AppCheckDebugToken)"
+      },
+      {
+        "key" : "APP_CHECK_WEB_API_KEY",
+        "value" : "$(APP_CHECK_WEB_API_KEY)"
+      }
+    ],
+    "targetForVariableExpansion" : {
+      "containerPath" : "container:AppAttestExample.xcodeproj",
+      "identifier" : "73080B272AAF9BDE00DEF667",
+      "name" : "AppAttestExampleTests"
+    }
+  },
+  "testTargets" : [
+    {
+      "parallelizable" : true,
+      "target" : {
+        "containerPath" : "container:AppAttestExample.xcodeproj",
+        "identifier" : "73080B272AAF9BDE00DEF667",
+        "name" : "AppAttestExampleTests"
+      }
+    }
+  ],
+  "version" : 1
+}

+ 16 - 2
Samples/Swift/AppAttestExample/AppAttestExample/AppCheckSecretReader.swift

@@ -18,7 +18,21 @@ import Foundation
 
 struct AppCheckSecretReader {
   private let APIKeyName = "APP_CHECK_WEB_API_KEY"
+  private let APIKeyResourceName = "AppCheckSecrets"
+  private let APIKeyExtensionName = "json"
+  private let debugTokenName = "AppCheckDebugToken"
 
+  /// Method to read the App Check debug token from the environment
+  var debugToken: String? {
+    guard let debugToken = ProcessInfo.processInfo.environment[debugTokenName],
+          !debugToken.isEmpty else {
+      print("Failed to get \(debugTokenName) from environment.")
+      return nil
+    }
+    return debugToken
+  }
+
+  /// Method to read the App Check API key from either the bundle or the environment
   var APIKey: String? {
     return APIKeyFromBundle ?? APIKeyFromEnvironment
   }
@@ -34,9 +48,9 @@ struct AppCheckSecretReader {
 
   /// Method for retrieving API key from the bundle during simulator or debug builds
   private var APIKeyFromBundle: String? {
-    guard let APIKey = Bundle.main.infoDictionary?[APIKeyName] as? String,
+    guard let APIKey = Bundle.main.object(forInfoDictionaryKey: APIKeyName) as? String,
           !APIKey.isEmpty else {
-      print("Failed to get \(APIKeyName) from Bundle.")
+      print("Failed to get \(APIKeyName) from environment.")
       return nil
     }
     return APIKey

+ 16 - 0
Samples/Swift/AppAttestExample/AppAttestExample/Secrets/AppCheckDefaultSecrets.xcconfig

@@ -0,0 +1,16 @@
+//
+// Copyright 2023 Google LLC
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+APP_CHECK_WEB_API_KEY=

+ 474 - 0
Samples/Swift/AppAttestExample/AppAttestExampleForPod.xcodeproj/project.pbxproj

@@ -0,0 +1,474 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 56;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		7345556F2AB142B40068F2B0 /* AppCheckDefaultSecrets.json in Resources */ = {isa = PBXBuildFile; fileRef = 7345556D2AB142B40068F2B0 /* AppCheckDefaultSecrets.json */; };
+		734555702AB142B40068F2B0 /* AppCheckSecrets.json in Resources */ = {isa = PBXBuildFile; fileRef = 7345556E2AB142B40068F2B0 /* AppCheckSecrets.json */; };
+		738B4A322AA8FE800056885D /* AppCheckSecretReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 738B4A312AA8FE800056885D /* AppCheckSecretReader.swift */; };
+		738D5F732A26BC3B00A7F11B /* BirthdayLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 738D5F722A26BC3B00A7F11B /* BirthdayLoader.swift */; };
+		73A464042A1C3B3400BA8528 /* AppAttestExampleApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73A464032A1C3B3400BA8528 /* AppAttestExampleApp.swift */; };
+		73A464062A1C3B3400BA8528 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73A464052A1C3B3400BA8528 /* ContentView.swift */; };
+		73A4640B2A1C3B3500BA8528 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 73A4640A2A1C3B3500BA8528 /* Preview Assets.xcassets */; };
+		D8DD1A90FCD4C367E280C0F7 /* Pods_AppAttestExampleForPod.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4728D878D216B7D622E237DA /* Pods_AppAttestExampleForPod.framework */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		1C96B5B2B34E31F1A1CEE95E /* Pods-AppAttestExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppAttestExample.release.xcconfig"; path = "Target Support Files/Pods-AppAttestExample/Pods-AppAttestExample.release.xcconfig"; sourceTree = "<group>"; };
+		4728D878D216B7D622E237DA /* Pods_AppAttestExampleForPod.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_AppAttestExampleForPod.framework; sourceTree = BUILT_PRODUCTS_DIR; };
+		73080B2A2AAF9BDE00DEF667 /* AppAttestExampleTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAttestExampleTests.swift; sourceTree = "<group>"; };
+		73443A232A55F56900A4932E /* AppAttestExample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AppAttestExample.entitlements; sourceTree = "<group>"; };
+		7345556D2AB142B40068F2B0 /* AppCheckDefaultSecrets.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = AppCheckDefaultSecrets.json; sourceTree = "<group>"; };
+		7345556E2AB142B40068F2B0 /* AppCheckSecrets.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = AppCheckSecrets.json; sourceTree = "<group>"; };
+		738B4A312AA8FE800056885D /* AppCheckSecretReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppCheckSecretReader.swift; sourceTree = "<group>"; };
+		738D5F722A26BC3B00A7F11B /* BirthdayLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BirthdayLoader.swift; sourceTree = "<group>"; };
+		73A065612A786D10007BC7FC /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+		73A464002A1C3B3400BA8528 /* AppAttestExampleForPod.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AppAttestExampleForPod.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		73A464032A1C3B3400BA8528 /* AppAttestExampleApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppAttestExampleApp.swift; sourceTree = "<group>"; };
+		73A464052A1C3B3400BA8528 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
+		73A4640A2A1C3B3500BA8528 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
+		73D87D512AAFE0FE002D841C /* AppAttestExample.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = AppAttestExample.xctestplan; sourceTree = "<group>"; };
+		7D9832F2FFAF408698660CA8 /* Pods-AppAttestExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppAttestExample.debug.xcconfig"; path = "Target Support Files/Pods-AppAttestExample/Pods-AppAttestExample.debug.xcconfig"; sourceTree = "<group>"; };
+		DB9DDDAE875580597968F796 /* Pods-AppAttestExampleForPod.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppAttestExampleForPod.release.xcconfig"; path = "Target Support Files/Pods-AppAttestExampleForPod/Pods-AppAttestExampleForPod.release.xcconfig"; sourceTree = "<group>"; };
+		E27EB8376FDCD7AB29F8A522 /* Pods-AppAttestExampleForPod.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AppAttestExampleForPod.debug.xcconfig"; path = "Target Support Files/Pods-AppAttestExampleForPod/Pods-AppAttestExampleForPod.debug.xcconfig"; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		73A463FD2A1C3B3400BA8528 /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				D8DD1A90FCD4C367E280C0F7 /* Pods_AppAttestExampleForPod.framework in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		6B1005926777EEB3C903F93A /* Pods */ = {
+			isa = PBXGroup;
+			children = (
+				7D9832F2FFAF408698660CA8 /* Pods-AppAttestExample.debug.xcconfig */,
+				1C96B5B2B34E31F1A1CEE95E /* Pods-AppAttestExample.release.xcconfig */,
+				E27EB8376FDCD7AB29F8A522 /* Pods-AppAttestExampleForPod.debug.xcconfig */,
+				DB9DDDAE875580597968F796 /* Pods-AppAttestExampleForPod.release.xcconfig */,
+			);
+			path = Pods;
+			sourceTree = "<group>";
+		};
+		73080B292AAF9BDE00DEF667 /* AppAttestExampleTests */ = {
+			isa = PBXGroup;
+			children = (
+				73080B2A2AAF9BDE00DEF667 /* AppAttestExampleTests.swift */,
+			);
+			path = AppAttestExampleTests;
+			sourceTree = "<group>";
+		};
+		7345556C2AB142B40068F2B0 /* Secrets */ = {
+			isa = PBXGroup;
+			children = (
+				7345556D2AB142B40068F2B0 /* AppCheckDefaultSecrets.json */,
+				7345556E2AB142B40068F2B0 /* AppCheckSecrets.json */,
+			);
+			path = Secrets;
+			sourceTree = "<group>";
+		};
+		73A463F72A1C3B3400BA8528 = {
+			isa = PBXGroup;
+			children = (
+				73D87D512AAFE0FE002D841C /* AppAttestExample.xctestplan */,
+				73A464022A1C3B3400BA8528 /* AppAttestExample */,
+				73080B292AAF9BDE00DEF667 /* AppAttestExampleTests */,
+				73A464012A1C3B3400BA8528 /* Products */,
+				6B1005926777EEB3C903F93A /* Pods */,
+				A73FBC2B93918F4B411815A1 /* Frameworks */,
+			);
+			sourceTree = "<group>";
+		};
+		73A464012A1C3B3400BA8528 /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				73A464002A1C3B3400BA8528 /* AppAttestExampleForPod.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		73A464022A1C3B3400BA8528 /* AppAttestExample */ = {
+			isa = PBXGroup;
+			children = (
+				73443A232A55F56900A4932E /* AppAttestExample.entitlements */,
+				73A464032A1C3B3400BA8528 /* AppAttestExampleApp.swift */,
+				73A464052A1C3B3400BA8528 /* ContentView.swift */,
+				738D5F722A26BC3B00A7F11B /* BirthdayLoader.swift */,
+				738B4A312AA8FE800056885D /* AppCheckSecretReader.swift */,
+				7345556C2AB142B40068F2B0 /* Secrets */,
+				73A065612A786D10007BC7FC /* Info.plist */,
+				73A464092A1C3B3500BA8528 /* Preview Content */,
+			);
+			path = AppAttestExample;
+			sourceTree = "<group>";
+		};
+		73A464092A1C3B3500BA8528 /* Preview Content */ = {
+			isa = PBXGroup;
+			children = (
+				73A4640A2A1C3B3500BA8528 /* Preview Assets.xcassets */,
+			);
+			path = "Preview Content";
+			sourceTree = "<group>";
+		};
+		A73FBC2B93918F4B411815A1 /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				4728D878D216B7D622E237DA /* Pods_AppAttestExampleForPod.framework */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		73A463FF2A1C3B3400BA8528 /* AppAttestExampleForPod */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 73A4640E2A1C3B3500BA8528 /* Build configuration list for PBXNativeTarget "AppAttestExampleForPod" */;
+			buildPhases = (
+				55BC416D6BAEAFD4409866C8 /* [CP] Check Pods Manifest.lock */,
+				73A463FC2A1C3B3400BA8528 /* Sources */,
+				73A463FD2A1C3B3400BA8528 /* Frameworks */,
+				73A463FE2A1C3B3400BA8528 /* Resources */,
+				D116F83514234BBFA76A4CC4 /* [CP] Copy Pods Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = AppAttestExampleForPod;
+			productName = AppAttestExample;
+			productReference = 73A464002A1C3B3400BA8528 /* AppAttestExampleForPod.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		73A463F82A1C3B3400BA8528 /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				BuildIndependentTargetsInParallel = 1;
+				LastSwiftUpdateCheck = 1430;
+				LastUpgradeCheck = 1430;
+				TargetAttributes = {
+					73A463FF2A1C3B3400BA8528 = {
+						CreatedOnToolsVersion = 14.3;
+					};
+				};
+			};
+			buildConfigurationList = 73A463FB2A1C3B3400BA8528 /* Build configuration list for PBXProject "AppAttestExampleForPod" */;
+			compatibilityVersion = "Xcode 14.0";
+			developmentRegion = en;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+				Base,
+			);
+			mainGroup = 73A463F72A1C3B3400BA8528;
+			productRefGroup = 73A464012A1C3B3400BA8528 /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				73A463FF2A1C3B3400BA8528 /* AppAttestExampleForPod */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		73A463FE2A1C3B3400BA8528 /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				7345556F2AB142B40068F2B0 /* AppCheckDefaultSecrets.json in Resources */,
+				73A4640B2A1C3B3500BA8528 /* Preview Assets.xcassets in Resources */,
+				734555702AB142B40068F2B0 /* AppCheckSecrets.json in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		55BC416D6BAEAFD4409866C8 /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputFileListPaths = (
+			);
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-AppAttestExampleForPod-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
+		D116F83514234BBFA76A4CC4 /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-AppAttestExampleForPod/Pods-AppAttestExampleForPod-resources-${CONFIGURATION}-input-files.xcfilelist",
+			);
+			name = "[CP] Copy Pods Resources";
+			outputFileListPaths = (
+				"${PODS_ROOT}/Target Support Files/Pods-AppAttestExampleForPod/Pods-AppAttestExampleForPod-resources-${CONFIGURATION}-output-files.xcfilelist",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-AppAttestExampleForPod/Pods-AppAttestExampleForPod-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		73A463FC2A1C3B3400BA8528 /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				738D5F732A26BC3B00A7F11B /* BirthdayLoader.swift in Sources */,
+				738B4A322AA8FE800056885D /* AppCheckSecretReader.swift in Sources */,
+				73A464062A1C3B3400BA8528 /* ContentView.swift in Sources */,
+				73A464042A1C3B3400BA8528 /* AppAttestExampleApp.swift in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin XCBuildConfiguration section */
+		73A4640C2A1C3B3500BA8528 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = dwarf;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				INFOPLIST_FILE = "";
+				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
+				MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
+				MTL_FAST_MATH = YES;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+				SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
+				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+			};
+			name = Debug;
+		};
+		73A4640D2A1C3B3500BA8528 /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_NONNULL = YES;
+				CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_ENABLE_OBJC_WEAK = YES;
+				CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_COMMA = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INFINITE_RECURSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+				CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
+				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+				CLANG_WARN_STRICT_PROTOTYPES = YES;
+				CLANG_WARN_SUSPICIOUS_MOVE = YES;
+				CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
+				CLANG_WARN_UNREACHABLE_CODE = YES;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				COPY_PHASE_STRIP = NO;
+				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+				ENABLE_NS_ASSERTIONS = NO;
+				ENABLE_STRICT_OBJC_MSGSEND = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu11;
+				GCC_NO_COMMON_BLOCKS = YES;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				INFOPLIST_FILE = "";
+				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
+				MTL_ENABLE_DEBUG_INFO = NO;
+				MTL_FAST_MATH = YES;
+				SDKROOT = iphoneos;
+				SWIFT_COMPILATION_MODE = wholemodule;
+				SWIFT_OPTIMIZATION_LEVEL = "-O";
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		73A4640F2A1C3B3500BA8528 /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = E27EB8376FDCD7AB29F8A522 /* Pods-AppAttestExampleForPod.debug.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				CODE_SIGN_ENTITLEMENTS = AppAttestExample/AppAttestExample.entitlements;
+				CODE_SIGN_IDENTITY = "Apple Development";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				CODE_SIGN_STYLE = Manual;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_ASSET_PATHS = "\"AppAttestExample/Preview Content\"";
+				DEVELOPMENT_TEAM = "";
+				"DEVELOPMENT_TEAM[sdk=iphoneos*]" = EQHXZ8M8AV;
+				ENABLE_PREVIEWS = YES;
+				ENABLE_TESTING_SEARCH_PATHS = NO;
+				GENERATE_INFOPLIST_FILE = YES;
+				INFOPLIST_FILE = AppAttestExample/Info.plist;
+				INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
+				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+				INFOPLIST_KEY_UILaunchScreen_Generation = YES;
+				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				MARKETING_VERSION = 1.0;
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.experimental0.dev;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE_SPECIFIER = "";
+				"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Experimental App 0 Dev";
+				SWIFT_EMIT_LOC_STRINGS = YES;
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Debug;
+		};
+		73A464102A1C3B3500BA8528 /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = DB9DDDAE875580597968F796 /* Pods-AppAttestExampleForPod.release.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
+				CODE_SIGN_ENTITLEMENTS = AppAttestExample/AppAttestExample.entitlements;
+				CODE_SIGN_IDENTITY = "Apple Development";
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				CODE_SIGN_STYLE = Manual;
+				CURRENT_PROJECT_VERSION = 1;
+				DEVELOPMENT_ASSET_PATHS = "\"AppAttestExample/Preview Content\"";
+				DEVELOPMENT_TEAM = "";
+				"DEVELOPMENT_TEAM[sdk=iphoneos*]" = EQHXZ8M8AV;
+				ENABLE_PREVIEWS = YES;
+				ENABLE_TESTING_SEARCH_PATHS = NO;
+				GENERATE_INFOPLIST_FILE = YES;
+				INFOPLIST_FILE = AppAttestExample/Info.plist;
+				INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
+				INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
+				INFOPLIST_KEY_UILaunchScreen_Generation = YES;
+				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
+				IPHONEOS_DEPLOYMENT_TARGET = 16.0;
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+				);
+				MARKETING_VERSION = 1.0;
+				PRODUCT_BUNDLE_IDENTIFIER = com.google.experimental0.dev;
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				PROVISIONING_PROFILE_SPECIFIER = "";
+				"PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "Experimental App 0 Dev";
+				SWIFT_EMIT_LOC_STRINGS = YES;
+				SWIFT_VERSION = 5.0;
+				TARGETED_DEVICE_FAMILY = "1,2";
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		73A463FB2A1C3B3400BA8528 /* Build configuration list for PBXProject "AppAttestExampleForPod" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				73A4640C2A1C3B3500BA8528 /* Debug */,
+				73A4640D2A1C3B3500BA8528 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		73A4640E2A1C3B3500BA8528 /* Build configuration list for PBXNativeTarget "AppAttestExampleForPod" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				73A4640F2A1C3B3500BA8528 /* Debug */,
+				73A464102A1C3B3500BA8528 /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 73A463F82A1C3B3400BA8528 /* Project object */;
+}

+ 113 - 0
Samples/Swift/AppAttestExample/AppAttestExampleForPod.xcodeproj/xcshareddata/xcschemes/AppAttestExample.xcscheme

@@ -0,0 +1,113 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1430"
+   version = "1.7">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "73A463FF2A1C3B3400BA8528"
+               BuildableName = "AppAttestExample.app"
+               BlueprintName = "AppAttestExample"
+               ReferencedContainer = "container:AppAttestExample.xcodeproj">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <TestPlans>
+         <TestPlanReference
+            reference = "container:AppAttestExample.xctestplan"
+            default = "YES">
+         </TestPlanReference>
+      </TestPlans>
+      <Testables>
+         <TestableReference
+            skipped = "NO"
+            parallelizable = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "73080B272AAF9BDE00DEF667"
+               BuildableName = "AppAttestExampleTests.xctest"
+               BlueprintName = "AppAttestExampleTests"
+               ReferencedContainer = "container:AppAttestExample.xcodeproj">
+            </BuildableReference>
+         </TestableReference>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "73A463FF2A1C3B3400BA8528"
+            BuildableName = "AppAttestExampleForPod.app"
+            BlueprintName = "AppAttestExampleForPod"
+            ReferencedContainer = "container:AppAttestExampleForPod.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "73A463FF2A1C3B3400BA8528"
+            BuildableName = "AppAttestExample.app"
+            BlueprintName = "AppAttestExample"
+            ReferencedContainer = "container:AppAttestExample.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <BuildableProductRunnable
+         runnableDebuggingMode = "0">
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "73A463FF2A1C3B3400BA8528"
+            BuildableName = "AppAttestExample.app"
+            BlueprintName = "AppAttestExample"
+            ReferencedContainer = "container:AppAttestExample.xcodeproj">
+         </BuildableReference>
+      </BuildableProductRunnable>
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "73A463FF2A1C3B3400BA8528"
+            BuildableName = "AppAttestExample.app"
+            BlueprintName = "AppAttestExample"
+            ReferencedContainer = "container:AppAttestExample.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>

+ 30 - 0
Samples/Swift/AppAttestExample/AppAttestExampleTests/AppAttestExampleTests.swift

@@ -0,0 +1,30 @@
+/*
+ * Copyright 2023 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import XCTest
+@testable import AppAttestExample
+
+final class AppAttestExampleTests: XCTestCase {
+  func testThatAPIKeyCanBeReadFromBundleOrEnvironment() {
+    let secretsReader = AppCheckSecretReader()
+    XCTAssertNotNil(secretsReader.APIKey)
+  }
+
+  func testThatDebugTokenCanBeReadFromEnvironment() {
+    let secretsReader = AppCheckSecretReader()
+    XCTAssertNotNil(secretsReader.debugToken)
+  }
+}

+ 2 - 2
Samples/Swift/AppAttestExample/Podfile

@@ -3,11 +3,11 @@ source 'https://github.com/firebase/SpecsDev.git'
 
 pod 'GoogleSignIn', :path => '../../../', :testspecs => ['unit']
 pod 'GoogleSignInSwiftSupport', :path => '../../../', :testspecs => ['unit']
-project 'AppAttestExample.xcodeproj'
+project 'AppAttestExampleForPod.xcodeproj'
 
 use_frameworks! :linkage => :static
 
-target 'AppAttestExample' do
+target 'AppAttestExampleForPod' do
   pod 'AppCheckCore'
   platform :ios, '14.0'
 end

+ 60 - 0
Samples/Swift/AppAttestExample/README.md

@@ -0,0 +1,60 @@
+# Google Sign-In with Firebase App Check Sample App
+
+## CocoaPods
+
+1. In the `../Samples/Swift/AppAttestExample/` folder, run the following 
+[CocoaPods](https://cocoapods.org) command.
+
+```
+pod install
+```
+
+2. Open the generated workspace:
+
+```
+open AppAttestExample.xcworkspace
+```
+
+3. Run the `AppAttestExampleForPod` target.
+
+## Swift Package Manager
+
+1. In the `../Samples/Swift/AppAttestExample/` folder, open the project:
+
+```
+open AppAttestExample.xcodeproj
+```
+2. Run the `AppAttestExample` target.
+
+## A Note on Provisioning Profiles
+
+You will need a provisioning profile with the App Attest entitlement.
+
+## Hiding Secrets
+
+This example app shows how you might hide your web API key and debug token
+(used during CI; AppCheckCore manages the debug token running locally in the 
+simulator). Both of these are required. Inside the `Secrets/` directory, we
+include a placeholder file entitled `AppCheckDefaultSecrets.xcconfig`. We have
+also set that as a configuration file for the project, which means that it will
+be used to find the web API key during debug builds on the simulator (for 
+example). You can either make a new file to fill in the stubbed data in
+`AppCheckDefaultSecrets.xcconfig` (which will require that you update where the
+projects finds its configurations), or you can add your API key there yourself.
+Do make sure that you do not commit this API key, or you will risk exposing
+this information on your repository.
+
+In builds running under continuous integration, make sure to use environment
+variables and `AppCheckSecretReader.swift` will find your web API key and debug
+token if you provide them to your `xcodebuild` command.
+
+## Integration Tests
+
+We show how you might hide your app's web API key and debug token when
+running locally and in CI environments. See GitHub's
+[secrets](https://docs.github.com/en/actions/learn-github-actions/contexts#secrets-context)
+documentation for how you might set those values in your repo.
+
+Locally, both the web API key and the debug token need to be passed to 
+`xcodebuild` as arguments: 
+`xcodebuild <other args> APP_CHECK_WEB_API_KEY=... AppCheckDebugToken=...`.