811-How-To-Offer-Google+Sign-In-Alongside-Other
Total Page:16
File Type:pdf, Size:1020Kb
Developers How to offer Google+ alongside other social sign-in options Managing Multiple Authentication Providers Ian Barber Google+ Developer Advocate Sign in with Google Log In Sign In Connect Sign in with Google Connect Sign In Sign Up Authentication & Capabilities Authorization Data Model User Story 5 OAuth Everywhere OAuth Logo: http://wiki.oauth.net 6 Patterns of Web Authentication App User IDP auth url auth & consent code code token 7 Patterns of Mobile Authentication App App App App Browser Browser App System 8 What Do We Want? Controller Controller User User Identity Layer IDP IDP IDP 9 Application Authentication Interaction PHP public function handle($path, $unsafe_request) { // Redirect to login if not logged in. if($this->auth->getUser() == null) { header("Location: /login"); exit; } $user = $this->auth->getUser(); $content = sprintf("<h1>Hi %s</h1>", $user->getName()); 10 Mediating Access View Authenticator Controller getUser() Github Login Provider Google Controller listProviders() Provider handleResponse() OAuth 2.0 onSignedIn() Callback 11 Authentication Strategies Check State Sign In Verify Strategy Strategy Strategy check token return markup retrieve token return code verify with server retrieve data Provide User 12 Provider PHP <?php interface Provider { public function getId(); public function checkState(); public function getMarkup(); public function getScript(); public function validate($unsafe_request); public function setCallback($callback); } 13 Strategy - Github private function getAuthUrl($options) { PHP $bytes = openssl_random_pseudo_bytes(8); $state = bin2hex($bytes); $params = array_merge(array( 'client_id' => $this->client_id, 'state' => $state, 'redirect_uri' => $this->redirect_uri ), $options); return self::AUTH_URL.http_build_query($params); } 14 Strategy - Github PHP public function getMarkup($options = array()) { $url = $this->getAuthUrl($options); return sprintf('<a class= "btn" href="%s">Sign In With Github</a>', $url); } 15 Strategy - Github PHP public function validate($unsafe_request) { // ... get $unsafe_request['code'] $context = stream_context_create($opts); $response = file_get_contents(self::TOKEN_URL, false, $context); $token = json_decode($response); if(isset($token->access_token)) { // ... 16 Strategy - Google+ PHP public function getMarkup() { return sprintf('<span class="g-signin" data-callback="signInCallback" data-clientid="%s" data-cookiepolicy="single_host_origin"> </span>', $this->client_id); } 17 Strategy - Google+ PHP public function validate($unsafe_request) { $this->gclient->authenticate ($unsafe_request['code']); $_SESSION[self::TAG]['token'] = $this->gclient->getAccessToken(); $_SESSION[self::TAG]['user'] = $this->plus->people->get("me"); // ... 18 How can we enable richer experiences? Recommended For You User getInterestList() 19 How can we enable richer experiences? Recommended For You User 20 Representing The User <?php PHP interface User { public function getProvider(); public function getId(); public function getName(); public function hasFeature($feature); public function signOut(); public function disconnect(); } 21 Sign In or Sign Up? 22 Who Is The User? (service, identifier) (google, 104824858261236811362) (facebook, 560561839) (linkedin,10492836) @ 23 Combining Accounts 24 25 26 27 Sharing Sessions TuneIn Radio The Fancy Banjo 28 Combining Accounts ProviderUsers Users ProviderUserId (int, primary key) UserID Provider (int, primary key) (varchar) Email UserId (varchar) (int) ProviderUserId (varchar) 29 Authentication on Android Activity Fragment Provider attach trySilent signIn onActivityResult onActivityResult onSignedIn onStatusChange 30 Mediating Access Sign In Activity Fragment LinkedIn getFragment() Provider getUser() Facebook Account Provider Google Activity signIn() onSignedIn() Provider Settings Activity Account User 31 Main Activity Fragment Callback public void onStatusChange(SignInUser user) { Java maintext.setText(user.getName()); graph.setChecked(user.hasFeature( ProviderUtil.Feature.GRAPH)); if(user.isNew()) { // For new users, give them an extra hello! Toast.makeText(this, getString(R.string.firstrun), Toast.LENGTH_LONG).show(); } 32 User Object Java public class SignInUser { private HashMap<Provider,Object> mProviderData; private String mName; private Integer mId; private boolean mIsNew; private DBAdapter mDb; 33 User Object - Adding Provider Data public void setProviderData( Java Provider idp, Object user) { mProviderData.put(idp, user); if (mId == null) { mId =mDb.getUserId(idp,getProviderUserId(idp)); if(mId == null) { mDb.createUser(idp, this); mIsNew = true; } } 34 User Object - Testing For Features public boolean hasFeature( Java ProviderUtil.Feature feature) { for(Provider p : mProviderData.keySet()) { if (p.hasFeature(feature)) { return true; } } return false; } 35 Strategy - Facebook public void trySilentAuthentication() { Java Session.openActiveSession(mManager.getActivity(), false, this); } public void signIn() { Session.openActiveSession(mManager.getActivity(), true, this); } 36 Strategy - Google+ Java public void trySilentAuthentication() { mPlusClient.connect(); } public void signIn() { mRequestCode = GPLUS_REQUEST; resolveLastResult(); } 37 Conflicting Accounts App Account IDP Account 38 Conflicting Accounts App Account IDP Account 39 40 Conflicting Accounts App Account IDP Account 41 42 Authenticator Mediates Merging public void onSignedIn(SignInUser user) { Java if (mUser == null) { mUser = user; } else if(mUser.getId() == user.getId()) { // ... merge provider data } else { if(mUser.canMerge(user)) { // ... show merge or switch } else { // ... how cancel or switch 43 44 45 46 Mediating Access Account Chooser Facebook Provider View Authenticator Twitter Provider Controller Google - providers Provider - setUser: NSNotification Center 47 ViewController Subscribes - (void)viewDidLoad { Objective-C [super viewDidLoad]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkUser:) name:kUserStatusNotification object:nil]; [self checkUser:nil]; } 48 Authenticator Publishes Message @implementation Authenticator Objective-C // ... - (void)setUser:(User *)user { _user = user; [[NSNotificationCenter defaultCenter] postNotificationName:kUserStatusNotification object:self]; } 49 Individual Provider Holds IDP State Objective-C - (void)signIn { if(self.user) { return [self returnUser]; } self.isUserAction = true; [self retrieveUser]; } 50 Individual Provider Holds IDP State - (void)retrieveUser { Objective-C [self.accountStore requestAccessToAccountsWithType:self.accountType options: nil completion:^(BOOL granted, NSError *error) { if(granted) { NSArray *accounts = [self.accountStore accountsWithAccountType:self.accountType]; if ([accounts count] > 0) { self.user = [accounts objectAtIndex:0]; 51 Strategy - Google+ Objective-C - (void)signIn { if (self.user) { return [self returnUser]; } self.isUserAction = true; [[GPPSignIn sharedInstance] authenticate]; } 52 Authentication Data Model User Story Capabilities & Authorization 53 <Thank You!> Ian Barber - http://google.com/+IanBarber Running a login system with an account chooser - http://goo.gl/R8pMP Google+ Developer Site - http://developers.google.com/+ Code from this talk - https://github.com/googleplus/googleIO-811 Developers.