안녕하세요. KataRN입니다.
드디어 마지막 애플로그인, 로그아웃, 회원정보 수정 입니다.
애플은 2019년 애플 로그인 기능을 발표했습니다. 동시에 앱 내에 다른 소셜 로그인 서비스를 사용하고 있다면...
반드시! 애플 로그인을 제공해야 한다는 심사지침도 함께 내놓았습니다.
FirebaseAuth를 이용하기 위한 사전지식이 필요하신 분들은 아래 링크 참고 부탁드립니다.
구글로그인도 있어요~
https://katarnios.tistory.com/45
https://katarnios.tistory.com/46
참고사항
애플개발자 멤버십 가입이 되어있어야 가능합니다.
파이어베이스(https://console.firebase.google.com/project/_/authentication/users)에 접속합니다.
이미지대로 따라서 설정해주세요.
이제 앱으로 돌아가서 설정을 해줍시다.
이제 애플개발자 페이지로 이동합시다.
위에서 말씀드렸듯이 애플 개발자 멤버십 가입이 되어있어야 진행가능합니다.
자 이렇게 누르면 3가지를 써줘야합니다.
1번은 App ID를 선택.
2번과 3번은 다시 파이어베이스로 가서 가져옵시다.
후... 길다..
1. 애플 로그인
이제 앱으로 돌아가 애플로그인을 만들어줍시다.
잠깐!
애플 로그인버튼 규격 준수해야합니다. 링크 참고해주세요.(https://bebesoft.tistory.com/35)
import AuthenticationServices
import CryptoKit
fileprivate var currentNonce: String?
extension ViewController: ASAuthorizationControllerDelegate {
func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
if let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential {
guard let nonce = currentNonce else {
fatalError("Invalid state: A login callback was received, but no login request was sent.")
}
guard let appleIDToken = appleIDCredential.identityToken else {
print("Unable to fetch identity token")
return
}
guard let idTokenString = String(data: appleIDToken, encoding: .utf8) else {
print("Unable to serialize token string from data: \(appleIDToken.debugDescription)")
return
}
let credential = OAuthProvider.credential(withProviderID: "apple.com", idToken: idTokenString, rawNonce: nonce)
Auth.auth().signIn(with: credential) { authResult, error in
if let error = error {
print ("Error Apple sign in: %@", error)
return
}
// User is signed in to Firebase with Apple.
// ...
///Main 화면으로 보내기
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let mainViewController = storyboard.instantiateViewController(identifier: "MainViewController")
mainViewController.modalPresentationStyle = .fullScreen
self.navigationController?.show(mainViewController, sender: nil)
}
}
}
}
//Apple Sign in
extension ViewController {
func startSignInWithAppleFlow() {
let nonce = randomNonceString()
currentNonce = nonce
let appleIDProvider = ASAuthorizationAppleIDProvider()
let request = appleIDProvider.createRequest()
request.requestedScopes = [.fullName, .email]
request.nonce = sha256(nonce)
let authorizationController = ASAuthorizationController(authorizationRequests: [request])
authorizationController.delegate = self
authorizationController.presentationContextProvider = self
authorizationController.performRequests()
}
private func sha256(_ input: String) -> String {
let inputData = Data(input.utf8)
let hashedData = SHA256.hash(data: inputData)
let hashString = hashedData.compactMap {
return String(format: "%02x", $0)
}.joined()
return hashString
}
// Adapted from https://auth0.com/docs/api-auth/tutorials/nonce#generate-a-cryptographically-random-nonce
private func randomNonceString(length: Int = 32) -> String {
precondition(length > 0)
let charset: Array<Character> =
Array("0123456789ABCDEFGHIJKLMNOPQRSTUVXYZabcdefghijklmnopqrstuvwxyz-._")
var result = ""
var remainingLength = length
while remainingLength > 0 {
let randoms: [UInt8] = (0 ..< 16).map { _ in
var random: UInt8 = 0
let errorCode = SecRandomCopyBytes(kSecRandomDefault, 1, &random)
if errorCode != errSecSuccess {
fatalError("Unable to generate nonce. SecRandomCopyBytes failed with OSStatus \(errorCode)")
}
return random
}
randoms.forEach { random in
if remainingLength == 0 {
return
}
if random < charset.count {
result.append(charset[Int(random)])
remainingLength -= 1
}
}
}
return result
}
}
extension ViewController : ASAuthorizationControllerPresentationContextProviding {
func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
return self.view.window!
}
}
????? 갑자기 뭐가 많죠?
제가 임의로 만든것들은 아닙니다.
우선 Nonce에 대해 설명드릴게요.
Nonce 란?
- 암호화된 임의의 난수
- 단 한번만 사용할 수 있는 값
- 주로 암호화 통신을 할 때 사용
- 동일한 요청을 짧은 시간에 여러번 보내는 릴레이 공격 방지
- 정보 탈취 없이 안전하게 인증 정보 전달을 위한 안전장치
randomNonceString()은 암호화된 Nonce를 만듭니다.
startSigInWithAppleFlow()에서 애플ID 인증값을 요청할때 request를 생성해서 전달하는데요.
이때 Nonce를 포함해서 전달합니다.
이걸 통해 나중에 Firebase에서 무결성 검사를합니다.
Firebase와 Apple에서 제공하는 가이드라인대로 붙여넣었습니다.
제가 직접 손댄부분이 없다보니... 설명이 부족하죠..
참고로 시뮬레이터로는 작동안합니다.
테스트 기기를 이용해서 빌드해보세요.
2. 로그아웃
예외처리 (throws, do-catch, try) 를 이용했습니다.
그리고 Auth.auth().signOut()을 이용하여 로그아웃 처리 했습니다.
let firebaseAuth = Auth.auth()
do {
try firebaseAuth.signOut()
self.navigationController?.popToRootViewController(animated: true)
} catch let signOutError as NSError {
print ("Error signing out: %@", signOutError)
}
3. 회원정보 수정
간단하게 만들기 위해 변하게될 프로필을 코드에 포함시켰습니다.
let changeRequest = Auth.auth().currentUser?.createProfileChangeRequest()
changeRequest?.displayName = "KataRN"
changeRequest?.commitChanges { _ in
let displayName = Auth.auth().currentUser?.displayName ?? Auth.auth().currentUser?.email ?? ""
self.welcomeLabel.text = "환영합니다.\n\(displayName)님"
}
사실 2, 3번의 내용은 이전글에 같은내용이 있습니다. 참고부탁드립니다.ㅎㅎ
https://katarnios.tistory.com/45
오늘도 긴글 읽어주셔서 감사합니다.
'Old_SWIFT(221012) > 라이브러리이야기' 카테고리의 다른 글
Lottie 다루기 (0) | 2022.03.22 |
---|---|
Kingfisher 다루기 (0) | 2022.03.22 |
Firebase Auth 다루기 (2/3) (구글로그인) (0) | 2022.03.20 |
Firebase Auth 다루기 (1/3) (소개, 이메일 회원가입, 로그인, 로그아웃, 회원정보수정, 암호재설정) (0) | 2022.03.20 |
다양한 그래프 그리기(라이브러리 Charts 사용, 파이차트, 원차트 포함)(쉬움주의, 따라만해) (0) | 2021.12.22 |