The Google+ Sign-In button manages the OAuth 2.0 flow and token lifecycle, simplifying your integration with the Google APIs. Furthermore, if the user has the native Google+ mobile app installed, the Google+ SDK also automatically integrates with it, so users will not have to re-enter their Google credentials to authorize your app.
A user always has the option to revoke access to an application at any time.
Before you begin
You must create a Google API Console project and initialize the Google+ client.
Enable sign in
To enable sign in, you must configure the GPPSignIn
shared singleton instance.
You can do this in many places in your app. The easiest place is often to
configure this instance in your view controller's viewDidLoad
method.
-
In your view controller's .h file, import
GooglePlus/GooglePlus.h
, and declare that this controller class implements theGPPSignInDelegate
protocol.#import <GooglePlus/GooglePlus.h> @interface MyViewController : UIViewController <GPPSignInDelegate>
-
In your view controller's .m file, import
GoogleOpenSource/GoogleOpenSource.h
.#import <GoogleOpenSource/GoogleOpenSource.h>
-
Choose a login scope for use in the next step based on this criteria:
- If you need access to the user's identity, social graph and the ability
to write app activities, set the scope to
kGTLAuthScopePlusLogin
, which resolves tohttps://www.googleapis.com/auth/plus.login
. - If you just need access to basic profile information, set the scope to
profile
.
Your app can request additional scopes along with the login scope or request them anytime after the initial scopes have been granted. See Requesting additional scopes.
- If you need access to the user's identity, social graph and the ability
to write app activities, set the scope to
-
In your view controller's
viewDidLoad
method, configure theGPPSignIn
shared singleton instance by declaring its client ID, delegate, and scopes. Be sure to choose thesignIn.scopes
statement below that you picked in the previous step.- (void)viewDidLoad { [super viewDidLoad]; GPPSignIn *signIn = [GPPSignIn sharedInstance]; signIn.shouldFetchGooglePlusUser = YES; //signIn.shouldFetchGoogleUserEmail = YES; // Uncomment to get the user's email // You previously set kClientId in the "Initialize the Google+ client" step signIn.clientID = kClientId; // Uncomment one of these two statements for the scope you chose in the previous step signIn.scopes = @[ kGTLAuthScopePlusLogin ]; // "https://www.googleapis.com/auth/plus.login" scope //signIn.scopes = @[ @"profile" ]; // "profile" scope // Optional: declare signIn.actions, see "app activities" signIn.delegate = self; }
-
Implement the
GPPSignInDelegate
in the view controller to handle the sign-in process by defining the following method.- (void)finishedWithAuth: (GTMOAuth2Authentication *)auth error: (NSError *) error { NSLog(@"Received error %@ and auth object %@",error, auth); }
-
In your app delegate .m file, import
GooglePlus/GooglePlus.h
.#import <GooglePlus/GooglePlus.h>
-
Call the
GPPURLHandler
URL handler from your app delegate's URL handler. This handler will properly handle the URL that your application receives at the end of the authentication process.- (BOOL)application: (UIApplication *)application openURL: (NSURL *)url sourceApplication: (NSString *)sourceApplication annotation: (id)annotation { return [GPPURLHandler handleURL:url sourceApplication:sourceApplication annotation:annotation]; }
Add the sign-in button
Next, you will add the Google+ Sign-In button so that the user can initiate the sign-in process.
-
If you added the test code
[signIn authenticate]
from the previous section, remove that code from yourviewDidLoad
controller. -
In your view controller's .h file, add the forward class declaration for the
GPPSignInButton
.@class GPPSignInButton;
-
Also in your view controller's .h file, declare the sign-in button as a property.
@property (retain, nonatomic) IBOutlet GPPSignInButton *signInButton;
-
In your view controller's .m file, import the header files for the Google+ Sign-In button.
#import <GooglePlus/GooglePlus.h>
-
Synthesize the
GPPSignInButton
property if necessary, although this step should no longer be required in newer versions of Xcode.@synthesize signInButton;
-
Add the
GPPSignInButton
to your storyboard, XIB file, or instantiate it programmatically.GPPSignInButton
inherits fromUIButton
, so if you are using a storyboard or XIB file, you can drag a Round Rect Button or View onto your view controller and set its Custom Class toGPPSignInButton
. The resources for the sign-in button are contained in theGooglePlus.bundle
file and should be imported into your xCode project to add it to your target. -
Connect the button to the
signInButton
property of your view controller.
Next, you can implement and handle automatic signing in of the user.
Automatically sign in the user
If you run your app at this point, you will be able to use the Google+ sign-in button to sign in to the app. You might also notice that after your first sign in, subsequent sign-in attempts succeed "silently" without any disruption to your app.
The GPPSignIn
class has a trySilentAuthentication
method that attempts to
automatically sign in the user. This call succeeds if the user has
authorized your application in the past, they haven't revoked access to your
application, and the app isn't requesting new scopes since they last signed in.
If this call succeeds, it calls your finishedWithAuth:error:
method when sign
in is complete.
-
Add the
[signIn trySilentAuthentication]
call to the end of yourviewDidLoad
method.[signIn trySilentAuthentication];
-
You probably want to hide the sign-in button after the user has successfully signed in. You can test for your
GPPSignIn
'sauthentication
property and if it exists, the user has signed in and you can refresh your interface appropriately. For example:-(void)refreshInterfaceBasedOnSignIn { if ([[GPPSignIn sharedInstance] authentication]) { // The user is signed in. self.signInButton.hidden = YES; // Perform other actions here, such as showing a sign-out button } else { self.signInButton.hidden = NO; // Perform other actions here } }
-
Call this method in your
finishedWithAuth:error
handler.- (void)finishedWithAuth: (GTMOAuth2Authentication *)auth error: (NSError *) error { NSLog(@"Received error %@ and auth object %@",error, auth); if (error) { // Do some error handling here. } else { [self refreshInterfaceBasedOnSignIn]; } }
Sign out the user
You can use the
signOut
method of the GPPSignIn
object to sign out your user, for example:
- (void)signOut {
[[GPPSignIn sharedInstance] signOut];
}
Revoking access tokens and disconnecting the app
To comply with the terms of the Google+ developer policies, you must offer users who signed in with Google the ability to disconnect from your app. If the user deletes their account, you must delete the information that your app obtained from the Google APIs.
The following code example demonstrates how to programmatically revoke access tokens that your app was granted on behalf of the user and to disconnect the user's account from your app.
- (void)disconnect {
[[GPPSignIn sharedInstance] disconnect];
}
- (void)didDisconnectWithError:(NSError *)error {
if (error) {
NSLog(@"Received error %@", error);
} else {
// The user is signed out and disconnected.
// Clean up user data as specified by the Google+ terms.
}
}
The disconnect
method signs out the user in addition to disconnecting
and revoking tokens. You must not sign out the user prior to calling
disconnect
.
You can trigger the above disconnect
method from a button that you add to your
app. You can then respond to the successful disconnection within the
didDisconnectWithError
method and trigger any appropriate logic in your app or
your back-end code. For more information, see the
deletion rules in the developer policies.
Requesting additional scopes
Your app can request additional scopes anytime after the initial scopes have been granted. In this case, only those additional scopes will appear in the user's consent screen. Your app should request all previously granted scopes with these additional scopes to ensure your app proceeds with all the access it expects.
To request additional scopes, append the new scopes
to the scopes
property of the GPPSignIn
shared singleton instance,
then call the authenticate
method to request consent. You will received
a call back to your finishedWithAuth:error:
method as with a regular sign-in.
You might use this technique if you suspect users are avoiding sign-in because your consent screen is overwhelming new users, or if you think users are confused why they are being asked for certain permissions. In either case, you can delay the additional scopes and present them just before they are needed.
Enable server-side API access for your app
Follow this procedure if you want your servers to be able to make Google API calls on behalf of users or while they are offline.
With the earlier Enable sign-in procedure, your app authenticates the user on the client side only; in that case, the Google+ iOS SDK is able to access the Google APIs only while the user is actively using your app. With this procedure your servers can make Google API calls on behalf of users or while they are offline. For example, an photo app can enhance a photo by processing it on a backend server. To do this, your server requires an access token and a refresh token.
To obtain an access token and refresh token for your server, you can
request a one-time authorization code that your server exchanges for
these two tokens. You request the one-time code by specifying your
server's client ID along with your other GPPSignIn
parameters.
After you successfully connect the user, you will find the one-time code
as the auth
parameter server_code
accessible via the
finishedWithAuth:error
handler.
To enable sign-in for server-side access, follow the Enable sign in procedure above, but skip those steps 4 and 5 and instead perform the following steps 4 and 5.
-
In your view controller's
viewDidLoad
method, configure theGPPSignIn
shared singleton instance by declaring its client ID, delegate, and scopes. Be sure to choose thesignIn.scopes
statement below that you picked in the previous step.NOTE: The only difference from the earlier step 4 is the statement that sets
signIn.homeServerClientID
.- (void)viewDidLoad { [super viewDidLoad]; GPPSignIn *signIn = [GPPSignIn sharedInstance]; signIn.shouldFetchGooglePlusUser = YES; //signIn.shouldFetchGoogleUserEmail = YES; // Uncomment to get the user's email // You previously set kClientId in the "Initialize the Google+ client" step signIn.clientID = kClientId; // Your server's OAuth 2.0 client ID signIn.homeServerClientID = @"<SERVER-CLIENT-ID>"; // Uncomment one of these two statements for the scope you chose in the previous step signIn.scopes = @[ kGTLAuthScopePlusLogin ]; // "https://www.googleapis.com/auth/plus.login" scope //signIn.scopes = @[ @"profile" ]; // "profile" scope // Optional: declare signIn.actions, see "app activities" signIn.delegate = self; }
-
Implement the
GPPSignInDelegate
in the view controller to handle the sign-in process by defining the following methods. You can access the one-time authorization code returned after successful authentication.NOTE: The only difference from the earlier step 5 is the
serverCode
statement and its surroundingif
block.- (void)finishedWithAuth: (GTMOAuth2Authentication *)auth error: (NSError *) error { NSLog(@"Received error %@ and auth object %@", error, auth); if (error) { // Do some error handling here. } else { NSString *serverCode = [GPPSignIn sharedInstance].homeServerAuthorizationCode; } }
Troubleshooting
Authentication is slow - If the authenticate:
method is very slow, you
might be trying to call the method before your app has fully loaded. Try using
the trySilentAuthentication:
method instead. See automatically signing in
the user.
Error redirect_uri_mismatch
- This error can occur when you entered an
incorrect bundle ID in your
Google API Console project that does not match your app's
bundle ID. Check that your client ID and bundle ID match the values that are
displayed in the API Console.
Error invalid_client
- This error can occur when the client ID that you
entered in your app's controller does not match a client ID in your
Google API Console project. Check that your client ID and
bundle ID match the values that are displayed in the API Console.
Next steps
Sign in enables your app to use other Google+ features and access the user's Google+ profile information: