Agenda

  • "Auth" and Google+ Sign-In
  • Auth Triangle: Your Client, Server, and Google
  • Client auth models across Android, iOS, and Web
  • Server auth
  • Choosing the right one for you
  • Q&A: Submit and vote on questions here http://goo.gl/48LOh

Talking about "auth"

  • Authentication
    • Verifies who you are
  • Authorization
    • Permission to do something
California Identification
Google I/O Badge

Don't Build Your Own Authentication!

  • Lots to worry about
    • Encrypt traffic
    • Hash + salt password
    • 2-factor authentication
    • Account recovery
    • More...
Rocket Science
http://spaceflight.nasa.gov/gallery/images/shuttle/sts-121/hires/sts121-s-030.jpg

Making Headline News

... but not the way you want.

Hack Headlines
Google News, May 11, 2013

Use An Identity Provider

  • Easier for you and the user
  • Can ask for authorization for additional features
  • A better way to reach your goal
Reach Your Goal
http://www.nasa.gov/centers/dryden/images/content/690557main_SCA_Endeavour_over_Ventura.jpg

Google+ Sign-In
Google+ Sign-In Button

How Does Google+ Sign-In Work?

Based on OAuth 2.0

OAuth 2.0 Permission Triangle
OAuth 2.0 logo from http://oauth.net/2/

Google API Console Project

https://developers.google.com/console

  • Create one project for your app with
    • Branding information
    • Multiple clients
PlatformClient Info
AndroidApp Package Name
iOSBundle ID
WebJavaScript Origins
Create Google API Console Project

Structuring your API Project correctly is important!

  • Authorization is granted to your app, not a specific client
  • For Android & Web:
    • Single user consent across clients
    • Google+ Sign-In automatically initializes clients with auth tokens, if available
    • Cross-platform Single Sign On

Your Client, Server, and Google

Auth Triangle: Your Client, Server, and Google

The connecting lines require auth

Auth Triangle

Client Auth: How to connect your app client with Google

Client Auth

  • Android
  • iOS
  • Web
Client Auth

Android: Client Auth

  • Managed via Google Play services API
    • Available on Android 2.2+
  • Auth using Google accounts on the device
Android Client Auth
Client Auth

Android: Client Auth

Connection Lifecycle

Resolution Lifecycle
http://www.riskcompletefailure.com/2013/03/common-problems-with-google-sign-in-on.html
Client Auth

Android: Client Auth

Coincides with the Android Activity Lifecycle

Android Connection Lifecycle

mPlusClient = new PlusClient.Builder(this, this, this)
  .setScopes(SCOPES).build();
findViewById(R.id.sign_in_button)
  .setOnClickListener(this);
mPlusClient.connect();
<com.google.android.gms.common.SignInButton
  android:id="@+id/sign_in_button"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content" />
mPlusClient.disconnect();
Client Auth

Android: Client Auth

Handle callback from mPlusClient.connect()

public void onConnectionFailed(ConnectionResult result) {
  // Save the result and resolve the connection failure upon a user click.
  mConnectionResult = result;
}

public void onConnected() {
  Person current = mPlusClient.getCurrentPerson();
  String gplusId = current.getId();
}
Client Auth

Android: Client Auth

Start Google Play services resolution onClick

public void onClick(View view) {
  if (view.getId() == R.id.sign_in_button  // Sign-In Button
        && !mPlusClient.isConnected()      // Not signed in
        && mConnectionResult != null) {    // We have next steps
    try {
      mConnectionResult.startResolutionForResult(this,
          REQUEST_CODE_RESOLVE_ERR);
    } catch (SendIntentException e) {
      mConnectionResult = null;
      mPlusClient.connect();
    }
  }
}
Client Auth

Android: Client Auth

Call connect() when Google Play services is done

protected void onActivityResult(int requestCode,
                                int responseCode, Intent intent) {
  if (requestCode == REQUEST_CODE_RESOLVE_ERR
        && responseCode == RESULT_OK) {
    mConnectionResult = null;
    mPlusClient.connect();
  }
}
Client Auth

Android: Client Auth

Connection Lifecycle

Resolution Lifecycle
http://www.riskcompletefailure.com/2013/03/common-problems-with-google-sign-in-on.html
Client Auth

iOS: Client Auth

  • Integrate with Google+ iOS SDK
  • SDK handles auth flows and token management
iOS Client Auth
Client Auth

iOS: Client Auth

Setup Sign-In

// In .m files as needed, or in your .pch file.
#import <GooglePlus/GooglePlus.h>
#import <GoogleOpenSource/GoogleOpenSource.h>

// In AppDelegate.m
- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  GPPSignIn *signIn = [GPPSignIn sharedInstance];
  signIn.clientID = @"YOUR_CLIENT_ID"
  signIn.scopes = kScopes;
  signIn.shouldFetchGoogleUserID = YES;
  signIn.delegate = self; // Implements GPPSignInDelegate protocol
}
Client Auth

iOS: Client Auth

User initiates with Sign-In Button

  • Add a button to your view
  • Set custom class to GPPSignIn
  • SDK localizes button and manages authflow
  • OR

  • Create your own button following our branding guidelines
  • Then explicitly call the following in the IBAction
  • [[GPPSignIn sharedInstance] authenticate];
    
Client Auth

iOS: Client Auth

// In AppDelegate.m
- (BOOL)application:(UIApplication *)application
              openURL:(NSURL *)url
    sourceApplication:(NSString *)sourceApplication
           annotation:(id)annotation {
  return [GPPURLHandler handleURL:url
                sourceApplication:sourceApplication
                       annotation:annotation];
}

- (void)finishedWithAuth:(GTMOAuth2Authentication *)auth
                   error:(NSError *)error {
  if (!error) {
    NSString *gplusId = [GPPSignIn sharedInstance].userID;
  }
}
Client Auth

Web: Client Auth

  • Simply include the JavaScript client
  • Add Google+ Sign-In Button
  • Handle auth callback
Web Client Auth
Client Auth

Web: Client Auth

Add Sign-In Button element and include JavaScript

<span id="signinButton">
  <span
    class="g-signin"
    data-callback="signinCallback"
    data-clientid="CLIENT_ID"
    data-cookiepolicy="single_host_origin"
    data-scope="https://www.googleapis.com/auth/plus.login">
  </span>
</span>

<!-- Place plusone.js asynchronous JavaScript
     just before your </body> tag -->
Client Auth

Web: Client Auth

Handle auth callback

function signinCallback(authResult) {
  if (authResult['access_token']) {
    // Successfully authorized
  } else if (authResult['error']) {
    // User is not signed in.
  }
}
Client Auth

Server Auth: How to connect your app server with Google

Server Auth

  • iOS
  • Android
  • Web
Server Auth

iOS Auth To Server

Send Access Token To Server

  • Send tokens securely
  • Access Tokens are bearer tokens and anyone can use them
  • Access Tokens last one hour
- (void)finishedWithAuth:(GTMOAuth2Authentication *)auth
                   error:(NSError *)error {
  NSString *accessToken = auth.accessToken;
  if (error) {
    signInAuthStatus_.text =
        [NSString stringWithFormat:@"Status: Authentication error: %@", error];
    return;
  }
  [self reportAuthStatus];
}
Server Auth

Android Auth To Server

Send Access Token To Server

  • Send tokens securely
  • Access Tokens are bearer tokens and anyone can use them
  • Access Tokens last one hour
try {
  String access_token = GoogleAuthUtil.getToken(this,
      mPlusClient.getAccountName(),
      "oauth2:" + TextUtils.join(' ', SCOPES));
} catch (UserRecoverableAuthException e) {
  // Recover
} catch (Exception e) {
  throw new RuntimeException(e);
}
Server Auth

Server: Verify Access Token

import httplib2
import json
url = ('https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=%s'
       % access_token)
h = httplib2.Http()
result = json.loads(h.request(url, 'GET')[1])

# If there was an error in the access token info, abort.
if result.get('error') is not None:
  return

# Verify that the access token is valid for this app.
if result['issued_to'] != CLIENT_ID:
  return

# Get the user ID.
gplus_id = result['user_id']
Server Auth

Android Auth To Server

Send One-Time Authorization Code

  • Code can only be used by your server
  • Code can get an Access Token and a Refresh Token
  • Refresh Tokens do not expire
try {
  String code = GoogleAuthUtil.getToken(this,
      mPlusClient.getAccountName(),
      "oauth2:server:client_id:" + CLIENT_ID
      + ":api_scope:" + TextUtils.join(' ', SCOPES));
} catch (UserRecoverableAuthException e) {
  // Recover
} catch (Exception e) {
  throw new RuntimeException(e);
}
Server Auth

Web Auth To Server

Send One-Time Authorization Code

  • Code can only be used by your server
  • Code can get an Access Token and a Refresh Token
  • Refresh Tokens do not expire
function signinCallback(authResult) {
  if (authResult['access_token']) {
    // Send code to server in POST request
    var code = authResult.code;
  } else if (authResult['error']) {
    // User is not signed in.
  }
}
Server Auth

Server: Exchange Authorization Code

$authorization.code = request.body.read
$authorization.fetch_access_token!
code = request.data
credentials = oauth_flow.step2_exchange(code)
$code = $request->getContent();
$client->authenticate($code);
Full code, including Java and C#/.NET, available in our Quickstarts
Server Auth

Ways To Enable Server-Side Auth

iOS Android Web
Verify Access Token
Exchange One-Time Code * - ✓ (new)

* The one-time code can retrieve a refresh token if you ask for offline access

Server Auth

Multiple Auth Systems

Proprietary password, Google+, Facebook

  • Trickier to support multiple-auth systems
    • e.g Need to consider ways to merge user identities across different systems
  • Talk by Ian Barber
    • How to Offer Google+ Sign-In Alongside Other Social Sign-In Services
Ian Barber

Review

Cross-Platform Auth with Google+ Sign-In