์์ ๋ก๊ทธ์ธ - ์ ํ ๋ก๊ทธ์ธ(Sign in with Apple)์ ๊ตฌํํด๋ณด์.
์์ฆ ์ดํ์์๋ ํ์๋ก ๋ค์ด๊ฐ๋ ์์ ๋ก๊ทธ์ธ์ ๊ตฌํํ๋ค๋ฉด, ์ ํ๋ก๊ทธ์ธ์ ๊ตฌํํด์ผ ํฉ๋๋ค.
์ ํ์ 2019๋ ์ ํ ๋ก๊ทธ์ธ ๊ธฐ๋ฅ์ ๋ฐํ์ ๋์์ ์ฑ ๋ด์ ๋ค๋ฅธ ์์ ๋ก๊ทธ์ธ ์๋น์ค๋ฅผ ์ฌ์ฉ ์ ํ์๋ก ์ ํ ๋ก๊ทธ์ธ์ ์ ๊ณตํด์ผ ํ๋ค๋ ์ฌ์ฌ์ง์นจ๋ ํจ๊ป ๋ด๋์๊ธฐ ๋๋ฌธ!!
๋ฐ๋ผ์, ์ด์ ๋ ํ์๊ฐ ๋ ์ ํ ๋ก๊ทธ์ธ์ ๊ตฌํํ๋ ๋ฐฉ๋ฒ์ ์์๋ด ์๋ค.
*์๋ฎฌ๋ ์ดํฐ์์ ์๋๊ณ , ์ค์ ์์ดํฐ ๊ธฐ๊ธฐ๋ก ์คํ ๊ฐ๋ฅ.
๋ก๊ทธ์์์ ์ง์์ด ์๋ผ์ ๊ฐ๋ฐ์๊ฐ ์ง์ ๊ตฌํํด์ผ ํจ.
Step 1. Capability ์ถ๊ฐ
์ ํ ๋ก๊ทธ์ธ์ ์ ์ฉํ๊ธฐ ์ํ ์ฌ์ ์ค์ ์ ๋๋ค.
XCode Project > Signing & Capabilities > + Capability > Sign In with Apple์ ๊ฒ์ ํ ์ถ๊ฐ!
๋ค๋ฅธ ์์ ๋ก๊ทธ์ธ ์๋น์ค๋ค์ ๊ฐ๋ฐํ ๋์ฒ๋ผ SDK๋ฅผ ์ฌ์ฉํ์ง๋ ์๊ณ ๋ณ๋ค๋ฅธ ์ค์ ๋ ํ์ ์์ต๋๋ค.
๋ฐ๋ก Capability์ ์๋์ ๊ฐ์ด Sign In with Apple ํญ๋ชฉ์ด ์ถ๊ฐ๋ฉ๋๋ค.
Step 2. ์ ํ ๋ก๊ทธ์ธ ๋ฒํผ ์ถ๊ฐ
Apple ๋ก๊ทธ์ธ Action์ ์ํํ๋ ๋ฒํผ์ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
2-1 AuthenticationServices import
๊ทธ์ ์ ์ฌ์ฉํ ํด๋์ค์ Apple ๋ก๊ทธ์ธ์ ์ฌ์ฉํ๊ธฐ ์ํ ํ๋ ์์ํฌ์ธ AuthenticationServices ์๋์ ๊ฐ์ด ์ํฌํธ ํด์ฃผ์ธ์.
import AuthenticationServices
2-2. ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding ์์
๋จผ์ ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding ์์๋ฐ์ต๋๋ค.
์ ๋ extension์ผ๋ก ํด์คฌ์ด์.
์์๋ฐ์ผ๋ฉด ํ์๋ก presentationAnchor ๋ฉ์๋๋ฅผ ๊ตฌํํด์ค๋๋ค.
>> presentationAnchor : ๋ฒํผ์ ๋๋ ์ ๋ Apple ๋ก๊ทธ์ธ์ ๋ชจ๋ฌ ์ํธ๋ก ํ์ํ๋ ํจ์์ ๋๋ค.
๋ํ, ์ฐ๋ ์ฑ๊ณต ์ ๋ฐ์์ฌ ์ ๋ณด๋ฅผ ์ฒ๋ฆฌํด์ค๋๋ค. ์ ๊ณต๋ฐ๋ ์ ๋ณด๋ ์๋์ ๊ฐ์ต๋๋ค.
user - ์ ์ ๊ณ ์ ์๋ณ์
fullName - ์ ์ ์ด๋ฆ
email - ์ ์ ์ด๋ฉ์ผ
authorizationCode - ์ธ์ฆ์ฝ๋
identityToken - ์ ์ ์ ํ ํฐ >> ์ ์ ๋ง๋ค ๋ค๋ฅด๊ฒ ๊ฐ์ง๊ณ ์๋ ๊ณ ์ ํ ๊ฐ์ผ๋ก ํ ํฐ ์ ํจ์ฑ ๊ฒ์ฌ๋ฅผ ํ๊ธฐ ์ํด์ ํ์ํ ๊ฐ!
extension SignInAppleVC: ASAuthorizationControllerPresentationContextProviding, ASAuthorizationControllerDelegate{
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return self.view.window!
}
// Apple ID ์ฐ๋ ์ฑ๊ณต ์
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
switch authorization.credential {
// Apple ID
case let appleIDCredential as ASAuthorizationAppleIDCredential:
// ๊ณ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
let userIdentifier = appleIDCredential.user
let fullName = appleIDCredential.fullName
let email = appleIDCredential.email
let idToken = appleIDCredential.identityToken!
let tokeStr = String(data: idToken, encoding: .utf8)
print("User ID : \(userIdentifier)")
print("User Email : \(email ?? "")")
print("User Name : \((fullName?.givenName ?? "") + (fullName?.familyName ?? ""))")
print("token : \(String(describing: tokeStr))")
default:
break
}
}
// Apple ID ์ฐ๋ ์คํจ ์
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
// Handle error.
}
}
์ต์ด ๋ก๊ทธ์ธ ์ดํ์๋ email๊ฐ์ด ์๊พธ nil์ด ๋์ค๋๋ฐ, ์ด๋ฏธ ๊ฐ์ ์ด ๋๊ธฐ ๋๋ฌธ์ email๊ฐ์ด nil์ด ๋์ต๋๋ค.
์ฑ์ ์ ํ ์์ด๋ ์ฐ๋์ ์ญ์ ํ๊ณ ๋ค์ ๋ก๊ทธ์ธํ๋ฉด ๋ค์ ๋์ต๋๋ค.
*[์ฐ๋ ์ญ์ ]
์ค์ > ๊ณ์ > ์ํธ > ์ ํ ์์ด๋ ์ฌ์ฉ ์ฑ > ํด๋น ์ฑ > ์์ด๋ ์ฌ์ฉ ์ค๋จ
2-3. Request
๋ก๊ทธ์ธ ๋ฒํผ ํด๋ฆญ ์ ์ํํ ๋ก์ง์ ๋จผ์ request ์์ฑ ํ request๋ฅผ ๋ณด๋ด์ค controller๋ฅผ ์์ฑํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ performRequest()๋ก ์์ฒญ์ ๋ณด๋ ๋๋ค. ๋งค์ฐ ๊ฐ๋จ ^^
class SignInAppleVC: UIViewController {
//์ ํ ์์
๋ก๊ทธ์ธ
@IBAction func appleLogin(_ sender: Any) {
let appleIDProvider = ASAuthorizationAppleIDProvider()
let request = appleIDProvider.createRequest()
request.requestedScopes = [.fullName, .email]
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
authorizationController.delegate = self
authorizationController.presentationContextProvider = self
authorizationController.performRequests()
}
}
[์คํ ํ๋ฉด]
[์ฑ๊ณต ๊ฒฐ๊ณผ]
+ ์ ํ ์ ๊ณตํ๋ ๋ฒํผ ์ฌ์ฉํ๊ธฐ(์ต์ )
์๋ ์ฝ๋๋ฅผ ์ถ๊ฐํ๊ณ ,
let appleButton = ASAuthorizationAppleIDButton(type: .signIn, style: .whiteOutline)
์์ ํ์ ์ด๋ ์คํ์ผ์ ๋ณ๊ฒฝํด์ ์ ํ ๋ก๊ทธ์ธ ๋ฒํผ ์ฌ์ฉ ๊ฐ๋ฅํฉ๋๋ค.
func setupProviderLoginView() {
let appleButton = ASAuthorizationAppleIDButton(type: .signIn, style: .whiteOutline)
appleButton.addTarget(self, action: #selector(handleAuthorizationAppleIDButtonPress), for: .touchUpInside)
self.view.addSubview(appleButton)
appleButton.translatesAutoresizingMaskIntoConstraints = false
appleButton.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
appleButton.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
appleButton.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
appleButton.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
}
@objc func handleAuthorizationAppleIDButtonPress() {
let appleIDProvider = ASAuthorizationAppleIDProvider()
let request = appleIDProvider.createRequest()
request.requestedScopes = [.fullName, .email]
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
authorizationController.delegate = self
authorizationController.presentationContextProvider = self
authorizationController.performRequests()
}
Step 3. ์ ํ ๋ก๊ทธ์ธ ์ํ ํ์ธ
๋ค์์ ์ฑ ์คํ ์ ์ ํ ๋ก๊ทธ์ธ ์ํ ํ์ธํ๋ ๋ฐฉ๋ฒ์ ๋๋ค.
์๋์ ๊ฐ์ด, AppDelegate์์ application(_:didFinishLaunchingWithOptions:)์ ํจ์๋ฅผ ์ถ๊ฐํฉ๋๋ค.
[์ ํ ๋ก๊ทธ์ธ ์ํ๊ฐ]
- authorized : ํด๋น User Identifier ๊ฐ์ด ์ฑ๊ณผ ์ฐ๊ฒฐ์ด ํ๊ฐ๋์ด์๋ค.
- revoked : ํด๋น User Identifier ๊ฐ์ด ์ฑ๊ณผ ์ฐ๊ฒฐ์ด ์ทจ์๋์ด์๋ค.
- notFound : ํด๋น User Identifier ๊ฐ์ด ์ฑ๊ณผ ์ฐ๊ฒฐ์ ์ฐพ์ ์ ์๋ค.
//applelogin ์ํ ํ์ธ
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
let appleIDProvider = ASAuthorizationAppleIDProvider()
//forUserID = userIdentifier
appleIDProvider.getCredentialState(forUserID: "001281.9301aaa1f617423c9c7a64b671b6eb84.0758") { (credentialState, error) in
switch credentialState {
case .authorized:
// The Apple ID credential is valid.
print("ํด๋น ID๋ ์ฐ๋๋์ด์์ต๋๋ค.")
case .revoked:
// The Apple ID credential is either revoked or was not found, so show the sign-in UI.
print("ํด๋น ID๋ ์ฐ๋๋์ด์์ง์์ต๋๋ค.")
case .notFound:
// The Apple ID credential is either was not found, so show the sign-in UI.
print("ํด๋น ID๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค.")
default:
break
}
}
//์ฑ ์คํ ์ค ๊ฐ์ ๋ก ์ฐ๊ฒฐ ์ทจ์ ์
NotificationCenter.default.addObserver(forName: ASAuthorizationAppleIDProvider.credentialRevokedNotification, object: nil, queue: nil) { (Notification) in
print("Revoked Notification")
// ๋ก๊ทธ์ธ ํ์ด์ง๋ก ์ด๋
}
return true
}
[์คํ ํ๋ฉด]