안녕하세요?
잠이 안와서 글 쓰러 하러왓서요
밀린 포스팅들 레쓰고...
사실 앱 심사 냈는데 2주째 리젝의 늪에서 씨름 중이라
억울하고 분하고 슬푸고 엉엉슨
그래도...하던건 해야하니까 마음 가담듬고 애플로 로그인 고고싱 ㅠㅠ
Apple은 다른 업체의 소셜 로그인 기능 제공 시 apple 로그인을 제공하지 않으면 100% 리젝당한다고 합니다.
그러니까 소셜 로그인 구현한다면 애플 로그인은 필수겠죠
참고로 애플 로그인 구현하려면 애플 개발자 계정이 필수랍니다!
그런데 이제 129,000원으로 유료인...
0. 애플 개발자 계정 등록하기
https://developer.apple.com/kr/programs/enroll/
멤버십 가입하기 - Apple Developer Program
Apple Developer Program에 등록하기 위해 필요한 사항을 알아보세요.
developer.apple.com
여기서 등록한 계정으로 Xcode에 로그인하시면 됩니다. (아마 다들 원래 되어있겠지만?)
관련 설정은 Xcode에서 Xcode > Settings > Account
가서 해당 애플 계정을 등록해주세요.
1. Identifiers 등록하기
링크 : https://developer.apple.com/account/resources/identifiers/list
로그인 - Apple
idmsa.apple.com

위 화면에서 식별자 들어가서

+ 버튼 클릭

App IDs 누르고 Continue

App 누르고 Continue

설명(영어로 적어야 함) 하고 번들 ID 적어주면 되고
(번들 아이디는 여기서 확인 가능합니다.)


아래로 쭉 내려서 Sign in with Apple 눌러주기
그럼 이 페이지에서 할 설정은 끝납니다!
2. Sign in with Apple 추가하기

앱 > TARGETS > + Capability 눌러서 Sign in with Apple 추가해주면 됨

참고로 위의 0, 1번 과정이 완료되어야 sign in with apple이 보여요!
2. Apple 로그인 버튼 만들기
그럼 초기 설정을 해줬으니 버튼을 만들어야겠죠?
https://developer.apple.com/kr/design/human-interface-guidelines/sign-in-with-apple
Apple로 로그인 | Apple Developer Documentation
‘Apple로 로그인’은 앱 및 웹사이트에 로그인할 수 있는 빠르고 개인적인 방법을 제공하여 사람들이 신뢰할 수 있는 일관적인 경험과 여러 계정 및 암호를 기억하지 않아도 되는 편리함을 누릴
developer.apple.com
위 링크에서 관련된 내용을 확인 할 수 있고요
저는 다른 소셜 로그인 버튼이랑 동일하게 만들려고 커스텀 로그인 버튼을 만들었답니다.
private let appleButton = UIButton().then {
$0.setTitle("Apple로 계속하기", for: .normal)
$0.setTitleColor(.white, for: .normal)
$0.titleLabel?.font = .systemFont(ofSize: 16, weight: .medium)
$0.backgroundColor = .black
$0.layer.cornerRadius = Metric.cornerRadius
$0.layer.borderWidth = 1.5
$0.layer.borderColor = UIColor.black.cgColor
}
private let appleIcon = UIImageView().then {
$0.image = UIImage(systemName: "apple.logo")
$0.tintColor = .white
$0.contentMode = .scaleAspectFit
}
이렇게 만들어서
3. 동작 함수 구독시키기
private func bindAction() {
...생략
// 애플 로그인
self.appleButton.rx.tap
.subscribe(onNext: { [weak self] in
self?.startSignInWithAppleFlow()
})
.disposed(by: disposeBag)
...생략
}
동작 함수 구독시켜요
4. 로직 구현하기
관련 내용은 공식 문서를 참고하세용
Apple을 사용하여 인증 | Firebase
의견 보내기 Apple을 사용하여 인증 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Firebase SDK를 통해 엔드 투 엔드 OAuth 2.0 로그인 과정을 실행하여 사용자가 A
firebase.google.com
근데 전 솔직히 아직 뭔소린지 모르겠네요 ; _ ;
4-1 필요한 프레임워크 import
먼저, LoginViewController 상단에 필요한 모듈을 임포트합니다.
import FirebaseAuth // Firebase 연동
import CryptoKit // Nonce(논스) 처리를 위해 사용
import AuthenticationServices // Apple 로그인 핵심 프레임워크
4-2. Delegate 채택 및 변수 정의
Apple 로그인 처리를 위해 LoginViewController에 두 개의 프로토콜을 채택하고, 생성된 논스 값을 임시로 저장할 변수를 정의합니다.
// MARK: Apple Login
extension LoginViewController: ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding {
// 현재 요청에서 사용된 논스(Nonce) 값을 임시로 저장합니다.
fileprivate var currentNonce: String?
// ... 나머지 코드
}
4-3 Nonce 생성 및 해시 함수
Apple 로그인은 ID 토큰 리플레이 공격(ID Token Replay Attack)을 방지하기 위해 논스(Nonce) 값을 필수로 요구합니다. 이 논스는 요청 시 생성되어 SHA256으로 해시된 후 Apple에 전달되며, 응답으로 받은 ID 토큰에 포함된 논스(해시되기 전)와 일치하는지 확인하여 요청의 유효성을 검증합니다.
라고 하네요 아 글쿤
코드를 보면, 안전한 논스 생성을 위한 두 개의 헬퍼 함수가 정의되어 있습니다.
1. randomNonceString()
길이 32의 무작위 문자열(Nonce)을 생성합니다. 이는 일회성 토큰으로 보안을 강화합니다.
private func randomNonceString(length: Int = 32) -> String {
precondition(length > 0)
var randomBytes = [UInt8](repeating: 0, count: length)
let errorCode = SecRandomCopyBytes(kSecRandomDefault, randomBytes.count, &randomBytes)
if errorCode != errSecSuccess {
fatalError(
"Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)"
)
}
let charset: [Character] =
Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._")
let nonce = randomBytes.map { byte in
// Pick a random character from the set, wrapping around if needed.
charset[Int(byte) % charset.count]
}
return String(nonce)
}
2. sha256(_:)
CryptoKit의 SHA256 함수를 사용하여 생성된 논스 문자열을 해시합니다.
private func sha256(_ input: String) -> String {
let inputData = Data(input.utf8)
let hashedData = SHA256.hash(data: inputData)
// 해시된 데이터를 16진수 문자열로 변환하여 반환
return hashedData.compactMap { String(format: "%02x", $0) }.joined()
}
4-4 Apple 로그인 요청 시작 (startSignInWithAppleFlow)
사용자가 "Apple로 계속하기" 버튼을 탭하면, 이 메서드가 호출됩니다.
func startSignInWithAppleFlow() {
// 1. 보안을 위한 Nonce(논스) 생성 및 저장
let nonce = randomNonceString()
currentNonce = nonce // 응답 검증을 위해 논스 값을 저장합니다.
// 2. Apple 인증 요청 생성
let request = ASAuthorizationAppleIDProvider().createRequest()
request.requestedScopes = [.fullName, .email] // 사용자에게 요청할 정보
// 3. 보안 논스 값 전달 (반드시 해시된 형태)
request.nonce = sha256(nonce) // SHA256 해시된 논스를 Apple 서버로 보냅니다.
// 4. 인증 컨트롤러 실행
let controller = ASAuthorizationController(authorizationRequests: [request])
controller.delegate = self
controller.presentationContextProvider = self
controller.performRequests() // Apple 로그인 팝업 실행
}
4-5 인증 완료 및 Firebase 연동 (didCompleteWithAuthorization)
인증이 성공적으로 완료되면 ASAuthorizationControllerDelegate의 이 메서드가 호출되며, 여기서 Firebase Authentication과 연동합니다.
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
guard let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential else { return }
// 1. 저장된 Nonce 값과 ID Token 추출 확인
guard let nonce = currentNonce else {
print("Invalid state: No login request was sent.")
return
}
guard let appleIDToken = appleIDCredential.identityToken,
let idTokenString = String(data: appleIDToken, encoding: .utf8) else {
print("Unable to fetch identity token.")
return
}
// 2. Firebase Apple 인증 정보 생성 (중요!)
// Nonce 값과 ID Token을 이용해 Firebase 인증 정보(Credential)를 생성합니다.
let credential = OAuthProvider.appleCredential(withIDToken: idTokenString,
rawNonce: nonce, // 저장된 원본 논스 값 전달
fullName: appleIDCredential.fullName)
// 3. Firebase 로그인 시도
Auth.auth().signIn(with: credential) { [weak self] authResult, error in
if let error = error {
print("Error during Firebase sign-in: \(error.localizedDescription)")
// 사용자에게 오류를 알리는 처리 필요
return
}
print("✅ Apple login success: \(authResult?.user.uid ?? "")")
self?.goHome() // 성공 시 다음 화면으로 전환
}
}
4-6 팝업 표시를 위한 앵커 제공 (presentationAnchor)
로그인 창(팝업)이 정상적으로 표시되려면 ASAuthorizationControllerPresentationContextProviding 프로토콜을 구현해야 합니다.
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
// 팝업이 표시될 윈도우를 반환합니다.
return view.window!
}
후... 이렇게 하면 드디어 애플 로그인 구현 끝!!! 🍎🍏
사실 아직 뭔소리인지 잘모르겠어요 ;;;
지피티 도움 받아서 엄청 오래 쓴 게시글이네요
이 글을 보고 도움이 되는 분들이 계셨으면....좋겠지만 그리 도움은 안될거 같네여 쩝
그럼 안녕히 계세요~!
'iOS > 흡구오디 -> 어딨쥐' 카테고리의 다른 글
| [흡구오디] 가 [어딨쥐]가 되었습니다. (0) | 2025.12.17 |
|---|---|
| [흡구오디] firebase firestore 문서 업데이트하기 (0) | 2025.10.24 |
| [흡구오디] Xcode - 앱 이름 변경하기 (0) | 2025.10.03 |
| [흡구오디] Swift - Firebase 구글 로그인 기능 구현하기 (0) | 2025.10.03 |
| [흡구오디] Swift - firebase Authentication로 이메일 로그인 구현하기 (0) | 2025.10.03 |
댓글