Apple로 가입하기
애플로 로그인 튜토리얼
소개
애플로 로그인을 사용하면 사용자가 애플 ID를 사용하여 앱에 로그인할 수 있습니다. 이 기능은 iOS 13 및 이후 버전, Parse 3.5 및 이후 버전에서 사용할 수 있습니다.
전제 조건
이 튜토리얼을 완료하려면 다음이 필요합니다:
- Back4App에서 생성된 앱
- Back4App 앱을 위한 서브도메인 설정
1 - 새로운 Back4App 앱 만들기
우선, Back4App에서 기존 앱이 생성되어 있는지 확인해야 합니다. 그러나 새로운 사용자라면 이 튜토리얼을 확인하여 앱을 만드는 방법을 알아보세요.
2 - XCode 프로젝트에 Apple로 로그인 기능 추가하기
XCode 프로젝트에서 Target (1)을 클릭하고 Signing & Capabilities 탭 (2)으로 이동합니다. + 기능 버튼 (3)을 클릭하고 Apple로 로그인 기능 (4)을 추가합니다. 그곳에서 번들 식별자 (5)를 선택하고 나중에 필요할 정보를 기억해 두세요.

3 - 새 서비스 ID 만들기
당신의 Apple 개발자 계정에 로그인하고 식별자 섹션으로 이동합니다. 생성한 번들 식별자가 있는지 확인합니다.

번들 식별자를 클릭하고 아래로 스크롤합니다. Apple로 로그인이 선택되었는지 확인합니다.

클릭 편집하고 기본 앱 ID로 활성화가 선택되었는지 확인하세요.

모든 것이 올바르다면, 저장하고 종료하세요.
4 - Apple을 위한 Parse Auth 설정하기
Back4App 웹사이트로 가서 로그인한 후, 앱을 찾으세요. 그 후, 서버 설정을 클릭하고 Apple 로그인 블록을 검색한 후, 설정을 선택하세요.
Apple 로그인 섹션은 다음과 같습니다:

이제 아래 필드에 Bundle ID를 붙여넣고 저장 버튼을 클릭하면 됩니다.

Apple 로그인 통합 중 문제가 발생하면, 채팅을 통해 저희 팀에 문의해 주세요!
5 - 옵션 1 - 템플릿 다운로드
Apple로 로그인하기 위해서는 약간의 코딩이 필요하므로, 이 템플릿을 만들었습니다. 이 템플릿을 다운로드하여 Bundle Identifier, App Id, 그리고 Client Key을 변경할 수 있습니다.
코드는 완전히 문서화되어 있으므로 좋은 출발점입니다.
이 문서를 읽고 싶으시다면, 다음 단계로 진행해 주세요.
6 - 옵션 2 - 수동으로 코드 작성하기
뷰 안에 AuthenticationServices 프레임워크를 추가하고 PFUserAuthenticationDelegate를 처리할 AuthDelegate를 생성하세요:
1 import AuthenticationServices
2
3 class AuthDelegate:NSObject, PFUserAuthenticationDelegate {
4 func restoreAuthentication(withAuthData authData: [String : String]?) -> Bool {
5 return true
6 }
7
8 func restoreAuthenticationWithAuthData(authData: [String : String]?) -> Bool {
9 return true
10 }
11 }7 - ViewController에 대한 Delegates 구현하기
ViewController에 대해 ASAuthorizationControllerDelegate 및 ASAuthorizationControllerPresentationContextProviding을 구현하세요:
1 class ViewController: UIViewController, ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding8 - 애플로 로그인 버튼 추가하기
ViewDidAppear는 그에 적합한 장소입니다. 다른 장소를 선택할 경우, 한 번만 호출해야 한다는 것을 기억하세요:
1 override func viewDidAppear(_ animated: Bool) {
2 super.viewDidAppear(animated)
3
4 // Sign In with Apple button
5 let signInWithAppleButton = ASAuthorizationAppleIDButton()
6
7 // set this so the button will use auto layout constraint
8 signInWithAppleButton.translatesAutoresizingMaskIntoConstraints = false
9
10 // add the button to the view controller root view
11 self.view.addSubview(signInWithAppleButton)
12
13 // set constraint
14 NSLayoutConstraint.activate([
15 signInWithAppleButton.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 50.0),
16 signInWithAppleButton.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -50.0),
17 signInWithAppleButton.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -70.0),
18 signInWithAppleButton.heightAnchor.constraint(equalToConstant: 50.0)
19 ])
20
21 // the function that will be executed when user tap the button
22 signInWithAppleButton.addTarget(self, action: #selector(appleSignInTapped), for: .touchUpInside)
23 }마지막 줄의 appleSignInTapped도 ViewController 클래스 안에 정의되어야 합니다:
1 // This is the function that will be executed when user taps the button
2 @objc func appleSignInTapped() {
3 let provider = ASAuthorizationAppleIDProvider()
4 let request = provider.createRequest()
5 // request full name and email from the user's Apple ID
6 request.requestedScopes = [.fullName, .email]
7
8 // pass the request to the initializer of the controller
9 let authController = ASAuthorizationController(authorizationRequests: [request])
10
11 // similar to delegate, this will ask the view controller
12 // which window to present the ASAuthorizationController
13 authController.presentationContextProvider = self
14
15 // delegate functions will be called when user data is
16 // successfully retrieved or error occured
17 authController.delegate = self
18
19 // show the Sign-in with Apple dialog
20 authController.performRequests()
21 }9 - presentationContextProvider
presentationContextProvider (ASAuthorizationControllerPresentationContextProviding)는 어떤 창에서 인증 대화 상자를 표시할지를 요청합니다. 우리는 같은 창에 표시할 것이므로 self.view.window를 반환해야 합니다:
1 func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
2 // return the current view window
3 return self.view.window!
4 }10 - 델리게이트 ASAuthorizationControllerDelegate 처리하기
델리게이트가 호출될 때 처리해야 할 몇 가지 옵션이 있으므로, 이러한 옵션을 구별하여 처리할 수 있도록 코드를 추가합시다:
1 func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
2 print("authorization error")
3 guard let error = error as? ASAuthorizationError else {
4 return
5 }
6
7 switch error.code {
8 case .canceled:
9 // user press "cancel" during the login prompt
10 print("Canceled")
11 case .unknown:
12 // user didn't login their Apple ID on the device
13 print("Unknown")
14 case .invalidResponse:
15 // invalid response received from the login
16 print("Invalid Respone")
17 case .notHandled:
18 // authorization request not handled, maybe internet failure during login
19 print("Not handled")
20 case .failed:
21 // authorization failed
22 print("Failed")
23 @unknown default:
24 print("Default")
25 }
26 }11 - didCompleteWithAuthorization에 대한 델리게이트 처리하기
성공적으로 인증되면, 승인된 정보를 검색할 수 있습니다:
1 func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
2
3 if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
4 // unique ID for each user, this uniqueID will always be returned
5 let userID = appleIDCredential.user
6 print("UserID: " + userID)
7
8 // if needed, save it to user defaults by uncommenting the line below
9 //UserDefaults.standard.set(appleIDCredential.user, forKey: "userID")
10
11 // optional, might be nil
12 let email = appleIDCredential.email
13 print("Email: " + (email ?? "no email") )
14
15 // optional, might be nil
16 let givenName = appleIDCredential.fullName?.givenName
17 print("Given Name: " + (givenName ?? "no given name") )
18
19 // optional, might be nil
20 let familyName = appleIDCredential.fullName?.familyName
21 print("Family Name: " + (familyName ?? "no family name") )
22
23 // optional, might be nil
24 let nickName = appleIDCredential.fullName?.nickname
25 print("Nick Name: " + (nickName ?? "no nick name") )
26 /*
27 useful for server side, the app can send identityToken and authorizationCode
28 to the server for verification purpose
29 */
30 var identityToken : String?
31 if let token = appleIDCredential.identityToken {
32 identityToken = String(bytes: token, encoding: .utf8)
33 print("Identity Token: " + (identityToken ?? "no identity token"))
34 }
35
36 var authorizationCode : String?
37 if let code = appleIDCredential.authorizationCode {
38 authorizationCode = String(bytes: code, encoding: .utf8)
39 print("Authorization Code: " + (authorizationCode ?? "no auth code") )
40 }
41
42 // do what you want with the data here
43
44 }
45 }여기가 Parse에 로그인하는 코드를 추가할 수 있는 곳입니다. 그래서 여기서 데이터로 원하는 작업을 수행하세요 주석 바로 뒤에 추가해 보겠습니다:
1 PFUser.logInWithAuthType(inBackground: "apple", authData: ["token": String(identityToken!), "id": userID]).continueWith { task -> Any? in
2 if ((task.error) != nil){
3 //DispatchQueue.main.async {
4 print("Could not login.\nPlease try again.")
5 print("Error with parse login after SIWA: \(task.error!.localizedDescription)")
6 //}
7 return task
8 }
9 print("Successfuly signed in with Apple")
10 return nil
11 }물론, Parse 프레임워크를 추가하세요:
1 import Parse