feat: switch login to use xcodesLoginKit

This commit is contained in:
Matt Kiazyk 2025-02-14 11:27:09 -06:00
parent 17f3d365b8
commit 84f1838e60
23 changed files with 163 additions and 192 deletions

View file

@ -3,7 +3,7 @@
archiveVersion = 1; archiveVersion = 1;
classes = { classes = {
}; };
objectVersion = 54; objectVersion = 60;
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
@ -60,7 +60,6 @@
CA9FF8E025959BAA00E47BAF /* ConnectionVerifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF8DF25959BAA00E47BAF /* ConnectionVerifier.swift */; }; CA9FF8E025959BAA00E47BAF /* ConnectionVerifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF8DF25959BAA00E47BAF /* ConnectionVerifier.swift */; };
CA9FF8E625959BB800E47BAF /* AuditTokenHack.m in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF8E525959BB800E47BAF /* AuditTokenHack.m */; }; CA9FF8E625959BB800E47BAF /* AuditTokenHack.m in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF8E525959BB800E47BAF /* AuditTokenHack.m */; };
CA9FF9362595B44700E47BAF /* HelperClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF9352595B44700E47BAF /* HelperClient.swift */; }; CA9FF9362595B44700E47BAF /* HelperClient.swift in Sources */ = {isa = PBXBuildFile; fileRef = CA9FF9352595B44700E47BAF /* HelperClient.swift */; };
CAA1CB2D255A5262003FD669 /* AppleAPI in Frameworks */ = {isa = PBXBuildFile; productRef = CAA1CB2C255A5262003FD669 /* AppleAPI */; };
CAA1CB35255A5AD5003FD669 /* SignInCredentialsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB34255A5AD5003FD669 /* SignInCredentialsView.swift */; }; CAA1CB35255A5AD5003FD669 /* SignInCredentialsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB34255A5AD5003FD669 /* SignInCredentialsView.swift */; };
CAA1CB45255A5B60003FD669 /* SignIn2FAView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB44255A5B60003FD669 /* SignIn2FAView.swift */; }; CAA1CB45255A5B60003FD669 /* SignIn2FAView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB44255A5B60003FD669 /* SignIn2FAView.swift */; };
CAA1CB49255A5C97003FD669 /* SignInSMSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB48255A5C97003FD669 /* SignInSMSView.swift */; }; CAA1CB49255A5C97003FD669 /* SignInSMSView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CAA1CB48255A5C97003FD669 /* SignInSMSView.swift */; };
@ -129,6 +128,8 @@
E87DD6EB25D053FA00D86808 /* Progress+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87DD6EA25D053FA00D86808 /* Progress+.swift */; }; E87DD6EB25D053FA00D86808 /* Progress+.swift in Sources */ = {isa = PBXBuildFile; fileRef = E87DD6EA25D053FA00D86808 /* Progress+.swift */; };
E89342FA25EDCC17007CF557 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E89342F925EDCC17007CF557 /* NotificationManager.swift */; }; E89342FA25EDCC17007CF557 /* NotificationManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E89342F925EDCC17007CF557 /* NotificationManager.swift */; };
E8977EA325C11E1500835F80 /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8977EA225C11E1500835F80 /* PreferencesView.swift */; }; E8977EA325C11E1500835F80 /* PreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8977EA225C11E1500835F80 /* PreferencesView.swift */; };
E89CBD382D5FAB950037ED95 /* XcodesLoginKit in Frameworks */ = {isa = PBXBuildFile; productRef = E89CBD372D5FAB950037ED95 /* XcodesLoginKit */; };
E89CBD3D2D5FB25A0037ED95 /* AppleAPI in Frameworks */ = {isa = PBXBuildFile; productRef = E89CBD3C2D5FB25A0037ED95 /* AppleAPI */; };
E8B20CBF2A2EDEC20057D816 /* SDKs+Xcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8B20CBE2A2EDEC20057D816 /* SDKs+Xcode.swift */; }; E8B20CBF2A2EDEC20057D816 /* SDKs+Xcode.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8B20CBE2A2EDEC20057D816 /* SDKs+Xcode.swift */; };
E8C0EB1A291EF43E0081528A /* XcodesKit in Frameworks */ = {isa = PBXBuildFile; productRef = E8C0EB19291EF43E0081528A /* XcodesKit */; }; E8C0EB1A291EF43E0081528A /* XcodesKit in Frameworks */ = {isa = PBXBuildFile; productRef = E8C0EB19291EF43E0081528A /* XcodesKit */; };
E8C0EB1C291EF9A10081528A /* AppState+Runtimes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8C0EB1B291EF9A10081528A /* AppState+Runtimes.swift */; }; E8C0EB1C291EF9A10081528A /* AppState+Runtimes.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8C0EB1B291EF9A10081528A /* AppState+Runtimes.swift */; };
@ -141,7 +142,6 @@
E8E98A9625D863D700EC89A0 /* InstallationStepDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E98A9525D863D700EC89A0 /* InstallationStepDetailView.swift */; }; E8E98A9625D863D700EC89A0 /* InstallationStepDetailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E8E98A9525D863D700EC89A0 /* InstallationStepDetailView.swift */; };
E8F44A1E296B4CD7002D6592 /* Path in Frameworks */ = {isa = PBXBuildFile; productRef = E8F44A1D296B4CD7002D6592 /* Path */; }; E8F44A1E296B4CD7002D6592 /* Path in Frameworks */ = {isa = PBXBuildFile; productRef = E8F44A1D296B4CD7002D6592 /* Path */; };
E8FA00542B5B109800769CE0 /* com.xcodesorg.xcodesapp.Helper in Copy Helper */ = {isa = PBXBuildFile; fileRef = CA9FF8AE2595967A00E47BAF /* com.xcodesorg.xcodesapp.Helper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; E8FA00542B5B109800769CE0 /* com.xcodesorg.xcodesapp.Helper in Copy Helper */ = {isa = PBXBuildFile; fileRef = CA9FF8AE2595967A00E47BAF /* com.xcodesorg.xcodesapp.Helper */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
E8FD5727291EE4AC001E004C /* AsyncNetworkService in Frameworks */ = {isa = PBXBuildFile; productRef = E8FD5726291EE4AC001E004C /* AsyncNetworkService */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@ -229,7 +229,6 @@
CA452BAF259FD9770072DFA4 /* ProgressIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressIndicator.swift; sourceTree = "<group>"; }; CA452BAF259FD9770072DFA4 /* ProgressIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProgressIndicator.swift; sourceTree = "<group>"; };
CA452BBF259FDDFE0072DFA4 /* Stub-version.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Stub-version.plist"; sourceTree = "<group>"; }; CA452BBF259FDDFE0072DFA4 /* Stub-version.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Stub-version.plist"; sourceTree = "<group>"; };
CA452BEA25A236500072DFA4 /* Stub-0.0.0.Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Stub-0.0.0.Info.plist"; sourceTree = "<group>"; }; CA452BEA25A236500072DFA4 /* Stub-0.0.0.Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Stub-0.0.0.Info.plist"; sourceTree = "<group>"; };
CA538A0C255A4F1A00E64DD7 /* AppleAPI */ = {isa = PBXFileReference; lastKnownFileType = folder; name = AppleAPI; path = Xcodes/AppleAPI; sourceTree = "<group>"; };
CA5D781D257365D6008EDE9D /* PinCodeTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinCodeTextView.swift; sourceTree = "<group>"; }; CA5D781D257365D6008EDE9D /* PinCodeTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PinCodeTextView.swift; sourceTree = "<group>"; };
CA61A6DF259835580008926E /* Xcode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Xcode.swift; sourceTree = "<group>"; }; CA61A6DF259835580008926E /* Xcode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Xcode.swift; sourceTree = "<group>"; };
CA735108257BF96D00EA9CF8 /* AttributedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedText.swift; sourceTree = "<group>"; }; CA735108257BF96D00EA9CF8 /* AttributedText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttributedText.swift; sourceTree = "<group>"; };
@ -358,15 +357,15 @@
33027E342CA8C18800CB387C /* LibFido2Swift in Frameworks */, 33027E342CA8C18800CB387C /* LibFido2Swift in Frameworks */,
CABFA9E42592F08E00380FEE /* Version in Frameworks */, CABFA9E42592F08E00380FEE /* Version in Frameworks */,
CABFA9FD2592F13300380FEE /* LegibleError in Frameworks */, CABFA9FD2592F13300380FEE /* LegibleError in Frameworks */,
E89CBD3D2D5FB25A0037ED95 /* AppleAPI in Frameworks */,
E689540325BE8C64000EBCEA /* DockProgress in Frameworks */, E689540325BE8C64000EBCEA /* DockProgress in Frameworks */,
CA9FF86D25951C6E00E47BAF /* XCModel in Frameworks */, CA9FF86D25951C6E00E47BAF /* XCModel in Frameworks */,
CABFA9F82592F0F900380FEE /* KeychainAccess in Frameworks */, CABFA9F82592F0F900380FEE /* KeychainAccess in Frameworks */,
E83FDC442CBB649100679C6B /* Sparkle in Frameworks */, E83FDC442CBB649100679C6B /* Sparkle in Frameworks */,
E862D43B2CC8B26F00BAA376 /* SRP in Frameworks */, E862D43B2CC8B26F00BAA376 /* SRP in Frameworks */,
CAA858CD25A3D8BC00ACF8C0 /* ErrorHandling in Frameworks */, CAA858CD25A3D8BC00ACF8C0 /* ErrorHandling in Frameworks */,
E89CBD382D5FAB950037ED95 /* XcodesLoginKit in Frameworks */,
E8C0EB1A291EF43E0081528A /* XcodesKit in Frameworks */, E8C0EB1A291EF43E0081528A /* XcodesKit in Frameworks */,
E8FD5727291EE4AC001E004C /* AsyncNetworkService in Frameworks */,
CAA1CB2D255A5262003FD669 /* AppleAPI in Frameworks */,
CABFA9EE2592F0CC00380FEE /* SwiftSoup in Frameworks */, CABFA9EE2592F0CC00380FEE /* SwiftSoup in Frameworks */,
E84E4F572B335094003F3959 /* OrderedCollections in Frameworks */, E84E4F572B335094003F3959 /* OrderedCollections in Frameworks */,
E8F44A1E296B4CD7002D6592 /* Path in Frameworks */, E8F44A1E296B4CD7002D6592 /* Path in Frameworks */,
@ -585,7 +584,6 @@
CA8FB61C256E115700469DA5 /* .github */, CA8FB61C256E115700469DA5 /* .github */,
CA9FF9252595A7EB00E47BAF /* Scripts */, CA9FF9252595A7EB00E47BAF /* Scripts */,
CA9FF8242594F10700E47BAF /* AcknowledgementsGenerator */, CA9FF8242594F10700E47BAF /* AcknowledgementsGenerator */,
CA538A0C255A4F1A00E64DD7 /* AppleAPI */,
CAD2E7A02449574E00113D76 /* Xcodes */, CAD2E7A02449574E00113D76 /* Xcodes */,
CAD2E7B62449575100113D76 /* XcodesTests */, CAD2E7B62449575100113D76 /* XcodesTests */,
CA9FF8AF2595967A00E47BAF /* com.xcodesorg.xcodesapp.Helper */, CA9FF8AF2595967A00E47BAF /* com.xcodesorg.xcodesapp.Helper */,
@ -715,7 +713,6 @@
); );
name = Xcodes; name = Xcodes;
packageProductDependencies = ( packageProductDependencies = (
CAA1CB2C255A5262003FD669 /* AppleAPI */,
CABFA9E32592F08E00380FEE /* Version */, CABFA9E32592F08E00380FEE /* Version */,
CABFA9ED2592F0CC00380FEE /* SwiftSoup */, CABFA9ED2592F0CC00380FEE /* SwiftSoup */,
CABFA9F72592F0F900380FEE /* KeychainAccess */, CABFA9F72592F0F900380FEE /* KeychainAccess */,
@ -723,13 +720,14 @@
CA9FF86C25951C6E00E47BAF /* XCModel */, CA9FF86C25951C6E00E47BAF /* XCModel */,
CAA858CC25A3D8BC00ACF8C0 /* ErrorHandling */, CAA858CC25A3D8BC00ACF8C0 /* ErrorHandling */,
E689540225BE8C64000EBCEA /* DockProgress */, E689540225BE8C64000EBCEA /* DockProgress */,
E8FD5726291EE4AC001E004C /* AsyncNetworkService */,
E8C0EB19291EF43E0081528A /* XcodesKit */, E8C0EB19291EF43E0081528A /* XcodesKit */,
E8F44A1D296B4CD7002D6592 /* Path */, E8F44A1D296B4CD7002D6592 /* Path */,
E84E4F562B335094003F3959 /* OrderedCollections */, E84E4F562B335094003F3959 /* OrderedCollections */,
E83FDC432CBB649100679C6B /* Sparkle */, E83FDC432CBB649100679C6B /* Sparkle */,
334A932B2CA885A400A5E079 /* LibFido2Swift */, 334A932B2CA885A400A5E079 /* LibFido2Swift */,
E862D43A2CC8B26F00BAA376 /* SRP */, E862D43A2CC8B26F00BAA376 /* SRP */,
E89CBD372D5FAB950037ED95 /* XcodesLoginKit */,
E89CBD3C2D5FB25A0037ED95 /* AppleAPI */,
); );
productName = XcodesMac; productName = XcodesMac;
productReference = CAD2E79E2449574E00113D76 /* Xcodes.app */; productReference = CAD2E79E2449574E00113D76 /* Xcodes.app */;
@ -814,11 +812,11 @@
CAA858CB25A3D8BC00ACF8C0 /* XCRemoteSwiftPackageReference "ErrorHandling" */, CAA858CB25A3D8BC00ACF8C0 /* XCRemoteSwiftPackageReference "ErrorHandling" */,
CAC28186259EE27200B8AB0B /* XCRemoteSwiftPackageReference "CombineExpectations" */, CAC28186259EE27200B8AB0B /* XCRemoteSwiftPackageReference "CombineExpectations" */,
E689540125BE8C64000EBCEA /* XCRemoteSwiftPackageReference "DockProgress" */, E689540125BE8C64000EBCEA /* XCRemoteSwiftPackageReference "DockProgress" */,
E8FD5725291EE4AC001E004C /* XCRemoteSwiftPackageReference "AsyncHTTPNetworkService" */,
E8F44A1C296B4CD7002D6592 /* XCRemoteSwiftPackageReference "Path" */, E8F44A1C296B4CD7002D6592 /* XCRemoteSwiftPackageReference "Path" */,
E84E4F552B335094003F3959 /* XCRemoteSwiftPackageReference "swift-collections" */, E84E4F552B335094003F3959 /* XCRemoteSwiftPackageReference "swift-collections" */,
E83FDC422CBB649100679C6B /* XCRemoteSwiftPackageReference "Sparkle" */, E83FDC422CBB649100679C6B /* XCRemoteSwiftPackageReference "Sparkle" */,
33027E282CA8BB5800CB387C /* XCRemoteSwiftPackageReference "LibFido2Swift" */, E89CBD362D5FAB950037ED95 /* XCRemoteSwiftPackageReference "XcodesLoginKit" */,
E89CBD3B2D5FB25A0037ED95 /* XCLocalSwiftPackageReference "Xcodes/AppleAPI" */,
); );
productRefGroup = CAD2E79F2449574E00113D76 /* Products */; productRefGroup = CAD2E79F2449574E00113D76 /* Products */;
projectDirPath = ""; projectDirPath = "";
@ -1487,15 +1485,14 @@
}; };
/* End XCConfigurationList section */ /* End XCConfigurationList section */
/* Begin XCRemoteSwiftPackageReference section */ /* Begin XCLocalSwiftPackageReference section */
33027E282CA8BB5800CB387C /* XCRemoteSwiftPackageReference "LibFido2Swift" */ = { E89CBD3B2D5FB25A0037ED95 /* XCLocalSwiftPackageReference "Xcodes/AppleAPI" */ = {
isa = XCRemoteSwiftPackageReference; isa = XCLocalSwiftPackageReference;
repositoryURL = "https://github.com/kinoroy/LibFido2Swift.git"; relativePath = Xcodes/AppleAPI;
requirement = {
kind = upToNextMinorVersion;
minimumVersion = 0.1.0;
};
}; };
/* End XCLocalSwiftPackageReference section */
/* Begin XCRemoteSwiftPackageReference section */
CA9FF86B25951C6E00E47BAF /* XCRemoteSwiftPackageReference "data" */ = { CA9FF86B25951C6E00E47BAF /* XCRemoteSwiftPackageReference "data" */ = {
isa = XCRemoteSwiftPackageReference; isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/xcodereleases/data"; repositoryURL = "https://github.com/xcodereleases/data";
@ -1576,6 +1573,14 @@
minimumVersion = 1.0.5; minimumVersion = 1.0.5;
}; };
}; };
E89CBD362D5FAB950037ED95 /* XCRemoteSwiftPackageReference "XcodesLoginKit" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/XcodesOrg/XcodesLoginKit";
requirement = {
branch = main;
kind = branch;
};
};
E8F44A1C296B4CD7002D6592 /* XCRemoteSwiftPackageReference "Path" */ = { E8F44A1C296B4CD7002D6592 /* XCRemoteSwiftPackageReference "Path" */ = {
isa = XCRemoteSwiftPackageReference; isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/mxcl/Path.swift"; repositoryURL = "https://github.com/mxcl/Path.swift";
@ -1584,14 +1589,6 @@
minimumVersion = 1.0.0; minimumVersion = 1.0.0;
}; };
}; };
E8FD5725291EE4AC001E004C /* XCRemoteSwiftPackageReference "AsyncHTTPNetworkService" */ = {
isa = XCRemoteSwiftPackageReference;
repositoryURL = "https://github.com/RobotsAndPencils/AsyncHTTPNetworkService";
requirement = {
branch = main;
kind = branch;
};
};
/* End XCRemoteSwiftPackageReference section */ /* End XCRemoteSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */ /* Begin XCSwiftPackageProductDependency section */
@ -1604,10 +1601,6 @@
package = CA9FF86B25951C6E00E47BAF /* XCRemoteSwiftPackageReference "data" */; package = CA9FF86B25951C6E00E47BAF /* XCRemoteSwiftPackageReference "data" */;
productName = XCModel; productName = XCModel;
}; };
CAA1CB2C255A5262003FD669 /* AppleAPI */ = {
isa = XCSwiftPackageProductDependency;
productName = AppleAPI;
};
CAA858CC25A3D8BC00ACF8C0 /* ErrorHandling */ = { CAA858CC25A3D8BC00ACF8C0 /* ErrorHandling */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = CAA858CB25A3D8BC00ACF8C0 /* XCRemoteSwiftPackageReference "ErrorHandling" */; package = CAA858CB25A3D8BC00ACF8C0 /* XCRemoteSwiftPackageReference "ErrorHandling" */;
@ -1657,6 +1650,15 @@
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = SRP; productName = SRP;
}; };
E89CBD372D5FAB950037ED95 /* XcodesLoginKit */ = {
isa = XCSwiftPackageProductDependency;
package = E89CBD362D5FAB950037ED95 /* XCRemoteSwiftPackageReference "XcodesLoginKit" */;
productName = XcodesLoginKit;
};
E89CBD3C2D5FB25A0037ED95 /* AppleAPI */ = {
isa = XCSwiftPackageProductDependency;
productName = AppleAPI;
};
E8C0EB19291EF43E0081528A /* XcodesKit */ = { E8C0EB19291EF43E0081528A /* XcodesKit */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = XcodesKit; productName = XcodesKit;
@ -1666,11 +1668,6 @@
package = E8F44A1C296B4CD7002D6592 /* XCRemoteSwiftPackageReference "Path" */; package = E8F44A1C296B4CD7002D6592 /* XCRemoteSwiftPackageReference "Path" */;
productName = Path; productName = Path;
}; };
E8FD5726291EE4AC001E004C /* AsyncNetworkService */ = {
isa = XCSwiftPackageProductDependency;
package = E8FD5725291EE4AC001E004C /* XCRemoteSwiftPackageReference "AsyncHTTPNetworkService" */;
productName = AsyncNetworkService;
};
/* End XCSwiftPackageProductDependency section */ /* End XCSwiftPackageProductDependency section */
}; };
rootObject = CAD2E7962449574E00113D76 /* Project object */; rootObject = CAD2E7962449574E00113D76 /* Project object */;

View file

@ -3,10 +3,10 @@
"pins": [ "pins": [
{ {
"package": "AsyncNetworkService", "package": "AsyncNetworkService",
"repositoryURL": "https://github.com/RobotsAndPencils/AsyncHTTPNetworkService", "repositoryURL": "https://github.com/XcodesOrg/AsyncHTTPNetworkService",
"state": { "state": {
"branch": "main", "branch": "main",
"revision": "97770856c4e429f880d4b4dd68cfaf286dc00c30", "revision": "12e225af8b5dc25afcfabfcf582a165b0581ab19",
"version": null "version": null
} }
}, },
@ -78,8 +78,8 @@
"repositoryURL": "https://github.com/kinoroy/LibFido2Swift.git", "repositoryURL": "https://github.com/kinoroy/LibFido2Swift.git",
"state": { "state": {
"branch": null, "branch": null,
"revision": "b77e5c6451bea69d15615d6578936b11777d9a6c", "revision": "94d496d6f850dcbb3e8c4a27cd7eeabfad9f14e3",
"version": "0.1.2" "version": "0.1.4"
} }
}, },
{ {
@ -144,6 +144,15 @@
"revision": "087c91fedc110f9f833b14ef4c32745dabca8913", "revision": "087c91fedc110f9f833b14ef4c32745dabca8913",
"version": "1.0.3" "version": "1.0.3"
} }
},
{
"package": "XcodesLoginKit",
"repositoryURL": "https://github.com/XcodesOrg/XcodesLoginKit",
"state": {
"branch": "main",
"revision": "3a6f2b82c47aea17c510f0326849734a08a74eae",
"version": null
}
} }
] ]
}, },

View file

@ -2,6 +2,7 @@ import Combine
import Foundation import Foundation
import Path import Path
import AppleAPI import AppleAPI
import XcodesLoginKit
import Version import Version
import LegibleError import LegibleError
import os.log import os.log

View file

@ -1,9 +1,10 @@
import Foundation import Foundation
import XcodesKit import XcodesKit
import AppleAPI
import OSLog import OSLog
import Combine import Combine
import Path import Path
import AppleAPI import XcodesLoginKit
import Version import Version
extension AppState { extension AppState {

View file

@ -4,7 +4,7 @@ import Path
import Version import Version
import SwiftSoup import SwiftSoup
import struct XCModel.Xcode import struct XCModel.Xcode
import AppleAPI import XcodesLoginKit
import XcodesKit import XcodesKit
extension AppState { extension AppState {

View file

@ -1,5 +1,5 @@
import AppKit import AppKit
import AppleAPI import XcodesLoginKit
import Combine import Combine
import Path import Path
import LegibleError import LegibleError
@ -9,7 +9,6 @@ import Version
import os.log import os.log
import DockProgress import DockProgress
import XcodesKit import XcodesKit
import LibFido2Swift
enum PreferenceKey: String { enum PreferenceKey: String {
case installPath case installPath
@ -31,7 +30,7 @@ enum PreferenceKey: String {
} }
class AppState: ObservableObject { class AppState: ObservableObject {
private let client = AppleAPI.Client() private let client = XcodesLoginKit.Client()
internal let runtimeService = RuntimeService() internal let runtimeService = RuntimeService()
// MARK: - Published Properties // MARK: - Published Properties
@ -258,50 +257,40 @@ class AppState: ObservableObject {
} }
func signInIfNeeded() -> AnyPublisher<Void, Error> { func signInIfNeeded() -> AnyPublisher<Void, Error> {
validateSession() return validateSession()
.catch { (error) -> AnyPublisher<Void, Error> in // .catch { (error) -> AnyPublisher<Void, Error> in
guard // guard
let username = self.savedUsername, // let username = self.savedUsername,
let password = try? Current.keychain.getString(username) // let password = try? Current.keychain.getString(username)
else { // else {
return Fail(error: error) // return Fail(error: error)
.eraseToAnyPublisher() // .eraseToAnyPublisher()
} // }
//
return self.signIn(username: username, password: password) // return self.signIn(username: username, password: password)
.map { _ in Void() } // //.map { _ in Void() }
.eraseToAnyPublisher() // .eraseToAnyPublisher()
} // }
.eraseToAnyPublisher() // .eraseToAnyPublisher()
} }
func signIn(username: String, password: String) { func signIn(username: String, password: String) {
authError = nil authError = nil
signIn(username: username, password: password)
.sink(
receiveCompletion: { _ in },
receiveValue: { _ in }
)
.store(in: &cancellables)
}
func signIn(username: String, password: String) -> AnyPublisher<AuthenticationState, Error> {
try? Current.keychain.set(password, key: username) try? Current.keychain.set(password, key: username)
Current.defaults.set(username, forKey: "username") Current.defaults.set(username, forKey: "username")
isProcessingAuthRequest = true isProcessingAuthRequest = true
return client.srpLogin(accountName: username, password: password)
.receive(on: DispatchQueue.main) Task { @MainActor in
.handleEvents( do {
receiveOutput: { authenticationState in let authenticationState = try await client.srpLogin(accountName: username, password: password)
self.authenticationState = authenticationState handleAuthenticationFlowCompletion(authenticationState)
}, isProcessingAuthRequest = false
receiveCompletion: { completion in } catch {
self.handleAuthenticationFlowCompletion(completion) Logger.appState.error("Error signing in: \(error, privacy: .public)")
self.isProcessingAuthRequest = false authError = error
} self.isProcessingAuthRequest = false
) }
.eraseToAnyPublisher() }
} }
func handleTwoFactorOption(_ option: TwoFactorOption, authOptions: AuthOptionsResponse, serviceKey: String, sessionID: String, scnt: String) { func handleTwoFactorOption(_ option: TwoFactorOption, authOptions: AuthOptionsResponse, serviceKey: String, sessionID: String, scnt: String) {
@ -314,21 +303,18 @@ class AppState: ObservableObject {
func requestSMS(to trustedPhoneNumber: AuthOptionsResponse.TrustedPhoneNumber, authOptions: AuthOptionsResponse, sessionData: AppleSessionData) { func requestSMS(to trustedPhoneNumber: AuthOptionsResponse.TrustedPhoneNumber, authOptions: AuthOptionsResponse, sessionData: AppleSessionData) {
isProcessingAuthRequest = true isProcessingAuthRequest = true
client.requestSMSSecurityCode(to: trustedPhoneNumber, authOptions: authOptions, sessionData: sessionData) Task {
.receive(on: DispatchQueue.main) do {
.sink( let authenticationState = try await client.requestSMSSecurityCode(to: trustedPhoneNumber, authOptions: authOptions, sessionData: sessionData)
receiveCompletion: { completion in self.handleAuthenticationFlowCompletion(authenticationState)
self.handleAuthenticationFlowCompletion(completion) self.isProcessingAuthRequest = false
self.isProcessingAuthRequest = false
}, } catch {
receiveValue: { authenticationState in Logger.appState.error("Error requesting SMS: \(error, privacy: .public)")
self.authenticationState = authenticationState authError = error
if case let AuthenticationState.waitingForSecondFactor(option, authOptions, sessionData) = authenticationState { self.isProcessingAuthRequest = false
self.handleTwoFactorOption(option, authOptions: authOptions, serviceKey: sessionData.serviceKey, sessionID: sessionData.sessionID, scnt: sessionData.scnt) }
} }
}
)
.store(in: &cancellables)
} }
func choosePhoneNumberForSMS(authOptions: AuthOptionsResponse, sessionData: AppleSessionData) { func choosePhoneNumberForSMS(authOptions: AuthOptionsResponse, sessionData: AppleSessionData) {
@ -341,101 +327,67 @@ class AppState: ObservableObject {
func submitSecurityCode(_ code: SecurityCode, sessionData: AppleSessionData) { func submitSecurityCode(_ code: SecurityCode, sessionData: AppleSessionData) {
isProcessingAuthRequest = true isProcessingAuthRequest = true
client.submitSecurityCode(code, sessionData: sessionData)
.receive(on: DispatchQueue.main)
.sink(
receiveCompletion: { completion in
self.handleAuthenticationFlowCompletion(completion)
self.isProcessingAuthRequest = false
},
receiveValue: { authenticationState in
self.authenticationState = authenticationState
}
)
.store(in: &cancellables)
}
var fido2: FIDO2?
func createAndSubmitSecurityKeyAssertationWithPinCode(_ pinCode: String, sessionData: AppleSessionData, authOptions: AuthOptionsResponse) {
self.presentedSheet = .securityKeyTouchToConfirm
guard let fsaChallenge = authOptions.fsaChallenge else {
// This shouldn't happen
// we shouldn't have called this method without setting the fsaChallenge
// so this is an assertionFailure
assertionFailure()
self.authError = "Something went wrong. Please file a bug report"
return
}
// The challenge is encoded in Base64URL encoding
let challengeUrl = fsaChallenge.challenge
let challenge = FIDO2.base64urlToBase64(base64url: challengeUrl)
let origin = "https://idmsa.apple.com"
let rpId = "apple.com"
// Allowed creds is sent as a comma separated string
let validCreds = fsaChallenge.allowedCredentials.split(separator: ",").map(String.init)
Task { Task {
do { do {
let fido2 = FIDO2() let authenticationState = try await client.submitSecurityCode(code, sessionData: sessionData)
self.fido2 = fido2 self.handleAuthenticationFlowCompletion(authenticationState)
let response = try fido2.respondToChallenge(args: ChallengeArgs(rpId: rpId, validCredentials: validCreds, devPin: pinCode, challenge: challenge, origin: origin)) self.isProcessingAuthRequest = false
Task { @MainActor in
self.isProcessingAuthRequest = true
}
let respData = try JSONEncoder().encode(response)
client.submitChallenge(response: respData, sessionData: AppleSessionData(serviceKey: sessionData.serviceKey, sessionID: sessionData.sessionID, scnt: sessionData.scnt))
.receive(on: DispatchQueue.main)
.handleEvents(
receiveOutput: { authenticationState in
self.authenticationState = authenticationState
},
receiveCompletion: { completion in
self.handleAuthenticationFlowCompletion(completion)
self.isProcessingAuthRequest = false
}
).sink(
receiveCompletion: { _ in },
receiveValue: { _ in }
).store(in: &cancellables)
} catch FIDO2Error.canceledByUser {
// User cancelled the auth flow
// we don't have to show an error
// because the sheet will already be dismissed
} catch { } catch {
Logger.appState.error("ERROR SUBMITTING SECURITYCODE: \(error, privacy: .public)")
authError = error authError = error
self.isProcessingAuthRequest = false
}
}
}
func createAndSubmitSecurityKeyAssertationWithPinCode(_ pinCode: String, sessionData: AppleSessionData, authOptions: AuthOptionsResponse) {
isProcessingAuthRequest = true
self.presentedSheet = .securityKeyTouchToConfirm
Task {
do {
let authenticationState = try await client.submitSecurityKeyPinCode(pinCode, sessionData: sessionData, authOptions: authOptions)
self.handleAuthenticationFlowCompletion(authenticationState)
self.isProcessingAuthRequest = false
} catch {
print("ERROR Requesting SMS: \(error)")
authError = error
self.isProcessingAuthRequest = false
} }
} }
} }
func cancelSecurityKeyAssertationRequest() { func cancelSecurityKeyAssertationRequest() {
self.fido2?.cancel() self.client.cancelSecurityKeyAssertationRequest()
} }
private func handleAuthenticationFlowCompletion(_ completion: Subscribers.Completion<Error>) { private func handleAuthenticationFlowCompletion(_ authenticationState: AuthenticationState) {
switch completion { self.authenticationState = authenticationState
case let .failure(error):
// remove saved username and any stored keychain password if authentication fails so it doesn't try again. switch authenticationState {
clearLoginCredentials() case .unauthenticated:
Logger.appState.error("Authentication error: \(error.legibleDescription)") authError = AuthenticationError.notAuthorized
self.authError = error case let .waitingForSecondFactor(twoFactorOption, authOptionsResponse, appleSessionData):
case .finished: self.presentedSheet = .twoFactor(.init(
switch self.authenticationState { option: twoFactorOption,
case .authenticated, .unauthenticated, .notAppleDeveloper: authOptions: authOptionsResponse,
self.presentedSheet = nil sessionData: AppleSessionData(serviceKey: appleSessionData.serviceKey, sessionID: appleSessionData.sessionID, scnt: appleSessionData.scnt)
case let .waitingForSecondFactor(option, authOptions, sessionData): ))
self.handleTwoFactorOption(option, authOptions: authOptions, serviceKey: sessionData.serviceKey, sessionID: sessionData.sessionID, scnt: sessionData.scnt) case .authenticated(let appleSession):
} Logger.appState.info("SUCCESSFULLY LOGGED IN - WELCOME: \(appleSession.user.fullName ?? "")")
self.presentedSheet = nil
break
case .notAppleDeveloper:
authError = AuthenticationError.notDeveloperAppleId
} }
} }
func signOut() { func signOut() {
clearLoginCredentials() clearLoginCredentials()
AppleAPI.Current.network.session.configuration.httpCookieStorage?.removeCookies(since: .distantPast) // TODO FIX ME
//client.signout()
authenticationState = .unauthenticated authenticationState = .unauthenticated
} }

View file

@ -2,6 +2,7 @@ import Combine
import Foundation import Foundation
import Path import Path
import AppleAPI import AppleAPI
import XcodesLoginKit
import KeychainAccess import KeychainAccess
import XcodesKit import XcodesKit
/** /**

View file

@ -1,5 +1,5 @@
import Foundation import Foundation
import AppleAPI import XcodesLoginKit
enum XcodesSheet: Identifiable { enum XcodesSheet: Identifiable {
case signIn case signIn

View file

@ -117,7 +117,7 @@ struct MainWindow: View {
@ViewBuilder @ViewBuilder
private func signInView() -> some View { private func signInView() -> some View {
if appState.authenticationState == .authenticated { if case .authenticated(_) = appState.authenticationState {
VStack { VStack {
SignedInView() SignedInView()
.padding(32) .padding(32)

View file

@ -1,4 +1,4 @@
import AppleAPI import XcodesLoginKit
import SwiftUI import SwiftUI
import Path import Path

View file

@ -1,4 +1,4 @@
import AppleAPI import XcodesLoginKit
import SwiftUI import SwiftUI
struct DownloadPreferencePane: View { struct DownloadPreferencePane: View {

View file

@ -1,4 +1,4 @@
import AppleAPI import XcodesLoginKit
import Path import Path
import SwiftUI import SwiftUI

View file

@ -1,4 +1,4 @@
import AppleAPI import XcodesLoginKit
import SwiftUI import SwiftUI
struct GeneralPreferencePane: View { struct GeneralPreferencePane: View {
@ -7,7 +7,7 @@ struct GeneralPreferencePane: View {
var body: some View { var body: some View {
VStack(alignment: .leading) { VStack(alignment: .leading) {
GroupBox(label: Text("AppleID")) { GroupBox(label: Text("AppleID")) {
if appState.authenticationState == .authenticated { if case .authenticated(_) = appState.authenticationState {
SignedInView() SignedInView()
} else { } else {
Button("SignIn", action: { self.appState.presentedSheet = .signIn }) Button("SignIn", action: { self.appState.presentedSheet = .signIn })

View file

@ -1,4 +1,4 @@
import AppleAPI import XcodesLoginKit
import Sparkle import Sparkle
import SwiftUI import SwiftUI

View file

@ -1,5 +1,5 @@
import SwiftUI import SwiftUI
import AppleAPI import XcodesLoginKit
struct SignIn2FAView: View { struct SignIn2FAView: View {
@EnvironmentObject var appState: AppState @EnvironmentObject var appState: AppState

View file

@ -1,4 +1,4 @@
import AppleAPI import XcodesLoginKit
import SwiftUI import SwiftUI
struct SignInPhoneListView: View { struct SignInPhoneListView: View {

View file

@ -1,5 +1,5 @@
import SwiftUI import SwiftUI
import AppleAPI import XcodesLoginKit
struct SignInSMSView: View { struct SignInSMSView: View {
@EnvironmentObject var appState: AppState @EnvironmentObject var appState: AppState

View file

@ -7,7 +7,7 @@
// //
import SwiftUI import SwiftUI
import AppleAPI import XcodesLoginKit
struct SignInSecurityKeyPinView: View { struct SignInSecurityKeyPinView: View {
@EnvironmentObject var appState: AppState @EnvironmentObject var appState: AppState

View file

@ -7,7 +7,7 @@
// //
import SwiftUI import SwiftUI
import AppleAPI import XcodesLoginKit
struct SignInSecurityKeyTouchView: View { struct SignInSecurityKeyTouchView: View {
@EnvironmentObject var appState: AppState @EnvironmentObject var appState: AppState

View file

@ -1,4 +1,4 @@
{\rtf1\ansi\ansicpg1252\cocoartf2818 {\rtf1\ansi\ansicpg1252\cocoartf2821
\cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 .SFNS-Regular;} \cocoatextscaling0\cocoaplatform0{\fonttbl\f0\fnil\fcharset0 .SFNS-Regular;}
{\colortbl;\red255\green255\blue255;} {\colortbl;\red255\green255\blue255;}
{\*\expandedcolortbl;;} {\*\expandedcolortbl;;}

View file

@ -237,6 +237,16 @@
} }
} }
}, },
"%@ (%@)" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "new",
"value" : "%1$@ (%2$@)"
}
}
}
},
"%@ %@ %@" : { "%@ %@ %@" : {
"localizations" : { "localizations" : {
"ar" : { "ar" : {

View file

@ -14,7 +14,7 @@ let package = Package(
], ],
dependencies: [ dependencies: [
// Dependencies declare other packages that this package depends on. // Dependencies declare other packages that this package depends on.
.package(url: "https://github.com/RobotsAndPencils/AsyncHTTPNetworkService", branch: "main"), .package(url: "https://github.com/XcodesOrg/AsyncHTTPNetworkService", branch: "main"),
.package(url: "https://github.com/mxcl/Path.swift", from: "1.0.0"), .package(url: "https://github.com/mxcl/Path.swift", from: "1.0.0"),
], ],
targets: [ targets: [

View file

@ -1,4 +1,4 @@
import AppleAPI import XcodesLoginKit
import Combine import Combine
import CombineExpectations import CombineExpectations
import Path import Path