iOS 에서 Swift로 PassKey를 생성해보고 생성한 키로 인증을 처리하는 샘플 코드를 작성해본다.
이때 ASAuthorizationPlatformPublicKeyCredentialProvider를 사용하기 때문에 이것부터 알아보자.
ASAuthorizationPlatformPublicKeyCredentialProvider
ASAuthorizationPlatformPublicKeyCredentialProvider는 iCloud Keychain과 함께 앱이나 웹사이트등 서비스에 공개키 자격증명 요청을 제공하는 객체이다. Credential Provider는 사용자의 등록 또는 인증을 위해 iCloud Keychain에 저장된 공개키-개인키 쌍에 접근하여 이 객체에 Credential Provider의 식별자를 전달해 인스턴스를 생성한다. 이때 식별자를 rpId로 부른다.
rpId(Relying Party Identifier)는 WebAuthn 및 PassKey 인증과정에서 서비스 제공자 또는 애플리케이션을 식별하는 도메인이다. 이 도메인은 사용자의 자격증명을 특정 서비스와 연결하여 해당 서비스에서만 인증이 될 수 있도록 보장해주는 역할을 한다.
예를 들어 rpId가 example.com 이었다면 해당 도메인과 연결되어 PassKey를 생성하고 로그인할때도 example.com 도메인에서믄 이 PassKey가 인증되어 사용이 가능하다.
PassKey 생성 및 등록
비밀번호 없이 새로운 서비스에 사용자를 인증하려면 서버에서 챌린지를 받아야 한다. 챌린지는 서버가 만드는 데이터로 인증자인 사용자가 해당 계정을 소유하고 있음을 증명하는데 사용된다.
아래의 swift 코드는 PassKey를 등록하는 과정을 설정한다.
let challenge: Data // Obtain this from the server.
let userID: Data // Obtain this from the server.
let platformProvider = ASAuthorizationPlatformPublicKeyCredentialProvider(relyingPartyIdentifier: "example.com")
let platformKeyRequest = platformProvider.createCredentialRegistrationRequest(challenge: challenge, name: "Anne Johnson", userID: userID)
let authController = ASAuthorizationController(authorizationRequests: [platformKeyRequest])
authController.delegate = self
authController.presentationContextProvider = self
authController.performRequests()
챌린지, 사용자 이름, 사용자 ID로 ASAuthorizationPlatformPublicKeyCredentialRegistrationRequest 인스턴스를 만들어 플랫폼 키 등록 요청을 생성한다.
그 이후 ASAuthorizationControllerDelegate의 인스턴스를 생성하고 플랫폼 키 요청 객체가 포함된 값을 전달한다. ASAuthorizationController의 delegate와 presentationContextProvider를 요청에 응답하는 객체로 설정한 다음 performRequests()를 호출하여 등록 요청을 수행하도록 한다.
생성한 PassKey로 인증
위에서 생성한 PassKey로 인증하는 코드는 다음과 같다.
let challenge: Data // Obtain this from the server.
let platformProvider = ASAuthorizationPlatformPublicKeyCredentialProvider(relyingPartyIdentifier: "example.com")
let platformKeyRequest = platformProvider.createCredentialAssertionRequest(challenge: challenge)
let authController = ASAuthorizationController(authorizationRequests: [platformKeyRequest])
authController.delegate = self
authController.presentationContextProvider = self
authController.performRequests()
사용자는 해당 서비스에 연결하고 로그인하려면 AssertionRequest를 사용하여 인증할 수 있다.
AssertionRequest를 시작하려면 먼저 서버에서 챌린지를 받아온다. 그 후 ASAuthorizationPlatformPublicKeyCredentialProvider의 인스턴스를 만들고 이때 relyingPartyIdentifier는 위에서 설명했던 rpId에 해당한다. 즉 서비스 URL인 셈이다.
챌린지를 이용해 ASAuthorizationPlatformPublicKeyCredentialAssertionRequest를 생성한 후 이 요청을 가지고 ASAuthorizationController를 생성한다. 그리고 ASAuthorizationController에 performRequests()를 호출하면 인증 요청을 수행하게 된다.
Authorization 핸들링
위에서 요청을 하면 응답은 아래코드와 같이 ASAuthorizationControllerDelegate로 응답이 내려온다.
func authorizationController(controller: controller, didCompleteWithAuthorization: authorization) {
if let credential = authorization.credential as? ASAuthorizationPlatformPublicKeyCredentialRegistration {
// Take steps to handle the registration.
} else if let credential = authorization.credential as? ASAuthorizationPlatformPublicKeyCredentialAssertion {
// Take steps to verify the challenge.
} else {
// Handle other authentication cases, such as Sign in with Apple.
}
func authorizationController(controller: controller, didCompleteWithError: error) {
// Handle the error.
}
ASAuthorizationControllerDelegate는 PassKey 등록 및 인증 요청에 대한 결과 정보를 수신할 수 있다. 이 프로토콜을 채택해 인증 성공 또는 인증 오류에 대한 핸들링 코드를 작성할 수 있다.
인증이 성공하면 ASAuthorizationController에서 자격 증명을 가져오고 그것이 Credential Registration 인지 Credential Assertion 인지 구분하여 해당 스텝에 맞는 코드를 작성한다.
인증 중 오류가 발생하면 authorizationController(controller: controller, didCompleteWithError: error)를 통해서 에러를 받을 수 있다.
WebView에서의 PassKey
iOS 에서 WKWebView에서 패스키를 사용하여 인증이 가능하며 서비스의 식별자를 앱의 연결된 도메인으로 구성해야 한다.
iOS 16.4 이후부터 WKWebView에서 Javascript API를 사용해 패스키 인증이 가능한지 테스트가 가능하며 사용자가 해당 서비스의 패스키를 보유하고 있을 경우 isUserVerifyingPlatformAuthenticatorAvailabe() 에서 true를 반환한다.
'Development' 카테고리의 다른 글
블록체인 지갑 주소 알고리즘에 대하여 (0) | 2024.10.20 |
---|---|
OAuth2.0 동작 흐름 알아보기 (0) | 2024.10.20 |
OpenID Connect 와 Auth2.0 (0) | 2024.10.19 |
Android12 SplashScreen 대응 방법 (feat. 앱 실행상태) (0) | 2024.07.30 |
Flutter In iOS 14+, debug mode Flutter apps can only be launched from Flutter tooling 오류를 만난 이유 (1) | 2024.06.08 |