티스토리 뷰

스위프트/SwiftUI

[SwiftUI] - Apple 로그인 구현

강철곰탱이 2024. 1. 6. 14:55

 

 

애플에서는 앱에서 소셜 로그인을 지원하는 경우 무조건 애플 로그인도 같이 지원을 해야한다고 한다.

만약 애플 로그인 지원하지 않으면 앱 심사에서 떨어질 수 있다는 점,,

 

https://developer.apple.com/sign-in-with-apple/get-started/

 

 

1️⃣ Apple Developer에서 App ID 설정

 

애플 로그인을 지원하기 위해서는 애플 개발자 계정이 필수로 필요하다 ㅎㅎ

 

 

로그인 - Apple

 

idmsa.apple.com

 

애플 개발자 계정으로 로그인한 후 Certificates, Identifiers & Profiles에서 Identifiers를 생성해준다.

 

 

Description과 Bundle ID 적어주고, Capabilities에서 Sign In with Apple을 추가해준다.

 

 

여기까지하면 identifier 등록은 끝났다!!

 

2️⃣ 프로젝트에 Capabilities 추가

 

 

[Target -> Signing & Capabliities]에서 +Capability를 클릭해서 Sign In with Apple을 추가해준다.

 

 

그럼 아래와 같이 Sign In with Apple이 추가된 걸 확인할 수 있다.

 

 

 

3️⃣ 애플 로그인 로직 구현

 

🟡 OAuthUserData 구조체 생성

OAuthUser의 정보를 관리하기 위해 구조체를 만들어준다.

 

struct OAuthUserData {
    var oauthId: String = ""
    var idToken: String = ""
}

 

 

🟡 AppleOAuthViewModel

 

  • 애플 로그인 실행
func signIn() {
    let appleIDProvider = ASAuthorizationAppleIDProvider()//Apple ID 제공자를 생성
    let request = appleIDProvider.createRequest()//인증 요청을 생성
    request.requestedScopes = [.fullName, .email]//사용자로부터 전체 이름과 이메일을 요청

    //인증 요청을 처리할 컨트롤러를 생성
    let authorizationController = ASAuthorizationController(authorizationRequests: [request])
    authorizationController.delegate = self//이 뷰 모델을 인증 컨트롤러의 delegate로 설정
    authorizationController.presentationContextProvider = self//이 뷰 모델을 인증 컨트롤러의 프레젠테이션 컨텍스트 제공자로 설정
    authorizationController.performRequests()//인증 요청을 수행
}

 

 

  • 유저 정보 확인
extension AppleOAtuthViewModel: ASAuthorizationControllerPresentationContextProviding, ASAuthorizationControllerDelegate {
    /// Apple ID 연동 성공 시
    func authorizationController(controller _: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        switch authorization.credential {//인증 정보에 따라 다르게 처리
        case let appleIDCredential as ASAuthorizationAppleIDCredential://Apple ID 자격 증명을 처리
             
            let userIdentifier = appleIDCredential.user//사용자 식별자
            let fullName = appleIDCredential.fullName//전체 이름
            let idToken = appleIDCredential.identityToken!//idToken
            
            oauthUserData.oauthId = userIdentifier
            oauthUserData.idToken = String(data: idToken, encoding: .utf8) ?? ""
        }            
        default:
            break
        }
    }
}

 

 

  • presentationAnchor() 메서드 구현

 

presentationAnchor(for: ) 메서드는 ASAuthorizationControllerPresentationContextProviding 프로토콜의 필수 메서드로 apple 로그인 UI를 어느 뷰에 표시할지 지정할 수 있다.

 

apple 로그인 UI는 모달 형식으로 표시되어서 presentationAnchor를 사용해 어디에 표시할지 정할 수 있고, UIWindow 객체는 apple로그인 UI가 표시될 윈도우이다. 

 

func presentationAnchor(for _: ASAuthorizationController) -> ASPresentationAnchor {
    guard let window = UIApplication.shared.windows.first else {//현재 애플리케이션에서 활성화된 첫 번째 윈도우
        fatalError("No window found")
    }
    return window
}

 

  • 최종코드
import AuthenticationServices
import SwiftUI

// MARK: - AppleOAtuthViewModel

class AppleOAtuthViewModel: NSObject, ObservableObject {
    @Published var givenName: String = ""
    @Published var errorMessage: String = ""
    @Published var oauthUserData = OOAuthUserData()

    func signIn() {
        let appleIDProvider = ASAuthorizationAppleIDProvider()
        let request = appleIDProvider.createRequest()
        request.requestedScopes = [.fullName, .email]

        let authorizationController = ASAuthorizationController(authorizationRequests: [request])
        authorizationController.delegate = self
        authorizationController.presentationContextProvider = self
        authorizationController.performRequests()
    }

    func signOut() {
        // 로그아웃 로직 (필요에 따라 구현)
    }
}

// MARK: ASAuthorizationControllerPresentationContextProviding, ASAuthorizationControllerDelegate

extension AppleOAtuthViewModel: ASAuthorizationControllerPresentationContextProviding, ASAuthorizationControllerDelegate {
    /// Apple ID 연동 성공 시
    func authorizationController(controller _: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        switch authorization.credential {
        case let appleIDCredential as ASAuthorizationAppleIDCredential:
            let userIdentifier = appleIDCredential.user
            let fullName = appleIDCredential.fullName
            let idToken = appleIDCredential.identityToken!

            oauthUserData.oauthId = userIdentifier
            oauthUserData.idToken = String(data: idToken, encoding: .utf8) ?? ""

            if let givenName = fullName?.givenName, let familyName = fullName?.familyName {
                self.givenName = "\(givenName) \(familyName)"
            }
        default:
            break
        }
    }

    func presentationAnchor(for _: ASAuthorizationController) -> ASPresentationAnchor {
        guard let window = UIApplication.shared.windows.first else {
            fatalError("No window found")
        }
        return window
    }

    func authorizationController(controller _: ASAuthorizationController, didCompleteWithError error: Error) {
        errorMessage = "Authorization failed: \(error.localizedDescription)"
    }
}

 

 

🟡 간단한 버튼 View

 

import SwiftUI

struct ContentView: View {
    @StateObject private var appleViewModel = AppleOAtuthViewModel()
    
    var body: some View {
        VStack {
            Button(action: {//버튼 클릭시 애플 로그인 로직 실행
                appleViewModel.signIn()
            }) {
                Text("Sign In with Apple")
                    .frame(width: 280, height: 45)
                    .cornerRadius(8)
            }
            .padding()
            
            if !appleViewModel.givenName.isEmpty {
                Text("Welcome, \(appleViewModel.givenName)")
                    .padding()
            } else {
                Text("Not Logged In")
                    .padding()
            }
            
            if !appleViewModel.errorMessage.isEmpty {
                Text("Error: \(appleViewModel.errorMessage)")
                    .foregroundColor(.red)
                    .padding()
            }
        }
        .padding()
    }
}

 

✋ 최종 결과물 !!

 

아래와 같이 버튼을 누르면 애플 로그인 UI가 모달으로 나오고 로그인 완료 후 유저 정보를 가져오는 걸 확인할 수 있다.

 

 

주의할 점!

Apple 로그인은 사용자가 처음 로그인할 때만 fullName과 email 정보를 요청할 수 있다.
이후 로그인 시에는 이러한 정보가 자동으로 제공되지 않기 때문에 사용자 정보가 필요한 경우 첫 로그인 시 정보를 백엔드 서버에 저장해야 한다고 한다,,,
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함