티스토리 뷰

22년 3월 21일 업데이트

(짝짝) GMT+9 22년 3월 9일을 기준으로 이 포스트에서 다뤘던 PR이 GoogleSignIn-iOS 프로젝트에 머지되었습니다.

다시 말해... 이 글에서 코드를 수정하라는 부분은, 이제 새로운 버전이 릴리즈 된다면 수정할 필요가 없어지는 거겠죠!!

크 구글 프로젝트에 PR 날리고 머지 된다니 저도 언젠가 해보고 싶네요. 

해당 PR링크를 남깁니다.

https://github.com/google/GoogleSignIn-iOS/pull/30

 

Add the option to choose additional scopes at sign-in by AntonKozlovskyi · Pull Request #30 · google/GoogleSignIn-iOS

 

github.com


(본 이슈 참고)

GoogleSignIn-iOS 6.0.0 이상 버전에서는 로그인을 요청할 때 한 번에 다른 권한까지 같이 요청할 수 없게 변경되었습니다. Incremental authorization pattern에 맞춰, 사용자에게 추가 권한이 필요한 시점(ex: 구글 드라이브 접근)에 요청하도록 변경되었습니다. 그래서 첫 구글 로그인에는 email, userId, openid 정도만 얻고, drive.readonly를 또 요청해야 합니다.

예를 들면 v6.0 이전에 구글 드라이브 권한이 필요한 경우 다음과 같이 구현했을 것입니다.

 GIDSignIn.sharedInstance().delegate = self 
 GIDSignIn.sharedInstance().uiDelegate = self 
 GIDSignIn.sharedInstance().scopes = [kGTLRAuthScopeDrive]


반면 v6.0부터는 델리게이트 패턴이 없어지고 scopes 또한 최초 로그인 시점에는 요청할 수 없게 되었습니다. 그래서 drive.readonly 등과 같은 권한은 GIDSignIn.addScopes(_:presenting:callback:)으로 추가 요청하도록 변경되었습니다(swift 인터페이스를 바탕으로 작성). 코드는 다음과 같습니다.

GIDSignIn.sharedInstance.signIn(with: signConfiguration, presenting: self, additionalScopes: [kGTLRAuthScopeDriveReadonly]) { user, error in 
	if let error = error { 
    	return 
    } 
    
    guard let user = user else {
    	return 
    } 
    
    GIDSignIn.sharedInstance.addScopes([kGTLRAuthScopeDriveReadonly], presenting: self) { user, error in 
    	if let error = error {
    		return 
    	} 
        
        guard let user = user else { 
        	return 
        } 
        
        service.authorizer = user.authentication.fetcherAuthorizer() // GTLRDriveService 
    } 
}

그런데 이렇게 구현하게 되면 사용자에게 두 번의 권한 요청 플로우를 순차적으로 보여줘야하고(권한 요청 Alert, ModalView가 두 번씩 뜨게 됨), 별로 좋지 못한 사용자 경험을 주게 됩니다.


해결방법

가장 간단한 해결방법은 6.0.0 이하의 버전을 사용하는 겁니다. 이와 관련해서는 다른 글들이 많으니 패스하고, 여기선 6.0.0 버전을 사용하기위해 직접 라이브러리를 건드려서 해결해보겠습니다.
다행히도 6.0.0 부터 GoogleSignIn-iOS가 오픈 소스로 전환되면서 직접 커스텀해서 쓸 수 있게 되었습니다.
(https://developers.google.com/identity/sign-in/ios/release)


먼저 GIDSignIn.signIn(with:presenting:callback:) 코드를 타고 들어가보면 다음과 같습니다.

GIDSignIn.m // 지금 예시에선 아래 -> 위 순으로 메소드 호출

signInWithConfiguration:presentingViewController:callback:,
signInWithConfiguration:presentingViewController:hint:callback: 순으로 호출되는 걸 볼 수 있습니다.

두 번째로 호출되는 signInWithConfiguration:presentingViewController:hint:callback: 에서 GIDSignInInternalOptions라는 객체를 생성하여 signInWithOptions: 메소드에 넘기고 있으니 또 해당 메소드를 살펴보겠습니다.

GIDSignIn.m
GIDScopes.m

GIDSignInInternalOptions에서 scopes를 지정하는 걸 알 수 있고, scopesWithBasicProfile: 은 이메일, 프로필을 기본 권한으로 두고 있는 걸 볼 수 있습니다. 이후 추가 권한이 필요하다면 GIDSignIn.addScopes(_:presenting:callback:) 을 통해서 얻어야겠죠.

그렇다면 최초 로그인 시에 필요한 권한을 같이 요청할 수 있도록 변경하는 건 로그인 요청 전에 GIDSignInInternalOptions를 수정해주면 될 것 같습니다(여기까지만 보면 근거가 좀 부족할 수 있어서 뒤에 메소드 흐름도 같이 봐야하지만 너무 길어지고, 저도 다 이해하지 못하여서 패스합니다).

맨 위 링크의 이슈를 타고 들어가면 이미 여러 개발자분들께서 적절한 구현을 시도한 걸 볼 수 있습니다. 처음에 제가 시도하던 방식과 유사하면서 더 깔끔하게 기능을 추가한 분이 계셔서, 해당 PR을 참고 링크로 달아둡니다. 해당 PR을 참고하여 GIDSignIn.h, GIDSignIn.m, GIDSignInInternalOptions.h, GIDSignInInternalOptions.m 파일을 수정하고 사용하시면 되겠습니다. 수정 후에는 이전 버전과 동일하게 사용자에게 한 번의 로그인 요청으로 필요한 여러 권한을 동시에 요청할 수 있습니다.

로그인 시점에 scopes 추가하기 PR: https://github.com/google/GoogleSignIn-iOS/pull/67

로그인 시점에 scopes 추가하기 PR(위 링크보다 더 이전에 다뤄진 PR. 6.2.0 릴리즈에 반영예정): https://github.com/google/GoogleSignIn-iOS/pull/30

 

Add the option to choose additional scopes at sign-in by AntonKozlovskyi · Pull Request #30 · google/GoogleSignIn-iOS

 

github.com

개인적인 생각

v6.0.0으로 올라가면서 정책상 권한 요청 방식을 필요한 시점에 획득하도록 변경한 구글의 선택은 이해가 됩니다(저같은 게 이해하니 마니 중요하진 않겠지만 ㅋㅋ). 애플도 HIG에서 디바이스 권한 요청 시에는 필요한 시점 그 순간에 요청하도록 권장하고 있는 걸 보면 아마 같은 맥락이지 않을까 싶습니다. 대강 '사용자가 어떤 행동을 하려고 할 때, 특정 추가 권한이 필요함을 인지시키기' 정도라고 생각합니다.

다만 지금처럼 라이브러리의 동작이 전과 달라졌다면 선택권을 줬다면 더 좋았을 것 같습니다. 캘린더나 드라이브 권한 등의 획득 시점과 구글 로그인 시점이 동일하게 디자인된 앱의 경우, 로그인 플로우가 연속해서 두 번 타야하니... 처음에는 관련 정보도 잘 없어서 당황했었습니다.

아무튼 로그인 시점에 여러 권한을 요청하는 게 언제까지 가능할진 모르지만 우선은 지금처럼 수정해서 사용하고자 합니다.






댓글