Git Product home page Git Product logo

googlesignin-ios's Introduction

Version Platform License unit_tests integration_tests

Google Sign-In for iOS and macOS

Get users into your apps quickly and securely, using a registration system they already use and trust—their Google account.

Visit our developer site for integration instructions, documentation, support information, and terms of service.

Getting Started

Try either the Objective-C or Swift sample app. For example, to demo the Objective-C sample project, you have two options:

  1. Using CocoaPod's install method:
git clone https://github.com/google/GoogleSignIn-iOS
cd GoogleSignIn-iOS/Samples/ObjC/SignInSample/
pod install
open SignInSampleForPod.xcworkspace
  1. Using Swift Package Manager:
git clone https://github.com/google/GoogleSignIn-iOS
open GoogleSignIn-iOS/Samples/ObjC/SignInSample/SignInSample.xcodeproj

If you would like to see a Swift example, take a look at Samples/Swift/DaysUntilBirthday.

Google Sign-In on macOS

Google Sign-In allows your users to sign-in to your native macOS app using their Google account and default browser. When building for macOS, the signInWithConfiguration: and addScopes: methods take a presentingWindow: parameter in place of presentingViewController:. Note that in order for your macOS app to store credientials via the Keychain on macOS, you will need to sign your app.

Mac Catalyst

Google Sign-In also supports iOS apps that are built for macOS via Mac Catalyst. In order for your Mac Catalyst app to store credientials via the Keychain on macOS, you will need to sign your app.

Using the Google Sign-In Button

There are several ways to add a 'Sign in with Google' button to your app, which path you choose will depend on your UI framework and target platform.

SwiftUI (iOS and macOS)

Creating a 'Sign in with Google' button in SwiftUI can be as simple as this:

GoogleSignInButton {
  GIDSignIn.sharedInstance.signIn(withPresenting: yourViewController) { signInResult, error in
      // check `error`; do something with `signInResult`
  }
}

This example takes advantage of the initializer's default argument for the view model. The default arguments for the view model will use the light scheme, the standard button style, and the normal button state. You can supply an instance of GoogleSignInButtonViewModel with different values for these properties to customize the button. This convenience initializer provides parameters that you can use to set these values as needed.

UIKit (iOS)

If you are not using SwiftUI to build your user interfaces, you can either create GIDSignInButton programmatically, or in a Xib/Storyboard. If you are writing programmatic UI code, it will look something like this:

let button = GIDSignInButton(frame: CGRect(<YOUR_RECT>))

AppKit (macOS)

Given that GIDSignInButton is implemented as a subclass of UIControl, it will not be available on macOS. You can instead use the SwiftUI Google sign-in button. Doing so will require that you wrap the SwiftUI button in a hosting view so that it will be available for use in AppKit.

let signInButton = GoogleSignInButton {
  GIDSignIn.sharedInstance.signIn(withPresenting: yourViewController) { signInResult, error in
      // check `error`; do something with `signInResult`
  }
}
let hostedButton = NSHostingView(rootView: signInButton)

googlesignin-ios's People

Contributors

alex-4-git avatar antonkozlovskyi avatar camden-king avatar dependabot[bot] avatar dmaclach avatar henryhl22321 avatar mdmathias avatar petea avatar sheikhbayazid avatar xiangtiandai avatar ywsang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

googlesignin-ios's Issues

[GIDSignIn signInWithConfiguration:..] too draconian with NS_EXTENSION_UNAVAILABLE

v6.1.0 of the SDK changed some of the methods in GIDSignIn to become unavailable to extensions. Whilst I can understand the motive, I think this is too draconian a change. In my app, I have a shared library that is used by the main app itself and various extensions. This library includes the Google sign-in support, but that side of things is only ever used by the app itself, not the extensions and the code already ensures you aren't running as an extension before attempting to sign-in. But with 6.1.0, my library no longer builds as it hits this error:

'signIn(with:presenting:callback:)' is unavailable in application extensions for iOS: The sign-in flow is not supported in App Extensions.

Whilst I 'could' refactor my library to extract out the non-extension friendly parts into another shared library, this is no small undertaking and provides no real-world benefit for the time involved.

I have a couple of solutions:

  1. Just revert the change that added NS_EXTENSION_UNAVAILABLE to the various calls.
  2. Add explicit equivalents of the NS_EXTENSION_UNAVAILABLE calls that make it clear that its OK to include them in a library, but that they MUST not be actually called from an extension.

For now, my only solution is to just limit my SDK usage to pre 6.1.0 versions.

Using v6 in SwiftUI: `.signIn()` workaround and suggestions for SwiftUI support

Background

With SwiftUI being the way forward for iOS dev, I would have hoped GoogleSignIn had better support for SwiftUI.

Unfortunatley there isn't any SwiftUI-focused documentation, and the patterns changed in v6 (e.g., no delegates) seem to make implementing GIDSignIn harder in SwifUI.

The biggest issue I've had (and clearest example) is below:

Sign In

The main issue I've run into is with this function:

- (void)signInWithConfiguration:(GIDConfiguration *)configuration
       presentingViewController:(UIViewController *)presentingViewController
                       callback:(nullable GIDSignInCallback)callback;

SwiftUI doesn't have view controllers, but we need to instantiate a sign-in view from SwiftUI.

There's two workarounds:

  1. Create a UIViewRepresentable view that accesses the root view controller with something like UIApplication.shared.windows.last?.rootViewController
  2. Create a UIViewRepresentable view that instantiates a dummy UIViewController that then calls some AuthManager singleton, which in turn calls sharedInstance.signIn(...).

This is so confusing to implement primarily because there already existed a delegate pattern and a non-presentingVC parameter before v6 of this library.

Tying it all together would be something like this:

// AuthManager.swift

class AuthManager {

    var shared = AuthManager()
    var config = GIDConfiguration()

    func signIn(withVC vc: UIViewController) {
        GIDSignIn.signIn(with: config, presenting: vc) { /* ... */ }
    }
}


// AuthWrapper.swift 

class AuthVC: UIViewController {
    func signIn() {
        AuthManager.shared.signIn(withVC: self)
    }
}

class AuthVCWrapper: UIViewRepresentable {
    let authVC = AuthVC() // strong ref
    func makeUIViewController() {
        return authVC
    }
    func signIn() {
        authVC.signIn() // single responsibility principle
    }
}


// SignIn.swift

class SignIn: View {
    var authWrapper = AuthVCWrapper()

    var body: some View {
        ZStack {
            authWrapper
            Button(action: authWrapper.signIn()) {
                Text("Sign In")
            }
        }
    }
}

To me personally this seems verbose.

Delegates

In addition, the delegate pattern seems to have been removed. This would have made it much easier to work alongside a more detached MVVM pattern instead of routing everything through the sharedInstance singleton anyways.

Is there a reason for why the delegate pattern was removed?

Suggestions

Given that SFSafariViewController is a UIKit component, having GIDSignIn instantiate the UIViewControllerRepresentable and alongisde an overloaded sharedInstance.signIn() for SwiftUI users would vastly shorten the above example.

The other suggestion I have is maybe a timeline on SwiftUI support, or some documentation on existing workarounds, as most blog posts are written pre-v6, and instruct users to create delegates and such, which is no longer supported.

Final Thoughts

I guess this brings me to my final question: is there SwiftUI support planned at all?

I'd be happy to write a sample project to catch up the Objective-C one currently in this repo, but without any official documentation for SwiftUI support it'd need a good chunk of review.

Support Google Sign-In on macOS

I have an Android app I'm porting over to iOS. After release 8.9.0, every Firebase dependency I use supports MacOS fine, except for optional GoogleSignIn integration - so the app is but one dependency away having full functionality.

Given the vast majority of users opt for Google Sign In on their Android phones, I can't release the Mac App without support. Is this planned? Are you hoping for contributions to tackle it?

Access to cached authentication object

In our apps we call the method restorePreviousSignInWithCallback: every startup. This is recommended by the documentation, and we do this in order to be informed that the user's token was revoked.
restorePreviousSignInWithCallback: can fail for many reasons, for example if there was a failure to refresh the token. In most of these cases, we would still like to get the cached token, even if it expired or about to expire. However currently there is no way to get the token if an error occurred during restorePreviousSignInWithCallback:.

One solution could be to make restorePreviousSignInNoRefresh public in some form.

Expose more advanced OIDAuthorizationRequest configuration options.

The current interface allows developers to configure their authorization requests on a very basic level with just clientId, audience, hosted domain and login_hint, leaving more advanced parameters outside of their control. However, OIDAuthorizationRequest exposes a more complex initializer than the one currently in use:

- (instancetype)initWithConfiguration:(OIDServiceConfiguration *)configuration
                clientId:(NSString *)clientID
            clientSecret:(nullable NSString *)clientSecret
                   scope:(nullable NSString *)scope
             redirectURL:(NSURL *)redirectURL
            responseType:(NSString *)responseType
                   state:(nullable NSString *)state
                   nonce:(nullable NSString *)nonce
            codeVerifier:(nullable NSString *)codeVerifier
           codeChallenge:(nullable NSString *)codeChallenge
     codeChallengeMethod:(nullable NSString *)codeChallengeMethod
    additionalParameters:(nullable NSDictionary<NSString *, NSString *> *)additionalParameters

which (in theory) means, that the limitation is only in GIDConfiguration.

Since we're talking about a piece of software made by developers for developers, I believe making it more flexible for non-standard and advanced use cases can only improve it.

GoogleSignIn required to be signed in Xcode

This seems like a new development, but GoogleSignIn is being required to be signed. This is quite strange for a CocoaPod. This means I need to alter the Pods project and add the signing information to only the GoogleSignIn project. What is the deal with this? It's creating distribution headaches too.

`addScopes` callback not called when nested

Hi, I'm working on updating GoogleSignIn to the latest version and facing a problem regarding the addScopes function.

Since we are now not able to Sign In with the necessary scopes, I am trying to add them as soon as the user is signed in.
It turns out that by chaining both methods, the callback I send to addScopes is never executed.

GIDSignIn.sharedInstance.signIn(with: configuration, presenting: presentingViewController) { user, error in
    
    guard error == nil else {
        completion(user, error)
        return
    }
                    
    GIDSignIn.sharedInstance.addScopes(
        scopes,
        presenting: presentingViewController,
        callback: {
            // This callback is never executed
            print(">>> addScopes callback")
            completion($0, $1)
        }
    )
}

Testing it manually I'm able to see:

  1. The web view being presented for the regular sign in and being dismissed when it succeeds
  2. The web view for allowing permissions to be added and dismissed when tapping "Allow"

After these two steps, nothing happens 😔 Am I missing something?

In my opinion the optimal solution would be being able to supply the scopes directly to the signIn method so that both tasks could be done in one step instead of two (like suggested on #23) but I wanted to flag this finding I'm running into as well.

Thanks for the great work!

Cannot find 'GIDSignInErrorCode' in scope

Since upgrading to v6.0.1 when trying to reference GIDSignInErrorCode in Swift (Xcode 12.5.1) I am now seeing a compiler error of "Cannot find 'GIDSignInErrorCode' in scope".

Add additional GIDSignInErrorCode when access to resources is denied

Hey

Currently, when access to resources is denied, GoogleSignIn return "kGIDSignInErrorCodeUnknown" with description "access_denied". Can we create an additional case called "kGIDSignInErrorCodeAccessDenied", which would be mapped from "OIDErrorCodeOAuthAccessDenied"?

In my case it would help a lot, as we send analytics events when user doesn't authorise access to resources.

GIDSignIn callback never called with EMM error

Hi,

I noticed that when getting a EMM error from OpenID then my workflow completion block is never called. From my testing:

  • I get up to GIDAuthentication.handleTokenFetchEMMError with a JSON error:
{
    "error": "emm_passcode_required",
    "error_description": "Access to your account data is restricted by policies within your organization. Please contact the administrator for xxx for more information."
}
  • GIDEMMEErrorHandler.handleErrorFromResponse is called but completion is never called

Does GoogleSignIn have plan to support scene-based lifecycle ?

UIWindow *alertWindow = [[UIWindow alloc] initWithFrame:keyWindowBounds];

Hi guys, recently my app decide to migrate from app-based lifecycle to scene-based lifecycle. It means that every UIWindow instance must connect to a specific UIWindowScene instance otherwise your window will not appear on the screen.

In the code above, you can see the error alert window is not connected to the scene. That's might cause a problem under scene-based lifecycle.

Do you have plan to support it ?

GTMAppAuth minimum platform Error

Showing Recent Messages The package product 'GTMAppAuth' requires minimum platform version 10.11 for the macOS platform, but this target supports 10.10

I get this error in macOS App, but in package.swift I get set the platform with .macOS(.v11) I think that enough. but this error is still showing

Issues on using gmail business email to login

Hey, I am seeing an issue when using gmail business email, which is reproduced on the latest version: 6.0.2.
I use SPM, and calling - (void)signInWithConfiguration:(GIDConfiguration *)configuration presentingViewController:(UIViewController *)presentingViewController callback:(nullable GIDSignInCallback)callback;

Login using gmail business email neither success nor return an error first time on a device, it only return an error on the second, third time, and so on.

But the gmail business email works well on simulator. any thoughts on why it did not work on a device, or why it did not return an error first time? Thanks!

Invalid `GIDConfiguration` object reports unsupported URL error, rather than something more descriptive

Background

I'm loading the clientID key from an .xcconfig file into an AuthManager, which is responsible for creating the GIDConfiguration object.

// AuthManager.swift
var config = GIDConfiguration(clientID: "asdf")

init() {
    // Fetches the API token from an .xcconfig thru the Info.plist
    if let clientID = Bundle.main.object(forInfoDictionaryKey: "GID_CLIENT_ID") as? String {
        config = GIDConfiguration(clientID: clientID)
    }
}

However, if no code is provided, I receive a runtime crash with the following error:

Your app is missing support for the following URL schemes: asdf'
terminating with uncaught exception of type NSException

Suggestion

I'd hope that for new users this would have a more detailed explanation, such as "Invalid GIDconfiguration object; key was invalid". "Missing URL scheme support' to me would imply an issue with the AppDelegate rather than a config object.

I recognize this is totally minor (especially given a lot of other API design issues I've experienced in v6 with SwiftUI) but I figured I might as well report it :)

Invalid scheme

unnamed

So I'm using version 6

pod 'GoogleSignIn', '~> 6.0'

it opens the dialog for authentication but says invalid scheme

my code is as following:

let signInConfig = GIDConfiguration.init(clientID: "MY_REVERSE_ID");
GIDSignIn.sharedInstance.signIn(with: signInConfig, presenting: visibleViewCtrl) { user, error in
                guard error == nil else { return }
        
                // If sign in succeeded, display the app's main content View.
            }
        }

I'm not getting any error in the Xcode console.

iOS app OAuth Verification: We couldn't find the OAuth Consent Screen grant process for your project xxx.

Hello

I meet an issue during OAuth Verification Request. My product is an iOS app written in Swift, it only requires Google drive read permission.

This is Google's reply for my app permission Verification.

Updated App Demonstration Video

We couldn't find the OAuth Consent Screen grant process for your project xxx. Please reply directly to this email with a link to a YouTube video that shows the OAuth grant process that users will go through.

I think the email said I need to show the google drive grant access page. But with current latest 6.0.1, we first signIn with the basic access and then add scope, that is two step, and I couldn't see the grant google drive process appearing, the web view for allowing permissions dismissing immediately after present. Please see this video.

Is it the correct behavior for 6.0.1 or configuration may be wrong in my project?

Here is how I implement Google SignIn and ad drive scope in code, I follow this Google guide

@objc func signInButtonTapped(_ sender: Any) {
        GIDSignIn.sharedInstance.signIn(with: modelController.signInConfig, presenting: self) { [weak self] user, error in
            
            if let error = error {
                print("SignIn failed, \(error), \(error.localizedDescription)")
            } else {
                print("Authenticate successfully")
                let driveScope = "https://www.googleapis.com/auth/drive.readonly"
                guard let user = user else { return }
    
                let grantedScopes = user.grantedScopes
                print("scopes: \(String(describing: grantedScopes))")
                
                if grantedScopes == nil || !grantedScopes!.contains(driveScope) {
                    // Request additional Drive scope if it doesn't exist in scope.
                    GIDSignIn.sharedInstance.addScopes([driveScope], presenting: self!) { user, error in
                        if let error = error {
                            print("add scope failed, \(error), \(error.localizedDescription)")
                        }

                        guard let user = user else { return }

                        // Check if the user granted access to the scopes you requested.
                        if let scopes = user.grantedScopes,
                           scopes.contains(driveScope) {
                            print("Scope added")
                            print(" NEW scopes: \(String(describing: scopes))")
                            self?.createGoogleDriveService(user: user)
                        }
                    }
                }
            }
        }

Add macCatalyst support

Hi Google team.

Do you have any raw estimations of when you'll add macCatalyst support?

Thank you

Unable to specify scopes before sign in

The new API looks to be a two step sign in -- first step basic sign in and then another one using addScopes to add a scope. This is a departure from previous versions of SDK where we could specify scopes as a property to GIDSignIn.sharedInstance() before sign in. Is this a new behaviour or is it still possible to do single step sign in?

Documenting errors of revoked tokens

Hi,

In our apps we need to know whether the Google token was revoked or not, so we can delete other data that was obtained using that token. Today, if one tries to call restorePreviousSignInWithCallback: when the token was revoked, we get the following error:

Error Domain=org.openid.appauth.oauth_token Code=-10 "invalid_grant: Token has been expired or revoked." UserInfo={OIDOAuthErrorResponseErrorKey={
    error = "invalid_grant";
    "error_description" = "Token has been expired or revoked.";
}, NSLocalizedDescription=invalid_grant: Token has been expired or revoked., NSUnderlyingError=0x281ab7e40 {Error Domain=org.openid.appauth.remote-http Code=400 "{
  "error": "invalid_grant",
  "error_description": "Token has been expired or revoked."
}" UserInfo={NSLocalizedDescription={
  "error": "invalid_grant",
  "error_description": "Token has been expired or revoked."
}}}}

Which comes directly from https://github.com/openid/AppAuth-iOS. Can this error be explicitly documented? Either by documenting that this is the error returned, or introducing a new error code to GIDSignInErrorCode.

There are no error code list document for GIDSignInDelegate

Hi.

GIDSignInDelegate's sign method is returning the error code like this.
Error Domain=org.openid.appauth.general Code=-15 "ID Token expired"

But this is not in your documentation.
Is there any way that I can find the above information?

GoogleSignIn does not define a clang module, cannot @import GoogleSignIn when built as a library

GoogleSignIn does not generate a clang module when built as a library instead of a framework. This forces users to use use_frameworks! in their Podfile, which isn't the default.

Steps to Reproduce

  1. Remove use_frameworks! from Sample Podfile to generate as a library
    use_frameworks!
  2. Open SignInSampleForPod.xcworkspace and build.

Compilation failure:

GoogleSignIn-iOS/Sample/Source/SignInViewController.h:19:9: Module 'GoogleSignIn' not found

Screen Shot 2021-07-20 at 11 06 43 AM

To fix

Add 'DEFINES_MODULE' => 'YES' to pod_target_xcconfig

s.pod_target_xcconfig = {
'GCC_PREPROCESSOR_DEFINITIONS' => 'GID_SDK_VERSION=' + s.version.to_s,
'HEADER_SEARCH_PATHS' => '"${PODS_TARGET_SRCROOT}"'
}

becomes:

 s.pod_target_xcconfig = { 
   'GCC_PREPROCESSOR_DEFINITIONS' => 'GID_SDK_VERSION=' + s.version.to_s, 
   'HEADER_SEARCH_PATHS' => '"${PODS_TARGET_SRCROOT}"',
   'DEFINES_MODULE' => 'YES'
 } 

See "Modular Headers" section of https://blog.cocoapods.org/CocoaPods-1.5.0/

[Flutter] - macOS Support

Hi there :)

hope you're all doing good.

I implemented Google Sign in for Flutter with the actual plugins repo, but I am getting this:

[!] The platform of the target `Runner` (macOS 10.15.0) is not compatible with `GoogleSignIn (5.0.2)`, which does not support `macOS`.

I assume that this error is related to this repo, but some other issues here saying, that it's working for Big Sur....

any idea someone?

Edit:

[!] The platform of the target `Runner` (macOS 10.15.0) is not compatible with `GoogleSignIn (6.0.2)`, which does not support `macOS`

Can't sign in without family name

Environment

  • Xcode 13.1 (and 13.2.1)
  • GoogleSignIn 6.0.2 (also 6.1.0)
  • GTMSessionFetcher 1.5.0 (also 1.7.0)
  • Release

Devices

  • iPhone 12 mini (iOS 15.2)
  • Simulator iPhone 13 (iOS 15.2)
  • Simulator iPhone 11 (iOS 13.7)

Screenshot

Issue

Can't receive a login completion response, when I try to log in with an email without a family name.
This only happens in the Release environment.

private func signIn() {
    GIDSignIn.sharedInstance.signIn(with: configuration, presenting: self.owner) { [weak self] user, error in
        self?.handleSignInResult(user: user, error: error)
    }
}

GIDSignIn instance tried to create a profile with profileDataWithIDToken:idToken but it couldn't, because my account didn't have a family name.

- (GIDProfileData *)profileDataWithIDToken:(OIDIDToken *)idToken {
  if (!idToken ||
      !idToken.claims[kBasicProfilePictureKey] ||
      !idToken.claims[kBasicProfileNameKey] || 
      !idToken.claims[kBasicProfileGivenNameKey] ||
      !idToken.claims[kBasicProfileFamilyNameKey]) {
    return nil;
  } 
  return [[GIDProfileData alloc]
      initWithEmail:idToken.claims[kBasicProfileEmailKey]
               name:idToken.claims[kBasicProfileNameKey]
          givenName:idToken.claims[kBasicProfileGivenNameKey]
          familyName:idToken.claims[kBasicProfileFamilyNameKey]
            imageURL:[NSURL URLWithString:idToken.claims[kBasicProfilePictureKey]]];
}

So GIDSignIn uses GTMSessionFetcher to fetch user information, but it seems that GTMSessionFetcher doesn't call startFetchURL's completion handler.

if (!handlerAuthFlow.profileData) {
  [handlerAuthFlow wait];
  NSURL *infoURL = [NSURL URLWithString:
      [NSString stringWithFormat:kUserInfoURLTemplate,
          [GIDSignInPreferences googleUserInfoServer],
          authState.lastTokenResponse.accessToken]];
  [self startFetchURL:infoURL
              fromAuthState:authState
                withComment:@"GIDSignIn: fetch basic profile info"
      withCompletionHandler:^(NSData *data, NSError *error) {
    if (data && !error) {
      NSError *jsonDeserializationError;
      NSDictionary<NSString *, NSString *> *profileDict =
          [NSJSONSerialization JSONObjectWithData:data
                                          options:NSJSONReadingMutableContainers
                                            error:&jsonDeserializationError];
      if (profileDict) {
        handlerAuthFlow.profileData = [[GIDProfileData alloc]
            initWithEmail:idToken.claims[kBasicProfileEmailKey]
                      name:profileDict[kBasicProfileNameKey]
                givenName:profileDict[kBasicProfileGivenNameKey]
                familyName:profileDict[kBasicProfileFamilyNameKey]
                  imageURL:[NSURL URLWithString:profileDict[kBasicProfilePictureKey]]];
      }
    }
    if (error) {
      handlerAuthFlow.error = error;
    }
    [handlerAuthFlow next];
  }];
}

Running with Mac Catalyst doesn't launch browser to sign in.

Hi!

I'm trying to get Google sign-in to work with an iOS app + Mac Catalyst, but the Safari browser never launches on macOS in order to actually perform the sign-in. The same project works fine on an iPad simulator.

Modified Sample Project
I have modified the sample project to try this out: LovebugLLC@c5ca41f

Steps to reproduce my Sample Project edits

  1. Clone GoogleSignIn-iOS project
  2. open Samples/ObjC/SignInSample/SignInSample.xcodeproj
  3. Wait for Xcode to install dependencies
  4. Select "SignInSample" target
  5. Go to the "General" tab
  6. Add Mac Catalyst app
  7. Go to the "Signing & Capabilities" tab
  8. Select your Development Team
  9. Click "+ Capability", and add "Keychain Sharing"
  10. Run scheme SignInSample -> My Mac (Catalyst)

Steps to reproduce the issue, after running the app

  1. Tap "Sign in" and you'll see this screen: Screen Shot 2022-01-29 at 16 08 57
  2. Click "Continue"

Expected results
Browser launches so I can log in

Actual results
No browser shows up

Other notes
If I change the run target to an iPad simulator, I am presented with the browser window and login just fine.

Documentation for adding scopes missing from the main docs?

I wasn't seeing anything about adding scopes at the main doc page: https://developers.google.com/identity/sign-in/ios/quick-migration-guide.

Also, in the main docs, the section:

"Retrieving user information
Once the user has authenticated and authorized access to the scopes you request, you can access user profile information through the GIDGoogleUser object."

(https://developers.google.com/identity/sign-in/ios/people) it makes it sound like you can explicitly request scopes prior to the addScopes call.

Google Sign-In for iOS Support

Hello!
How long will IOS version 5 support last? Unfortunately, i could not find information about this on the sdk page.

iOS restorePreviousSignIn: `restorePreviousSignIn` is not triggered in v6.0.1 when reopen the app.

Hello, my iOS app can't restorePreviousSignIn in v6.0.1.

Before, I used signIn:didSignInForUser:withError: to restore user signIn state, and it works fine.
Now, I follow your migration guide, to Move the logic from signIn:didSignInForUser:withError: to the callback block of signInWithConfiguration:presentingViewController:callback:.

Now, I put signInWithConfiguration:presentingViewController:callback: into Google signIn button, I could sign in but when I close and reopen my app, signInWithConfiguration:presentingViewController:callback: is not triggered, then I couldn't restore the previous user signIn state.

Is this the correct position it should be, how could I fix this issue? This version is quite new, I couldn't find related issue in internet, please help, guys.

@objc func signInButtonTapped(_ sender: Any) {
        GIDSignIn.sharedInstance.signIn(with: modelController.signInConfig, presenting: self) { [weak self] user, error in
            
            if let error = error {
                print("SignIn failed, \(error), \(error.localizedDescription)")
            } else {
                print("Authenticate successfully")
                let driveScope = "https://www.googleapis.com/auth/drive.readonly"
                guard let user = user else { return }
    
                let grantedScopes = user.grantedScopes
                print("scopes: \(String(describing: grantedScopes))")
                
                if grantedScopes == nil || !grantedScopes!.contains(driveScope) {
                    // Request additional Drive scope if it doesn't exist in scope.
                    GIDSignIn.sharedInstance.addScopes([driveScope], presenting: self!) { user, error in
                        if let error = error {
                            print("add scope failed, \(error), \(error.localizedDescription)")
                        }

                        guard let user = user else { return }

                        // Check if the user granted access to the scopes you requested.
                        if let scopes = user.grantedScopes,
                           scopes.contains(driveScope) {
                            print("Scope added")
                            print("NEW scopes: \(String(describing: scopes))")
                            self?.createGoogleDriveService(user: user)
                        }
                    }
                }
            }
        }
    }

func createGoogleDriveService(user: GIDGoogleUser) {
        let service = GTLRDriveService()
        service.authorizer = user.authentication.fetcherAuthorizer()

        // dependency inject
        modelController.googleAPIs = GoogleDriveAPI(service: service)

        // Post notification after user successfully sign in
        NotificationCenter.default.post(name: .signInGoogleCompleted, object: nil)
        
        user.authentication.do { [weak self] authentication, error in
            guard error == nil else { return }
            guard let authentication = authentication else { return }
            
            // Or, get an object that conforms to GTMFetcherAuthorizationProtocol for
            // use with GTMAppAuth and the Google APIs client library.
            let service = GTLRDriveService()
            service.authorizer = authentication.fetcherAuthorizer()
            
            // dependency inject
            self?.modelController.googleAPIs = GoogleDriveAPI(service: service)
            
            // Post notification after user successfully sign in
            NotificationCenter.default.post(name: .signInGoogleCompleted, object: nil)
        }
    }

previous restore logic code

func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
        if let error = error {
            print("SignIn failed, \(error), \(error.localizedDescription)")
        } else {
            print("Authenticate successfully")
            let service = GTLRDriveService()
            service.authorizer = user.authentication.fetcherAuthorizer()

            // dependency inject
            modelController.googleAPIs = GoogleDriveAPI(service: service)

            // Post notification after user successfully sign in
            NotificationCenter.default.post(name: .signInGoogleCompleted, object: nil)
        }
    }

Keychain access group used for the sign-in state

Hi,

This framework stores the user's sign-in information persistently in the keychain storage. From looking at the code, it doesn't set the access group of the query to the keychain, which means according to Apple's docs that it will use the first access group.

If the first access group is shared in several apps of the same vendor, this means that the state will be read and written to the same place, which means that one app will get the user state of another app, which is not necessarily the desired result.

Did I understand everything correctly? If so, what's the way to work around it?
Also if that's the case, I suggest to document it explicitly.

Thanks

iOS 13 deprecation warnings

When building for iOS 13 minimum and above the following warnings are triggered:

GIDEMMErrorHandler.m:93:61: warning: 'keyWindow' is deprecated: first deprecated in iOS 13.0 - Should not be used for applications that support multiple scenes as it returns a key window across all connected scenes [-Wdeprecated-declarations]
    UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
GIDEMMErrorHandler.m:177:11: warning: 'openURL:' is deprecated: first deprecated in iOS 10.0 [-Wdeprecated-declarations]
          openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
          ^~~~~~~
          openURL:options:completionHandler:
GIDEMMErrorHandler.m:207:42: warning: 'openURL:' is deprecated: first deprecated in iOS 10.0 [-Wdeprecated-declarations]
      [[UIApplication sharedApplication] openURL:url];
                                         ^~~~~~~
                                         openURL:options:completionHandler:

`'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0 warning (Swift Package Manager)

Hi,

I observe a warning in the SignInSample example project:

Package AppAuth:
'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.5.99.

The same warning appears after adding GoogleSignIn SDK using Swift Package Manager to another project.

Can you advise how this warning could be fixed, or should I use POD instead of Swift Package?

Can't login due to "This browser or app may not be secure"

I'm using the GIDSignIn.sharedInstance.signIn to let my app users login with their google account and it works well for most of the cases.

But recently I got a report from one of the users seeing the "Couldn't sign you in" error page when logging in saying "This browser or app may not be secure. Try using a different browser. If you're already using a supported browser, you can try again to sign in.".

What is the reason for this error and what can I do to solve it? I'm not in control of the way GIDSignIn is displaying in-app Safari instance.

Request additional scopes with `signIn`

Hello,

Since the 6.0.0 it looks like isn't anymore possible to SignIn with scopes. The only way I'v found is :

  • firstly call signInWithConfiguration:presentingViewController:callback:
  • then call addScopes:presentingViewController:callback:

In my case, I need to connect my user to their Youtube account. It results in two" sign in" in a row, which can be weird for some users.

Is there a way to make one sign in with scope or this is a volunteer behavior?

Btw, thanks for the SPM and M1 compatibility!

Thanks
Florian

click "Use another account" fail to login

GoogleSignIn Version: 6.0.2

my code for this:

[GIDSignIn.sharedInstance signInWithConfiguration:self.signInConfig presentingViewController:[TTAccount accountConf].visibleViewControllerHandler() callback:^(GIDGoogleUser *_Nullable user, NSError *_Nullable error) {
}];

when I click "Use another account" then input account and password, this page always freeze:
middle_img_v2_3a22bedf-bc9c-44cb-b15c-e849b2a99a8g

Is this a bug?

AST Deserialization Issue GTMSessionFetcher.h:797

Xcode 12.5.1
SwiftPM
Also firebase-is-sdk 8.3.1 with SwiftPM
Got an error, when compiling to device:
'GTMSessionFetcher' has different definitions in different modules; first difference is definition in module 'GTMSessionFetcher.GTMSessionFetcher' found property name 'sessionUserInfo'

Connection error making token request to 'https://oauth2.googleapis.com/token': The request timed out..

Google sign in NOT working and returns connection error.

Error! Optional(Error Domain=org.openid.appauth.general Code=-5 "Connection error making token request to 'https://oauth2.googleapis.com/token': The request timed out.." UserInfo={NSLocalizedDescription=Connection error making token request to 'https://oauth2.googleapis.com/token': The request timed out.., NSUnderlyingError=0x600000634030 {Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={_kCFStreamErrorCodeKey=-2102, NSUnderlyingError=0x6000006392c0 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <0F0E1E47-8CBA-499F-AEE1-957F160BB706>.<2>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDataTask <0F0E1E47-8CBA-499F-AEE1-957F160BB706>.<2>"
), NSLocalizedDescription=The request timed out., NSErrorFailingURLStringKey=https://oauth2.googleapis.com/token, NSErrorFailingURLKey=https://oauth2.googleapis.com/token, _kCFStreamErrorDomainKey=4}}})

To reproduce:
follow the instructions from https://developers.google.com/identity/sign-in/ios/start

[Clone the project](git clone https://github.com/google/GoogleSignIn-iOS) and run it to the device/simulator and click the sign in button.

Environment:

Xcode 13.2.1 (13C100)

Device: Simulator/Phone iOS 15.2

Undefined symbols for architecture arm64:

Hello, I'm getting this error while trying to run to device Google SingIn.

Undefined symbols for architecture arm64:
  "___ubsan_handle_sub_overflow", referenced from:
      -[GIDCallbackQueue next] in GoogleSignIn.o
      -[GTMSessionFetcher simulateByteTransferReportWithDataLength:block:] in GTMSessionFetcherCore.o
      -[GTMSessionCookieStorage removeExpiredCookies] in GTMSessionFetcherCore.o
      -[GTMSessionUploadFetcher updateChunkFetcher:forChunkAtOffset:] in GTMSessionFetcherCore.o
  "___ubsan_handle_divrem_overflow", referenced from:
      +[OIDIDToken base64urlNoPaddingDecode:] in AppAuthCore.o
      -[GTMSessionFetcher simulateByteTransferReportWithDataLength:block:] in GTMSessionFetcherCore.o
      -[GTMSessionFetcher simulateByteTransferWithData:block:] in GTMSessionFetcherCore.o
      -[GTMSessionUploadFetcher updateChunkFetcher:forChunkAtOffset:] in GTMSessionFetcherCore.o
  "___ubsan_handle_pointer_overflow", referenced from:
      _colorForStyleState in GoogleSignIn.o
      -[GTMSessionFetcher isRetryError:] in GTMSessionFetcherCore.o
      -[GTMSessionFetcher(GTMSessionFetcherLogging) stringFromStreamData:contentType:] in GTMSessionFetcherCore.o
  "___ubsan_handle_float_cast_overflow", referenced from:
      +[GIDMDMPasscodeState passcodeState] in GoogleSignIn.o
      -[GIDSignIn handleDevicePolicyAppURL:] in GoogleSignIn.o
      ___65-[GTMSessionFetcher beginFetchMayDelay:mayAuthorize:mayDecorate:]_block_invoke.280 in GTMSessionFetcherCore.o
  "___ubsan_handle_add_overflow", referenced from:
      -[GIDCallbackQueue wait] in GoogleSignIn.o
      -[GTMSessionFetcher simulateByteTransferReportWithDataLength:block:] in GTMSessionFetcherCore.o
      -[GTMSessionFetcher isRetryError:] in GTMSessionFetcherCore.o
      +[GTMSessionFetcher(GTMSessionFetcherLogging) logDirectoryForCurrentRun] in GTMSessionFetcherCore.o
      -[GTMSessionFetcher(GTMSessionFetcherLogging) logFetchWithError:] in GTMSessionFetcherCore.o
      -[GTMSessionUploadFetcher setupRequestHeaders] in GTMSessionFetcherCore.o
      -[GTMSessionUploadFetcher generateChunkSubdataWithOffset:length:response:] in GTMSessionFetcherCore.o
      ...
  "___ubsan_handle_shift_out_of_bounds", referenced from:
      _colorForStyleState in GoogleSignIn.o
  "___ubsan_handle_nonnull_arg", referenced from:
      -[GIDAuthentication doWithFreshTokens:] in GoogleSignIn.o
      ___39-[GIDAuthentication doWithFreshTokens:]_block_invoke_2 in GoogleSignIn.o
      +[GIDEMMErrorHandler sharedInstance] in GoogleSignIn.o
      -[GIDEMMErrorHandler handleErrorFromResponse:completion:] in GoogleSignIn.o
      +[GIDMDMPasscodeCache sharedInstance] in GoogleSignIn.o
      -[GIDMDMPasscodeCache passcodeState] in GoogleSignIn.o
      ___36-[GIDMDMPasscodeCache passcodeState]_block_invoke in GoogleSignIn.o
      ...
  "___ubsan_handle_type_mismatch_v1", referenced from:
      +[GIDAuthStateMigration extractAuthorizationWithTokenURL:callbackPath:] in GoogleSignIn.o
      -[GTMAppAuthFetcherAuthorizationEMMChainedDelegate initWithDelegate:selector:] in GoogleSignIn.o
      ___93-[GTMAppAuthFetcherAuthorizationEMMChainedDelegate authentication:request:finishedWithError:]_block_invoke in GoogleSignIn.o
      -[GIDAuthentication clientID] in GoogleSignIn.o
      -[GIDAuthentication accessToken] in GoogleSignIn.o
      -[GIDAuthentication accessTokenExpirationDate] in GoogleSignIn.o
      -[GIDAuthentication refreshToken] in GoogleSignIn.o
      ...
  "___ubsan_handle_out_of_bounds", referenced from:
      _colorForStyleState in GoogleSignIn.o
      -[GTMSessionFetcher isRetryError:] in GTMSessionFetcherCore.o
  "___ubsan_handle_load_invalid_value", referenced from:
      +[GIDAuthStateMigration migrateIfNeededWithTokenURL:callbackPath:keychainName:isFreshInstall:] in GoogleSignIn.o
      +[GIDAuthentication parametersWithParameters:emmSupport:isPasscodeInfoRequired:] in GoogleSignIn.o
      ___57+[GIDAuthentication handleTokenFetchEMMError:completion:]_block_invoke in GoogleSignIn.o
      -[GIDCallbackQueue fire] in GoogleSignIn.o
      -[GIDEMMErrorHandler handleErrorFromResponse:completion:] in GoogleSignIn.o
      -[GIDEMMErrorHandler passcodeRequiredAlertWithCompletion:] in GoogleSignIn.o
      -[GIDMDMPasscodeCache passcodeState] in GoogleSignIn.o
      ...
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Lib version: 6.1.0
Xcode version: 13.2.1

The issue is only happening when I run against the real device.
Help is really welcome :)

Remove Access To App For Google SSO on Settings isn't working as expected.

Hello, I am seeing an issue when I try to Remove Access To our app for Google SSO on Settings page(i.e. link).

Here is what i did:
1.) Sign in with Google SSO on my app.
2.) Put my app to background or killed the app.
3.) Sign in to google on browser with the same gmail account i used in step 1 & Go to Data & Privacy Page(i.e. link)
4.) Remove access for my app in Data & Privacy Page(i.e. link)
5.) Get my App to Foreground or Relaunching the app.
6.) During App coming to Foreground or Relaunch, In didFinishLaunchingWithOptions of App Delegate, I do check for GIDSignIn.sharedInstance.restorePreviousSignIn to see if Google SSO tokens are still valid.
7.) GIDSignIn.sharedInstance.restorePreviousSignIn returns that the google sso idTokens are still valid for my app, in my case it shouldn't be as I removed access for my app.

Conclusion:
I think this should be the correct behavior, GIDSignIn.sharedInstance.restorePreviousSignIn should return error or nil user when user removes access for an app and tries to GIDSignIn.sharedInstance.restorePreviousSignIn , because that is how it worked for Apple & Facebook SSO.

Would love to hear your thoughts or feedback on this, Thank you!.

How to add prompt: consent to user auth flow?

We need the user to consent on every login attempt and on web you can set prompt = consent. However, I'm having a difficult time trying to achieve this on mobile. Is this implemented and if so, can someone help provide guidance on how to implement this?

Screen Shot 2022-04-05 at 10 50 59 AM

Currently, we're doing:

private lazy var configuration: GIDConfiguration = {
        return GIDConfiguration(clientID: clientID, serverClientID: serverClientId)
    }()

GIDSignIn.sharedInstance.signIn(with: configuration,
                                        presenting: rootViewController) { user, error in

}

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.