我正在为我的 Ionic 应用程序实现 Passkey,但我找不到任何插件,所以我正在构建自己的插件。一切正常,直到触发本机 iOS 上的密钥,但我无法从 iOS 获取注册数据。如何从 AppDelegate 获取数据?我的代码基于Apple官方文档示例:https://developer.apple.com/documentation/authenticationservices/connecting_to_a_service_with_passkeys。
在示例中,它需要 AppDelegate 来获取注册数据委托,但是我无法使我的 Capacitor 插件使用主 AppDelegate。因此,授权控制器在密钥注册后不会运行。从 webview 获取挑战并将其传递到本机并触发 iOS 设备上的密钥提示一切都已经正常,只是无法获取注册结果数据。
PasskeyPlugin.swift
@objc(PasskeyPlugin)
public class PasskeyPlugin: CAPPlugin {
private let implementation = Passkey()
@objc func create(_ call: CAPPluginCall) {
let challenge: Data? = call.getString("challenge")!.data(using: .utf8)
DispatchQueue.main.async {
let signInViewController = SignInViewController(challenge: challenge!)
self.bridge?.viewController?.present(signInViewController, animated: true, completion: nil)
}
call.resolve([
"platform": "iOS Native Passkey",
])
}
}
SignInViewController.swift
class SignInViewController: UIViewController {
var challenge: Data!
init(challenge: Data) {
self.challenge = challenge
print(self.challenge! as NSData)
super.init(nibName: nil, bundle: nil)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
signInObserver = NotificationCenter.default.addObserver(forName: .UserSignedIn, object: nil, queue: nil) {_ in
self.didFinishSignIn()
}
signInErrorObserver = NotificationCenter.default.addObserver(forName: .ModalSignInSheetCanceled, object: nil, queue: nil) { _ in
self.showSignInForm()
}
guard let window = self.view.window else { fatalError("The view was not in the app's view hierarchy!") }
let userName = "Name"
let accountManager = AccountManager()
accountManager.signUpWith(userName: userName, challenge: self.challenge, anchor: window)
// I cannot use the AppDelegate with errors
// (UIApplication.shared.delegate as? AppDelegate)?.accountManager.signUpWith(userName: userName, challenge: self.challenge, anchor: window)
}
}
AccountManager.swift
extension NSNotification.Name {
static let UserSignedIn = Notification.Name("UserSignedInNotification")
static let ModalSignInSheetCanceled = Notification.Name("ModalSignInSheetCanceledNotification")
}
class AccountManager: NSObject, ASAuthorizationControllerPresentationContextProviding, ASAuthorizationControllerDelegate {
let domain = "com.domain.my"
var authenticationAnchor: ASPresentationAnchor?
var isPerformingModalReqest = false
func signUpWith(userName: String, challenge: Data, anchor: ASPresentationAnchor) {
self.authenticationAnchor = anchor
if #available(iOS 15.0, *) {
let publicKeyCredentialProvider = ASAuthorizationPlatformPublicKeyCredentialProvider(relyingPartyIdentifier: domain)
// The userID is the identifier for the user's account.
// Hard coded for example purposes
let userID = "d0a4bc91-2def-4567-8983-9188a4ca2048".data(using: .utf8)!
let registrationRequest = publicKeyCredentialProvider.createCredentialRegistrationRequest(challenge: challenge,
name: "Some name", userID: userID)
let authController = ASAuthorizationController(authorizationRequests: [ registrationRequest ] )
authController.delegate = self
authController.presentationContextProvider = self
authController.performRequests()
isPerformingModalReqest = true
} else {
// Fallback on earlier versions
}
}
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
if #available(iOS 14.0, *) {
let logger = Logger()
if #available(iOS 15.0, *) {
switch authorization.credential {
case let credentialRegistration as ASAuthorizationPlatformPublicKeyCredentialRegistration:
logger.log("A new passkey was registered: \(credentialRegistration)")
// Verify the attestationObject and clientDataJSON with your service.
// The attestationObject contains the user's new public key to store and use for subsequent sign-ins.
// let attestationObject = credentialRegistration.rawAttestationObject
// let clientDataJSON = credentialRegistration.rawClientDataJSON
// After the server verifies the registration and creates the user account, sign in the user with the new account.
didFinishSignIn()
case let credentialAssertion as ASAuthorizationPlatformPublicKeyCredentialAssertion:
logger.log("A passkey was used to sign in: \(credentialAssertion)")
// Verify the below signature and clientDataJSON with your service for the given userID.
// let signature = credentialAssertion.signature
// let clientDataJSON = credentialAssertion.rawClientDataJSON
// let userID = credentialAssertion.userID
// After the server verifies the assertion, sign in the user.
didFinishSignIn()
case let passwordCredential as ASPasswordCredential:
logger.log("A password was provided: \(passwordCredential)")
// Verify the userName and password with your service.
// let userName = passwordCredential.user
// let password = passwordCredential.password
// After the server verifies the userName and password, sign in the user.
didFinishSignIn()
default:
fatalError("Received unknown authorization type.")
}
} else {
// Fallback on earlier versions
}
} else {
// Fallback on earlier versions
}
isPerformingModalReqest = false
}
}
如何让authorizationController在本机设备上出现密码提示后运行?预先感谢您。
您能告诉我如何从自动填充凭据扩展中获取密码吗 如果我在 webauthn.io 上,那么我的应用程序会显示创建密钥弹出窗口,但然后什么也不起作用
请帮助我