Naver Sign In iOS
Firebase Chat App: Naver Sign In & Sign Out
구현 목표
구현 태스크
- 네이버 API 사용 관련 개발자 등록 및 URL 작성
SceneDelegate
등 URL 패치 함수 구현
- 네이버 로그인 버튼 UI
- 네이버 로그인 완료 여부 확인
- 로그인 이후 사용자 정보 패치 HTTP GET 사용
- 파이어베이스 이메일/패스워드 기반 인증 연동
핵심 코드
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
...
let instance = NaverThirdPartyLoginConnection.getSharedInstance()
instance?.isNaverAppOauthEnable = true
instance?.isInAppOauthEnable = true
instance?.serviceUrlScheme = kServiceAppUrlScheme
instance?.consumerKey = kConsumerKey
instance?.consumerSecret = kConsumerSecret
instance?.appName = kServiceAppName
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
... NaverThirdPartyLoginConnection.getSharedInstance()?.application(app, open: url, options: options)
...
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
if let url = URLContexts.first?.url {
...
NaverThirdPartyLoginConnection.getSharedInstance()?.receiveAccessToken(url)
}
}
private let naverLoginInstance = NaverThirdPartyLoginConnection.getSharedInstance()
...
naverLoginInstance?.delegate = self
...
naverLoginInstance?.requestThirdPartyLogin()
- 네이버 로그인 버튼 클릭 시 해당 싱글턴 인스턴스의 로그인 함수 작동 (버튼에 함수 추가 필요)
extension SignInViewController: NaverThirdPartyLoginConnectionDelegate {
private func getUserFromNaver() {
guard
let isValidAccessToken = naverLoginInstance?.isValidAccessTokenExpireTimeNow(),
isValidAccessToken == true,
let tokenType = naverLoginInstance?.tokenType,
let accessToken = naverLoginInstance?.accessToken,
let url = URL(string: "https://openapi.naver.com/v1/nid/me")
else {
return
}
var urlRequest = URLRequest(url: url)
let authorization = tokenType + " " + accessToken
urlRequest.httpMethod = "GET"
urlRequest.addValue(authorization, forHTTPHeaderField: "Authorization")
URLSession.shared.dataTask(with: urlRequest) { data, response, error in
guard
let data = data,
let response = response,
error == nil else {
if let error = error {
print(error.localizedDescription)
}
return
}
do {
let result = try JSONDecoder().decode(NaverProfileModel.self, from: data)
let firstName = result.response.name
let lastName = result.response.nickname ?? ""
let email = result.response.email
let password = result.response.id
self.thirdPartyToFirebaseAuth(firstName: firstName, lastName: lastName, email: email, password: password, platform: .Naver)
} catch {
print(error.localizedDescription)
}
}
.resume()
}
func oauth20ConnectionDidFinishRequestACTokenWithAuthCode() {
print("Successfully Naver Sign In")
getUserFromNaver()
}
func oauth20ConnectionDidFinishRequestACTokenWithRefreshToken() {
print(naverLoginInstance?.accessToken)
getUserFromNaver()
}
func oauth20ConnectionDidFinishDeleteToken() {
print("Naver Token Deleted")
}
func oauth20Connection(_ oauthConnection: NaverThirdPartyLoginConnection!, didFailWithError error: Error!) {
print("DID FAIL")
print(error.localizedDescription)
}
}
- 네이버 로그인 유효 토큰 사용
- 로그인 확인 이후 액세스 토큰 이용 프로필 조회 API 사용
- 리턴받은 데이터로 파이어베이스 실시간 데이터베이스 조회
- 파이어베이스 이메일/패스워드 기반 인증에 적용하기
import Foundation
struct NaverProfileModel: Codable {
let resultcode: String
let message: String
let response: ResponseModel
}
struct ResponseModel: Codable {
let id: String
let name: String
let email: String
let nickname: String?
}
- 프로필에 필요한 이메일, 이름 정보만 요청(어플리케이션 API 사용에 필요)
private func thirdPartyToFirebaseAuth(firstName: String, lastName: String, email: String, password: String, platform: Platform) {
DatabaseManager.shared.userExists(with: email, at: platform) { exists in
if !exists {
print("THERE IS NO FIREBASE \(platform.rawValue) USER")
DatabaseManager.shared.insertUser(with: ChatAppUser(firstName: firstName, lastName: lastName, emailAddress: email, platform: platform))
FirebaseAuth.Auth.auth().createUser(withEmail: platform.rawValue.lowercased() + email, password: password) { result, error in
guard
let _ = result,
error == nil else {
if let error = error {
print(error.localizedDescription)
}
return
}
self.thirdPartyToSignIn(email: email, password: password, platform: platform)
}
} else {
print("THIS EMAIL EXISTS")
self.thirdPartyToSignIn(email: email, password: password, platform: platform)
}
}
}
private func thirdPartyToSignIn(email: String, password: String, platform: Platform) {
FirebaseAuth.Auth.auth().signIn(withEmail: platform.rawValue.lowercased() + email, password: password) { [weak self] result, error in
guard let self = self else { return }
guard
let _ = result,
error == nil else {
if let error = error {
print(error.localizedDescription)
}
return
}
print("Successfully \(platform.rawValue) Sign In")
NotificationCenter.default.post(name: .didSignInNotification, object: nil)
}
}
- 카카오톡 기반 데이터를 파이어베이스 인증에 사용한 함수를 리팩토링
- 이메일, 패스워드, 플랫폼 정보를 통해 파이어베이스 데이터정보 사용자 존재 파악 및 유저 생성 또는 로그인
구현 화면