먹고 기도하고 코딩하라

[Swift] iOS 구글 로그인 7.0.0 추가하기 본문

앱/Swift

[Swift] iOS 구글 로그인 7.0.0 추가하기

사과먹는사람 2023. 3. 6. 20:25
728x90
728x90

 

회사에서 3번째로 맡은 프로젝트는 구글 로그인 지원이다. 웹, 안드로이드에서는 구글 로그인이 지원되는데 iOS에는 해당 기능이 없어 이번에 추가하게 됐다.

예전에 해본 적은 있었는데, 다시 하려니 뭔가 헷갈려서 정리한다.

 

글을 수정하는 2023년 4월 기준 구글 로그인 최신 버전은 7.0.0이다.

5 버전과 좀 달라졌다 하는 건 GIDSignIn.sharedInstance를 어떻게 쓰느냐 여부와 SignIn을 delegate 방식으로 하느냐 바로 클래스 메소드를 사용하느냐 하는 약간의 차이만 있다. 

 

 

순서

(1) Podfile 혹은 SPM으로 GoogleSignIn 패키지를 추가한다.

 

(2) 파이어베이스 콘솔 들어가면 OAuth 2.0 클라이언트 ID를 확인할 수 있다.

com.googleusercontent.apps.클라이언트ID

이런 식으로 되어 있는데 이걸 프로젝트 파일 TARGET > Info > URL Types에 추가해준다.

Identifier, Role 이런 거 아무것도 설정 안 해도 되고 URL Schemes에 그것만 그대로 복사하면 된다.

또한, Info.plist에도 GIDClientID를 key로 하는 value를 등록해줘야 한다. 이 ClientID는 다음과 같이 끝나는 String이다.

.apps.googleusercontent.com

 

(3) iOS 13 이상만을 지원하는 앱이라면, SceneDelegate에 다음과 같이 추가해준다.

func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
    guard let url = URLContexts.first?.url else { return }
		let _ = GIDSignIn.sharedInstance.handle(url)
    }

만약 13 미만도 지원한다면, AppDelegate에서도 처리가 필요하다.

import GoogleSignIn

func application(
        _ app: UIApplication,
        open url: URL,
        options: [UIApplication.OpenURLOptionsKey: Any] = [:]
    ) -> Bool {
		// 이 부분이 핵심
		if GIDSignIn.sharedInstance.handle(url) {
        return true
    }
    return false
}

 

(4) 원래 7.0.0 미만 버전에서는 signIn 작업을 delegate로 따로 빼서 진행했는데, 이걸 그냥 GIDSignIn.sharedInstance 객체의 메소드로 붙여서 써주면 된다.

// Viewcontroller.swift
import GoogleSignIn

// before 7
override func viewDidLoad() {
        super.viewDidLoad()

        GIDSignIn.sharedInstance().delegate = self
        GIDSignIn.sharedInstance().presentingViewController = self
    }

func signInGoogle() {
		GIDSignIn.sharedInstance().signIn()
}

extension ViewController: GIDSignInDelegate {
    func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
        if let error = error {
            print(error)
            return
        }
        guard let authentication = user.authentication else { return }
				// 서버에 토큰을 보내기. 이 때 idToken, accessToken 차이에 주의할 것
    }
}


// 7.0.0에서는 GIDSignInDelegate를 따를 필요 없이, 그냥 바로 이렇게 쓰면 된다.
// import GoogleSignIn만 추가할 것
GIDSignIn.sharedInstance.signIn(withPresenting: self) { [weak self] signInResult, _ in
            guard let self,
                  let result = signInResult,
                  let token = result.user.idToken?.tokenString else { return }
            // 서버에 토큰을 보내기. 이 때 idToken, accessToken 차이에 주의할 것
        }

주의할 점은 signIn에서 토큰은 accessToken이 아니라 idToken을 사용해야 한다는 점이다. accessToken을 사용하면, Invalid username or invalid password 하면서 로그인 과정이 제대로 이뤄지지 않는다. 

GIDAuthentication에는 위와 같은 2가지 토큰이 있는데, 막간을 이용해 잠시 두 토큰의 차이를 살펴보자면...

  • idToken : An OpenID Connect ID token that identifies the user. Send this token to your server to authenticate the user there. For more information on this topic, see https://developers.google.com/identity/sign-in/ios/backend-auth (즉, idToken은 사용자를 식별할 수 있는 토큰으로, 인증을 위해 서버에 보내는 토큰이다)
  • accessToken : The OAuth2 access token to access Google services. (accessToekn은 구글 서비스에 접근할 수 있는 토큰이다)

즉, 서비스에 인증하는 토큰과 사용자를 식별하는 토큰이 나뉘어 있는 것이다.

 

 

(5) signOut도 다음과 같이 해주면 된다.

GIDSignIn.sharedInstance.signOut()

 

Firebase 통해서 구글 로그인하는 거랑은 또 다른 방법이다.

그건 FirebaseAuth도 추가해야 하는데 굳이 그것까지 쓸 필요가 없다.

하지만 FirebaseAuth를 통하면 복잡한 인증 과정을 파이어베이스가 대신 해주므로, 서버가 부실하거나 인증에 공수를 들일 자신이 없다면 FirebaseAuth를 추가해서 함께 사용하는 것도 추천한다.

 

만약 "No active configuration. Make sure GIDClientID is set in Info.plist" 같은 에러가 난다면, GIDSignIn config 객체를 잘 설정해주기만 하면 된다. References에 있는 스택오버플로우 답변이 도움이 될 것이다.

 

 

References

 

 

728x90
반응형
Comments