애플에서 아주 편한 로그인 기능을 내놨다. 아이폰 쓰는 사람은 애플계정을 갖고 있으니 그 정보로 로그인을 하는데, 개발자가 받을 수 있는 건 이름, 실제/가상 이메일 주소, 임의로 생성된 사용자 고유번호 정도가 전부다.
Xcode의 Signing & capabilities
로 가면 +Capability
가 있는데, 이걸 누르면 이런게 뜬다. sign 만 입력해도 Sign in with Apple 이 나오는데, 클릭하면

이렇게 추가가 된다.

애플이 지원하는 Sign in with Apple 이 적힌 버튼을 만들고
import AuthenticationServices import SwiftUI final class SignInWithAppleButton: UIViewRepresentable { func makeUIView(context: Context) -> ASAuthorizationAppleIDButton { return ASAuthorizationAppleIDButton(type: .signIn, style: .whiteOutline) } func updateUIView(_ uiView: ASAuthorizationAppleIDButton, context: Context) {} }
화면에 표시한 다음에
import AuthenticationServices import SwiftUI struct ContentView: View { @State var appleSignInDelegate: SignInWithAppleDelegate! = nil var body: some View { SignInWithAppleButton().frame(width: 280, height: 60) .cornerRadius(5) .onTapGesture(perform: showAppleLogin) } private func showAppleLogin() { appleSignInDelegates = SignInWithAppleDelegate { print("로그인 성공?: \($0)") } let request = ASAuthorizationAppleIDProvider().createRequest() request.requestedScopes = [.fullName, .email] let controller = ASAuthorizationController(authorizationRequests: [request]) controller.delegate = appleSignInDelegate controller.presentationContextProvider = appleSignInDelegate controller.performRequests() } }
실제 로그인 동작을 할 delegate 를 만들면 된다.
import AuthenticationServices import SwiftUI class SignInWithAppleDelegate: NSObject { private let signInSucceeded: (Bool) -> Void init(onSignedIn: @escaping (Bool) -> Void) { signInSucceeded = onSignedIn } } extension SignInWithAppleDelegate: ASAuthorizationControllerDelegate { func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) { switch authorization.credential { case let appleIdCredential as ASAuthorizationAppleIDCredential: if let _ = appleIdCredential.email, let _ = appleIdCredential.fullName { print("111111 ================= 첫 로그인") displayLog(credential: appleIdCredential) } else { print("222222 ================== 로그인 했었음") displayLog(credential: appleIdCredential) } signInSucceeded(true) default: break } } func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {} private func displayLog(credential: ASAuthorizationAppleIDCredential) { print("identityToken: \(String(describing: credential.identityToken))\nauthorizationCode: \(credential.authorizationCode!)\nuser: \(credential.user)\nemail: \(String(describing: credential.email))\ncredential: \(credential)") } } extension SignInWithAppleDelegate: ASAuthorizationControllerPresentationContextProviding { func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor { return UIApplication.shared.windows.last! } }
최초 로그인할 때는

이렇게 뜨는데, 만약 나의 이메일 공유하기를 선택하면 실제 메일 주소가 리턴되고, 이메일 가리기를 하면 가상으로 만들어진 alskhfda@privaterelay.appleid.com
이런 메일주소가 리턴된다. 그나마도 이름과 메일주소는 최초 로그인할 때만 받을 수 있고, 다음에 로그인할 때는 토큰주소만 넘어온다. 저 주소로 메일을 보냈는데, 전달에 실패했다. 송신메일서버에서 뭔가 작업을 해야 송신이 된다고 한다.
처음 로그인은 이렇게 로그가 찍힌다.
111111 ================= 첫 로그인 identityToken: Optional(802 bytes) authorizationCode: 63 bytes user: 000944.4de0e41477fc4cd6a4a1fbfdbdcd8c29.0504 email: Optional("tt55c74yjy@privaterelay.appleid.com") credential: <ASAuthorizationAppleIDCredential: 0x2812c3840 { userIdentifier: 000944.4de0e41477fc4cd6a4a1fbfdbdcd8c29.0504, authorizedScopes: ( ) }> 로그인 성공?: true
두 번째 로그인부터는 이렇게 표시된다.

로그는 이렇게 찍힌다.
222222 ================== 로그인 했었음 identityToken: Optional(802 bytes) authorizationCode: 63 bytes user: 000944.4de0e41477fc4cd6a4a1fbfdbdcd8c29.0504 email: nil credential: <ASAuthorizationAppleIDCredential: 0x2812c59e0 { userIdentifier: 000944.4de0e41477fc4cd6a4a1fbfdbdcd8c29.0504, authorizedScopes: ( ) }> 로그인 성공?: true