Passkeyme Web SDK 是一个便利的 SDK,用于 Passkeyme 平台 JavaScript/TypeScript 库,它提供简单函数用于处理使用 WebAuthn API 的 passkey 注册和认证。这个库可以帮助您轻松地将基于 passkey 的身份验证集成到您的 Web 应用程序中。
您可以通过 cocoapods 安装 Passkey SDK
platform :ios, '16.0'
target 'Passkeyme SDK Demo' do
use_frameworks!
pod 'PasskeymeSDK', "~> 0.3.0"
end
然后
pod install
导入 SDK
import PasskeymeSDK
创建一个 PasskeySDK 实例
let sdk = PasskeymeSDK()
要注册 passkey,请使用 passkeyRegister 方法。该方法接受一个挑战字符串作为输入,并返回一个解析到包含凭证的对象的承诺。
sdk.passkeyRegister(challenge: challenge, anchor: self.view.window!) { result in
switch result {
case .success(let credential):
self.completeRegistration(credential: credential)
case .failure(let error):
print("Registration error: \(error)")
}
}
要使用 passkey 进行认证,请使用 passkeyAuthenticate 方法。该方法接受一个挑战字符串作为输入,并返回一个解析到包含凭证的对象的承诺。
sdk.passkeyAuthenticate(challenge: challenge, anchor: self.view.window!) { result in
switch result {
case .success(let credential):
self.completeAuthentication(credential: credential)
case .failure(let error):
print("Authentication error: \(error)")
}
}
passkeyRegister(challenge: string): Promise<{ credential: string }>
• challenge: A string that represents the challenge provided by your server.
• Returns: A promise that resolves to an object containing the credential.
passkeyAuthenticate(challenge: string): Promise<{ credential: string }>
• challenge: A string that represents the challenge provided by your server.
• Returns: A promise that resolves to an object containing the credential.
这里是一个完整的工作示例。
要运行它,首先前往 Passkeyme 注册,创建一个应用程序,获取 AppID 和 API 密钥,并在 env 中填写
APP_ID=
API_KEY=
您需要在可寻址域后面运行它才能使 Passkeys 正常工作。您可以托管它,或使用 ngrok 来提供服务。您需要遵循 https://passkeyme.com/docs/docs/SDKs/swift-sdk 中的说明
import UIKit
import PasskeymeSDK
import Alamofire
class ViewController: UIViewController {
let sdk = PasskeymeSDK()
var APP_ID = ""
var API_KEY = ""
var backendURL = ""
override func viewDidLoad() {
super.viewDidLoad()
APP_ID = getEnvironmentVar("APP_ID")!
API_KEY = getEnvironmentVar("API_KEY")!
backendURL = "https://passkeyme.com/webauthn/\(APP_ID)"
let registerButton = UIButton(type: .system)
registerButton.setTitle("Register", for: .normal)
registerButton.addTarget(self, action: #selector(startRegistration), for: .touchUpInside)
let authenticateButton = UIButton(type: .system)
authenticateButton.setTitle("Authenticate", for: .normal)
authenticateButton.addTarget(self, action: #selector(startAuthentication), for: .touchUpInside)
let stackView = UIStackView(arrangedSubviews: [registerButton, authenticateButton])
stackView.axis = .vertical
stackView.spacing = 20
stackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
}
@objc func startRegistration() {
let url = "\(backendURL)/start_registration"
AF.request(url, method: .post, parameters: nil, encoding: JSONEncoding.default)
.responseJSON { response in
switch response.result {
case .success(let value):
if let json = value as? [String: Any], let challenge = json["challenge"] as? String {
self.registerPasskey(challenge: challenge)
}
case .failure(let error):
print("Error getting registration challenge: \(error)")
}
}
}
func registerPasskey(challenge: String) {
sdk.passkeyRegister(challenge: challenge, anchor: self.view.window!) { result in
switch result {
case .success(let credential):
self.completeRegistration(credential: credential)
case .failure(let error):
print("Registration error: \(error)")
}
}
}
func completeRegistration(credential: String) {
let url = "\(backendURL)/complete_registration"
let parameters: [String: Any] = ["credential": credential]
AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { response in
switch response.result {
case .success(let value):
print("Registration completed: \(value)")
case .failure(let error):
print("Error completing registration: \(error)")
}
}
}
@objc func startAuthentication() {
let url = "\(backendURL)/start_authentication"
AF.request(url, method: .post, parameters: nil, encoding: JSONEncoding.default)
.responseJSON { response in
switch response.result {
case .success(let value):
if let json = value as? [String: Any], let challenge = json["challenge"] as? String {
self.authenticatePasskey(challenge: challenge)
}
case .failure(let error):
print("Error getting authentication challenge: \(error)")
}
}
}
func authenticatePasskey(challenge: String) {
sdk.passkeyAuthenticate(challenge: challenge, anchor: self.view.window!) { result in
switch result {
case .success(let credential):
self.completeAuthentication(credential: credential)
case .failure(let error):
print("Authentication error: \(error)")
}
}
}
func completeAuthentication(credential: String) {
let url = "\(backendURL)/complete_authentication"
let parameters: [String: Any] = ["credential": credential]
AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default)
.responseJSON { response in
switch response.result {
case .success(let value):
print("Authentication completed: \(value)")
case .failure(let error):
print("Error completing authentication: \(error)")
}
}
}
func getEnvironmentVar(_ name: String) -> String? {
guard let rawValue = getenv(name) else { return nil }
return String(utf8String: rawValue)
}
}