DADAHAE's Log
비싼 장난감 가지고 노는 중 (❁´▽`❁)*✲゚*
[SwiftUI] Firebase의 GitHub 로그인으로 Auto Login 구현하기

2023.03.05 작성

Firebase를 사용한 GitHub OAuth 로그인에서 자동 로그인이 되도록 해야 한다.

같이 개발한 태영님은 다른 프로젝트에서 Firebase 이메일 로그인에서는 아래와 같은 형식으로 자동 로그인을 해주었다고 한다.

  • 기존 Firebase 이메일 로그인에서는 currentUser가 남아있어서 이게 nil인지 아닌지로 자동 로그인을 해줬다.

이게 GitHub도 가능할지 아닐지는 해봐야 알 것 같았다.

Firebase-GitHub 자동 로그인을 구현해보자!

 


 

Auto Login?

사용자가 직접 로그인하지 않고 시스템에서 필요한 로그인 과정을 수행하는 것.

사용자의 개입없이 시스템에 진입하는데 필요한 로그인 시퀀스를 수행하는 것

현재 GitSpace(22.03.05 기준)에는 Firebase의 Auth를 사용한 GitHub OAuth 로그인이 구현되어 있다. 그러나 사용자가 앱을 들어올 때마다 계속 로그인을 해주어야 한다. 아직 자동 로그인은 구현된 상태가 아니기 때문이다.

그래서 이미 로그인한 적이 있으면 내부적으로 로그인 과정을 처리해주는 자동 로그인을 구현하려고 한다. 이를 통해 사용자가 앱 사용을 더욱 원활하게 할 수 있도록 도울 예정이다.

 

 

 

Auto Login 구현을 향한 삽질

1️⃣ UserDefault 사용하기

iOS 앱에서 자동 로그인하는 방법을 찾아보는 도중에 UserDefault에 아이디와 패스워드를 저장하는 과정을 보았다. 아주 단순하지만 직관적인 자동 로그인이라고 생각했다.

  • 그러나 보안상 좋지 못할 것이라고 판단하여 이 방법을 선택하지 않았다.
  • 왜냐하면 UserDefault는 사용자 설정을 저장하기 위해 고안된 기술이긴 하지만, 패스워드처럼 사용자의 개인 정보는 담고있기에는 너무나 접근하기 쉽다. 차라리 Keychain으로 암호화된 데이터베이스에 저장한다면 괜찮을 것 같았다. 그래서 UserDefault에 아이디와 패스워드를 통째로 저장하는 방법을 선택하지 않았다.

 

 

2️⃣ Firebase Auth의 currentUser 사용하기

너무나 당연하지만, Firebase의 Auth를 사용해야지만 해당 라이브러리에서 제공하는 currentUser를 사용할 수 있다.

GitSpace의 경우에는 Firebase Auth(OAuth 제공자: GitHub)를 사용하고 있으므로 currentUser값으로 자동 로그인을 구현할 수 있다.

그러나 GitSpace 전반에 쓰이는 GitHub REST API 호출을 위해서는 GitHub 로그인시 리턴받는 access token이 절/대/적으로 필요하다. 이게 없으면 아무리 자동 로그인을 해서 메인 화면에 들어갔다 한들,,, 아무것도 불러올 수가 없다. (띠요요용)

그래서 Firebase Auth의 currentUser로 사용자가 이전에 로그인을 한 적이 있는지 확인하고(currentUser != nil), GitHub Signin을 시스템에서 다시 해주면 된다.

  • 그래서 앱의 첫 화면이 메모리에 로드될 때(onViewDidLoad: 직접 만든 수정자로, UIKit의 viewDidLoad와 동일한 역할을 함) 자동 로그인 분기처리를 하고 일반 로그인 시퀀스에서 사용되는 signin 메서드를 호출해줬는데 문제가 있었다.
  • GitHub OAuth 로그인을 시도하면 알아서 새로운 SafariView가 떠서 "나 지금 로그인 중이야"가 드러나버리게 된다. 화면이 전환되거나, progress을 보여주면서 로그인하는 과정은 보여주지 않아야 자연스러운데 이렇게 로그인 뷰를 딱 띄워버리면 .. 앱 사용이 매끄럽지 않게 된다.
  • 결과적으로 signin을 호출하는게 아니라 재인증(reauth)를 하는 메서드를 호출하는게 맞다고 판단했다. GitHub의 reauth 메서드는 Firebase에서 제공하고 있어서 나는 그 내부에 들어갈 로직만 작성하면 되었다.

Reauth를 할 때도 signin처럼 Firebase에서 제공하는 AuthCredential 타입의 credential이 필요하다. 그래서 첫 로그인시에 credential을 기기에 저장해두거나 getCredential로 받아오는 과정이 필요하다.

https://firebase.google.com/docs/auth/ios/github-auth#swift_5

  • 문제점
    • getCredential을 하면 SafariView가 뜬다. 비상비상... 그러면 getCredential은 쓸 수가 없다는 뜻이고, signin 메서드를 선택하지 않은 이유도 이 메서드 때문이라는 것이다. 으아아악
    • 그럼 진짜 credential을 기기에 저장해야하는데... 이게 타입이 Firebase에서 제공해준거라, Keychain에 제대로 저장이 될지 모르겠다. ㅠ

 

3️⃣ KeyChain에 credential을 저장해볼까?

어떤 걸 KeyChain에 저장할 것인가?

  • Firebase credential (type: AuthCredential)
  • Create > 처음 로그인을 하면 "credential"을 key로 가지는 KeyChain을 만든다.
    • 의문: key값이 결국 value 값을 가져오는 열쇠가 되는데, 이거를 일반 String으로 막 둬도 되나? 사용자가 가진 고유 값을 key로 해야 안전한거 아닌가?
    • kSecClass : kSecClassGenericPassword
    • kSecAttrAccount : "credential"
    • kSecValueData : AuthCredential
  • Read > 이후 자동 로그인을 할 때 KeyChain에 저장된 credential을 가져온다.
    • kSecClass : kSecClassGenericPassword
    • kSecAttrAccount : "credential"
    • kSecValueData : AuthCredential (나중에 해당 타입으로 형변환 필요)
    • kSecReturnAttributes : true (아이템 특성을 반환할지 여부를 나타내는 키)
  • Update > 사용자가 로그인을 하면 알아서 update함
  • Delete > 사용자가 로그아웃을 하면 해당 credential을 삭제함

그러나 Keychain에 credential을 저장하기엔 역부족이었다. 일단 credential 타입 자체를 저장할 수 없고, 타입을 바꾸기 어려웠다.

정말로 답이 없나? 이 credential만 있으면 기존 메서드로 reauth를 할 수 있는데... 다시 찾아보도록 하자.

 

 

결국 난 답을 찾았다.

GitHubAuthProvider.credential(withToken:) 을 사용하면 credential을 가져올 수 있고, 나는 AT만 미리 저장해두면 된다.

Firebase에 이런 메서드가 있다니... 공식문서에 너무 꽁꽁 숨겨져 있었다.

https://github.com/APPSCHOOL1-REPO/finalproject-gitspace/pull/280

 

[Feat] #263 GitHub Auto Login을 구현했습니다. by dahae0320 · Pull Request #280 · APPSCHOOL1-REPO/finalproject-gitspace

개요 및 관련 이슈 Firebase Auth Provider중에 하나인 GitHub 로그인의 자동 로그인을 구현합니다. 작업 사항 currentUser로 자동 로그인 분기 처리 Reauthenticate로 Auto Login 구현 주요 로직(Optional) GitHub Provider

github.com

위의 링크는 직접 구현하고 날린 PR이다. reauth 메서드가 async 메서드가 아니라서 async 구문에 사용하기 위해서는 withCheckContinuation을 사용해야 한다.

 

 


 

참고자료

  Comments,     Trackbacks