Firebase Authentication
Updated:
🔷 Firebase / Firebase Authentication
Firebase?
Firebase official documentation - https://firebase.google.com/docs
-
사용자 인증(Authentication), 실시간 DB(Cloud Firestore, Realtime Database), push 알림을 원격으로 앱 내의 특정 사용자, 전체 사용자에게 app 표시를 할 수 있는기능(Cloud Messaging) 등을 제공합니다
-
특정 segment 에서 해당되는 사용자를 분류하기(Google Analytics), 분류하는 사용자에게 별도의 메세지, 화면을 보여주는것(A/B Testing, Remote Config), 사용자 행동분석 데이터 수집 (Google Analytics)의 기능을 제공합니다
-
Firebase 를 통해서 통합 backend service 를 제공함으로써, 별도의 개발없이 서버리스로 대체해서 DB 환경을 구축 할 수 있습니다.
Firebase Auth
OAuth란?
-
사용자 인증 방식에 대한 업계 표준
-
ID/PW 를 노출하지 않고 OAuth를 사용하는 업체의 API 접근 권한을 위임 받음
-
기본 개념
-
User Service Provider에 계정을 가지고 있는 사용자
-
Consumer Service Provider 의 API(제공 기능)를 사용하려는 서비스 (앱, 웹 등)
-
Service Provider OAuth를 사용하여 API 를 제공하는 서비스
-
Access Token 인증 완료 후 Service Provider의 제공 기능을 이용할 수 있는 권한을 위임받은 인증 키
-
-
예시 flow: User 사용자가 기기로 App 에서 google 로 로그인 요청 -> App 에서 Google(Service Provider) 에 request Token 을 요청 -> Google(Service Provider) 가 User에게 권한 위임 확인 요청을 하게 됨(AppName 이 Google 계정에 엑세스 하려고 합니다.) -> User가 권한 위임을 승인함 -> Google(Service Provider) 가 App 에 Access Token(사용자의 email, 이름등 google 이 가지고 있는 사용자의 정보를 포함) 을 보냄 -> App 에서 로그인 완료 승인됩을 유저에 UI에 나타나게 됨
-
위의 역활들을 Firebase 에서 대신 처리 하게 되는것임 (Request Token, Access Token)
Firebase Authentication 제공 업체
🔷 Firebase Authentication 초기 설정
-
Firebase console 에서 프로젝트 추가 한다음에, ios 앱을 추가하여 시작하기를 누르고 xcode 내의 프로젝트
Bundle identifier
를 Apple 번들 ID 에 추가 시킵니다. 그리고, 앱 등록을 합니다 -
구성파일에 생성된
GoogleService-Info.plist
를 다운로드해서 프로젝트 root 경로에 추가 시킵니다 -
CocoaPods 을 통해 Firebase SDK 패키지를 프로젝트 안에 설치 합니다
pod init
# in Podfile
...
# Pods for 08_firebase_login_app
pod 'Firebase/Auth'
...
- 추가하고 terminal 에서
pod install
해서 Firebase/Auth SDK 설치
설치 자세히 보기 - https://firebase.google.com/docs/ios/installation-methods?authuser=0#cocoapods
-
Pod 을 추가하면 xcode 를 workspace 로 변경하고 프로젝트 시작해야 됨
-
Root 경로에 AppDelegate 에 가서 firebase initialization 해줘야 App 에서 실행이 됩니다
import UIKit
import Firebase
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// Firebase init
FirebaseApp.configure()
return true
}
🔷 이메일/비밀번호 로그인/로그아웃
- Authentication 메뉴에 가서 시작하기 하고 제공 업체에서 email/password 를 활성 화 시킵니다
// in EnterEmailViewController.swift
// MARK: Actions
@IBAction func tabNextBtn(_ sender: UIButton) {
// Firebase email/ password 인증
let email = emailTextField.text ?? "" // nil이면 optional 로 빈값으로 처리
let password = passwordTextField.text ?? ""
// Firebase 신규 사용자 생성
Auth.auth().createUser(withEmail: email, password: password) { [weak self] authResult, error in
guard let self = self else { return } // 일시적으로 Strong 참조 되게 함
self.showMainViewController() // 로그인이 재대로 끝났을때 mainView 로 이동
}
}
// MARK: Methods
// 로그인 성공시 mainViewController 로 이동 하는 method
private func showMainViewController() {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let mainViewController = storyboard.instantiateViewController(identifier: "MainViewController")
mainViewController.modalPresentationStyle = .fullScreen
navigationController?.show(mainViewController, sender: nil)
}
로그아웃 설정
// in MainViewController.swift
// MARK: Actions
@IBAction func tabLogoutBtn(_ sender: UIButton) {
// 로그아웃 method
let firebaseAuth = Auth.auth()
do { // error 가 발생하지 않으면
try firebaseAuth.signOut()
// RootViewController 로 이동
self.navigationController?.popToRootViewController(animated: true)
} catch let singOutError as NSError {
debugPrint("ERROR : signout \(singOutError.localizedDescription)")
}
}
🔷 Google 로그인/로그아웃
사전작업
- 먼저 firebase 사이트에서 Google 을 sign-in-method 제공업체로 등록 합니다
- Google login 을 사용하기 위해서는 추가로 Podfile 에서 googleSignIn 페키지를 설치해 줍니다
# in Podfile
target '08_firebase_login_app' do
# Comment the next line if you don't want to use dynamic frameworks
use_frameworks!
# Pods for 08_firebase_login_app
pod 'Firebase/Auth'
pod 'GoogleSignedIn'
end
- Google 로그인을 사용하려면, 맞춤 URL schema 를 구성해주여야 합니다. 처음 firebase 연결에 사용된
GoogleService-info.plist
파일에서REVERSED_CLIENT_ID
값을 복사해서 프로젝트Targets
의Info
에서URL Types
에URL Schemes
에 복사한 값은 붙여 넣기 해 줍니다 (이 값은 앱서비스마다 각각 다스 값을 가지고, 이 값을 통해서 Google 은 권한을 위임할것을 구분하게 됨)
Google SignIn delegate protocol 추가
Google 로 로그인 official reference - https://firebase.google.com/docs/auth/ios/google-signin?hl=ko#swift
GoogleSignIn v.6.0.0 기준 - https://developers.google.com/identity/sign-in/ios/release
변경된 중요 checkPoint (v.6.0.0 이후)
📌 GIDSignIn sharedInstance is now a class property.
-
기존에 method 로 제공되었던
sharedInstance()
가 class 의 property 로 변경되었습니다 -
GIDSignIn.sharedInstance()
=>GIDSignIn.sharedInstance
📌 AppDelegate.swift
에서 GIDSignInDelegate
자체가 삭제 되었습니다(따로 delegate 를 구현하지 않아 도 됩니다)
(The GIDSignInDelegate protocol has been removed in favor of GIDSignInCallback and GIDDisconnectCallback blocks.)
📌 GIDSignInButton
no longer makes calls to GIDSignIn
internally and will need to be wired to an IBAction
similar in order for you to call signInWithConfiguration:presentingViewController:callback:
to initiate a sign-in flow. (GIDSignInButton 이 자동적으로 GIDSignIn 을 호출하지 않으므로 우리가 기존에 AppDelegate 내에 GIDSignInDelegate 을 통해 구현한 것을 googleLoginButtonAction IBAction 메소드 내에 구현해주어야 합니다)
// AppDelegate.swift
import UIKit
import Firebase
import GoogleSignIn
@main
class AppDelegate: UIResponder, UIApplicationDelegate{
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
// Firebase init
FirebaseApp.configure()
return true
}
// Google 의 인증 process 가 끝날때, app 이 수신하는 url을 처리하는 method
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
return GIDSignIn.sharedInstance.handle(url)
}
.....
}
// in LoginViewController.swift
// MARK: Action
// Google Login action
@IBAction func tapGoogleLoginBtn(_ sender: UIButton) {
// 버튼 누르면 google login webView 가 나오게 하는 logic
//
guard let clientID = FirebaseApp.app()?.options.clientID else { return }
let config = GIDConfiguration(clientID: clientID)
GIDSignIn.sharedInstance.signIn(with: config, presenting: self) { [unowned self] user, error in
if let error = error {
print("ERROR", error.localizedDescription)
return
}
guard let authentication = user?.authentication,
let idToken = authentication.idToken else { return }
let credential = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: authentication.accessToken)
// 로그인 완료된 credential 값을 mainViewController 에 넘기는 method 실행
Auth.auth().signIn(with: credential) { _, _ in
self.showMainViewController()
}
}
}
// MARK: Methods
// login 된 credeatial 값을 mainViewController 에 넘기는 method
private func showMainViewController() {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let mainViewController = storyboard.instantiateViewController(identifier: "MainViewController")
mainViewController.modalPresentationStyle = .fullScreen
UIApplication.shared.windows.first?.rootViewController?.show(mainViewController, sender: nil)
}
Change password
- Firebase 는 사용자 관리에대한 다양한 method 등을 제공하고 있는데, 가장 자주 사용되는 비밀번호 것이 비밀번호 변경입니다.
소셜 ID 로 로그인 한 경우에는 App 자체 내에서 비밀번호 변경은 할 수 없고, email/ password 방식으로 등록한 계정에 한해서 sendPasswordReset()
을 통해서 reset 가능한 email 을 보낼 수 있습니다
// in mainViewController.swift
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// view에 navigation 보이지 않기
navigationController?.navigationBar.isHidden = true
// 로그인시 넘겨 받은 email 화면에 나타내기
let email = Auth.auth().currentUser?.email ?? "User"
welcomeLabel.text = """
Welcome.
\(email)
"""
// resetPasswordBtn 보이게 하기 (google Signin 경우에는 resetPasswordBtn 을 숨김
let isEmailLogin = Auth.auth().currentUser?.providerData[0].providerID == "password"
resetPasswordBtn.isHidden = !isEmailLogin
}
// Reset password action
@IBAction func tabResetPasswordBtn(_ sender: UIButton) {
// Google Auth 기능을 통해서 사용자의 email 에 reset 할 수 있는 email 을 보내게 됨
let email = Auth.auth().currentUser?.email ?? ""
Auth.auth().sendPasswordReset(withEmail: email, completion: nil)
}
🔷 Apple 로그인/로그아웃
-
2020년 이후 앱 심사 정책에 따르면, App 내의 로그인 방식으로 social 방식이 포함되어 있는 경우(예, 페이스북, 카카오, 네이버 등) 반드시 애플개정을 통한 로그인도 App 내에서 제공하게 되는 규정이 있습니다.
-
만약 Google 로그인 기능을 제공하는데, Apple 로그인을 제공하지 않으면 AppStore 에 앱 심사에서 반려되어 앱을 올릴 수 없습니다. 그래서 소셜방식의 로그인을 제공하는 App 일 경우 반드시 Apple 로그인을 제공해야 합니다
Apple로 로그인에 대한 신규 가이드라인 - https://developer.apple.com/kr/news/?id=09122019b
- 추후, 유료결제후 내용이 업데이트 될 예정입니다
For more Details Code - https://github.com/jacobkosmart/fireAuth-iOS-practice
🔶 🔷 📌 🔑 👉
🗃 Reference
firebaseAuth-iOS-practice code - https://github.com/jacobkosmart/fireAuth-iOS-practice.git
firebase documentation - https://firebase.google.com/docs/auth/ios/start
How to Sign in to Your iOS App with Email/Password Using Firebase Authentication - https://medium.com/firebase-developers/ios-firebase-authentication-sdk-email-and-password-login-6a3bb27e0536
fastcampus - https://fastcampus.co.kr/dev_online_iosappfinal
Leave a comment