How to authorize user with Google in OS X Cocoa ap

2020-07-18 05:35发布

问题:

I am using Firebase in my OS X application. I am trying to add Google Authentication. This is an example for iOS.

Question is: How to obtain Google OAuth access token in OS X application?

回答1:

Firebase auth can be integrated with Google sign in on OS X the following way using the GTMOAuth2 pod.

import Cocoa
import GTMOAuth2
import Firebase

class MainWindowController: NSWindowController {

let ref = Firebase(url: "https://xyz.firebaseio.com")

override func windowDidLoad() {
    super.windowDidLoad()


    let frameworkBundle = NSBundle(forClass: GTMOAuth2WindowController.self)
    let windowController = GTMOAuth2WindowController(scope: "", clientID: clientID, clientSecret: clientSecret, keychainItemName: keychainName, resourceBundle: frameworkBundle)
    windowController.signInSheetModalForWindow(window, delegate: self, finishedSelector: #selector(MainWindowController.didFinishWithAuth(windowController:auth:error:)))

}

func didFinishWithAuth(windowController wc:GTMOAuth2WindowController, auth: GTMOAuth2Authentication, error: NSError?) {
    if error != nil {
        print(error)
    } else {
        print(auth)
        ref.authWithOAuthProvider("google", token: auth.accessToken, withCompletionBlock: { err, auth in
            if err != nil {
                print(err)
            } else {
                print(auth)
            }
        })
      }
  }
}

A couple of things to notice, as brainless mentioned above, you have to create an OAuth Api key using the other option in the credentials manager. You have to remember to white list your clientID in your firebase project.



回答2:

It is possible to obtain Google OAuth 2 token in Objective-C with. GTMOAuth2. Using cocoapods:

pod 'GTMOAuth2'


GTMOAuth2 library needs client id with application type other. It is possible to create one in Google Developer Console:


This a code sample describing how to work with this lib:

#import "GTMOAuth2Authentication.h"
#import "GTMOAuth2WindowController.h"

...

- (void) applicationDidFinishLaunching:(NSNotification *) aNotification {
    GTMOAuth2Authentication * = [GTMOAuth2WindowController
               authForGoogleFromKeychainForName: @"where-to-store-token-in-a-keychain" 
                                       clientID: @"client-id"
                                   clientSecret: @"client-secret"];

    if (authorizer.canAuthorize) {
        NSLog(@"Your authorizer was restored from key chain and can be autorized. Authorozer: %@", authorizer);
    }
    else {
        NSBundle * frameworkBundle = [NSBundle bundleForClass:[GTMOAuth2WindowController class]];
        GTMOAuth2WindowController * windowController;
        windowController = [GTMOAuth2WindowController controllerWithScope: @"" //scope url here, empty is just email and profile
                                                             clientID: clientID
                                                         clientSecret: clientSecret
                                                     keychainItemName: kKeychainItemName
                                                       resourceBundle: frameworkBundle];

        [windowController signInSheetModalForWindow: [self window]
                              completionHandler: ^(GTMOAuth2Authentication * auth, NSError * error) {
                                                    if (error == nil) {
                                                        authorizer = auth;
                                                        NSLog(@"Successfully signed in.");
                                                    } else {
                                                        NSLog(@"Failed to sign in.");
                                                    }
                              }];
}

It will create pop-up window with Google authorization page inside on a first launch and use "token" stored in keychain for subsequent runs.


Pros

This authorizer can be used with almost every Google Service.

Cons

Looks like it can not be easily integrated with Firebase.



回答3:

UPDATED

Updated code for recent versions of Firebase. Signing in with Google (using OAuth) to authenticate with Firebase.

func someFunc {
    let frameworkBundle = Bundle(for: GTMOAuth2WindowController.self)
    let windowController = GTMOAuth2WindowController(scope: "https://www.googleapis.com/auth/plus.me", clientID: YOUR_CLIENT_ID, clientSecret: YOUR_CLIENT_SECRET, keychainItemName: "OAuth2 APP_NAME: Google+", resourceBundle: frameworkBundle)

    guard let window = self.view.window else { return }

    windowController?.signInSheetModal(for: window, delegate: self, finishedSelector: #selector(didFinishWithAuth(windowController:auth:error:)))
}

  @objc func didFinishWithAuth(windowController:GTMOAuth2WindowController, auth: GTMOAuth2Authentication, error: NSError?) {
    if error != nil {
      print(error?.localizedDescription ?? String())
    } else {

      let credential = OAuthProvider.credential(withProviderID: GoogleAuthProviderID, accessToken: auth.accessToken)

        Auth.auth().signIn(with: credential) { (auth, error) in
          if let error = error {
            print(error.localizedDescription)
            return
          }

          // Successful sign in
      }
    }
  }