Giter Site home page Giter Site logo

fireauth-ios-practice's Introduction

πŸ” firebaseAuth-iOS-practice

스크란샷

πŸ“Œ κΈ°λŠ₯ 상세

  • Firebase Authentication κΈ°λŠ₯을 μ‚¬μš©ν•˜μ—¬ μ‚¬μš©μž 둜그인 κΈ°λŠ₯ κ΅¬ν˜„ν•©λ‹ˆλ‹€

  • Email / Password νšŒμ›κ°€μž… ν›„, 둜그인

  • Google ID 둜 둜그인

  • Apple ID 둜 둜그인

πŸ”‘ Check Point !

UI Structure

image

슬ᄅᅑ아드1

firebase-auth-practice

πŸ”· 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
	}

πŸ”· Email / password 둜그인 μ„€μ •

  • Authentication 메뉴에 κ°€μ„œ μ‹œμž‘ν•˜κΈ° ν•˜κ³  제곡 μ—…μ²΄μ—μ„œ email/password λ₯Ό ν™œμ„± ν™” μ‹œν‚΅λ‹ˆλ‹€

image

// 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 ID 둜그인

μ‚¬μ „μž‘μ—…

  • λ¨Όμ € firebase μ‚¬μ΄νŠΈμ—μ„œ Google 을 sign-in-method μ œκ³΅μ—…μ²΄λ‘œ 등둝 ν•©λ‹ˆλ‹€

image

  • 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 은 κΆŒν•œμ„ μœ„μž„ν• κ²ƒμ„ κ΅¬λΆ„ν•˜κ²Œ 됨)

image

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

image

λ³€κ²½λœ μ€‘μš” 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)
}

image

πŸ”· Apple ID 둜그인

μ‚¬μ „μž‘μ—…

Apple 계정을 μœ„ν•œ 둜그인 κΈ°λŠ₯을 μ œκ³΅ν•˜λ €λ©΄, Apple Developer ν”„λ‘œκ·Έλž¨μ— κ°€μž…μ„ ν•΄μ•Ό ν•©λ‹ˆλ‹€ (1λ…„ λ‹¨μœ„λ‘œ ꡬ독 ν•΄μ•Ό 됨) - 유료 결제 ν›„, μΆ”ν›„ μ—…λ°μ΄νŠΈ μ˜ˆμ •

Describing check point in details in Jacob's DevLog - https://jacobko.info/ios/ios-08/

❌ Error Check Point

πŸ”Ά λ‘œκ·ΈμΈμ‹œ 이미 같은 Email μž…λ ₯ ν•˜λ©΄ Error λ°œμƒ

image

Solving problem

  • 동일 κ³„μ •μœΌλ‘œ 계쏙 κ°€μž…ν•˜λŠ”κ²ƒμ„ λ°©μ§€ν•˜μ§€ ν•˜κ³ , 둜그인 μ²˜λ¦¬ν•˜κΈ°λ‘œ ν•˜κΈ°
		// Firebase μ‹ κ·œ μ‚¬μš©μž 생성
		Auth.auth().createUser(withEmail: email, password: password) { [weak self] authResult, error in
			guard let self = self else { return } // μΌμ‹œμ μœΌλ‘œ Strong μ°Έμ‘° 되게 함

			if let error = error {
				let code = (error as NSError).code
				// μ—λŸ¬ 처리
				switch code {
				case 17007: // 이미 κ°€μž…ν•œ 계정일 λ•Œ
					// 둜그인 ν•˜κΈ° 처리
					self.loginUser(withEmail: email, password: password)
				default:
					self.errorMessageLabel.text = error.localizedDescription // μ—λŸ¬ 메세지 ν‘œμ‹œ
				}
			} else { // error κ°€ λ°œμƒν•˜μ§€ μ•Šμ•˜μ„ 경우
				self.showMainViewController() // 둜그인이 μž¬λŒ€λ‘œ λλ‚¬μ„λ•Œ mainView 둜 이동
			}
		}
	}

		// 둜그인 method
	private func loginUser(withEmail email: String, password: String) {
		Auth.auth().signIn(withEmail: email, password: password) {[ weak self] _, error in
			guard let self = self else { return }

			if let error = error {
				self.errorMessageLabel.text = error.localizedDescription
			} else {
				self.showMainViewController()
			}
		}
	}

스크란샷


πŸ”Ά πŸ”· πŸ“Œ πŸ”‘ πŸ‘‰

πŸ—ƒ Reference

Jacob's DevLog - https://jacobko.info/firebaseios/ios-firebase-01/

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

fireauth-ios-practice's People

Contributors

jacobkosmart avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.