Google I/O 2013 – How to Offer Google+ Sign-In Alongside Other Social Sign-In Services
Articles Blog

Google I/O 2013 – How to Offer Google+ Sign-In Alongside Other Social Sign-In Services

IAN BARBER: If any of you worry
there’s no space at the front, there’s plenty. Feel free to move. So my name’s Ian. I’m a developer advocate
with Google+. And I’m going to talk today
a little bit about using authentication systems for
multiple providers in your code without having it turn into
a giant ball of hay that you don’t want to deal with. Hopefully over the last day and
a half, you’ve seen some things about sign-in in general,
maybe Tim Bray’s identity talk yesterday. And you’ll know that sign-in
is difficult. It’s very easy to make a fragile
implementation of identity, of passwords, of
dealing with account recovery, things like two-factor auth. It’s complicated. And it’s nice that you
can defer that. You can hand that off to some
other party who’s got the engineering, who’s got the
privacy and the security teams to look after it. So I think social authentication is a good thing. I think third party identity
providers are a good thing. But it doesn’t necessarily
follow that it’s a good thing to have multiple providers
on, right? You can easily get into a
situation where you have hundreds of buttons, and no
one wants to deal with it. But I think it is worth
considering adding more than one identity provider
to your application. I think there’s a reason that
it’s good for you, and there’s a reason that it’s good
for the users. For the users, it gives
them choice. And that choice is valuable. That choice allows them to
choose the one they’re most familiar with, choose the
one that works for them. But it also allows them to
express a facet of their personality. We don’t all use the internet
in the same way. And we don’t all use every
service in the same way. I have certain friends on
certain sites and certain networks, and certain interests
that I post there. If I can sign into your app
with the network that most closely aligns to my interest,
I can express myself more accurately. As a developer, the big gain is
that these days, identity providers don’t just
provide identity. They provide services. And you get access to those
APIs for users as well. So it’s valuable even if you
have a user who is connected to connect an extra network to
have ways of getting into additional systems so that you
can enhance your application, so that you can add more
services, so that you can do things which are a bit
more interesting. Now adding an identity
provider isn’t actually that hard. And if you just went out and
tried to implement Google+ Sign-In or Facebook or Twitter
or LinkedIn or whoever, you’d get it done in a reasonably
short time. It’s somewhere between
days and a few weeks. But it’s very, very easy to
spread knowledge of how a user is created throughout your
system and end up in a case where changing it then
becomes tricky. When there’s an API change, when
there is a newer version of something, it becomes
complicated to do so. It becomes complicated
to think about it. So what I think we need to think
about when we’re talking about multiple providers is
roughly these four things. We have to think about how the
user is authorized and authenticated. We have to think about what are
the capabilities of the various systems we’re
integrating with. What’s shared, and what’s
different, what’s special. We have to think about the
data model on our side. And we have to think about the
story for the user side. I’m not saying the user
interface or the user experience. Those are things which have been
covered elsewhere and are well worth spending time on. But I mean, why does
the user sign in? What is the mechanism
they are using? Why are they going to go
and press this button? What do they get out of it? Telling that story is an
important part of it, and having a feel for what signing
in means in your application. So when I say authorization,
I mean OAuth. OAuth is the dominant pattern
for authorizing access to services online, on
the web at least. And OAuth is very, very
well established. OAuth 2.0, standardized, lots
of good implementations. Most providers now are working
with OAuth 2.0. There are some with
OAuth 1.0, though. Twitter, I think, is
a notable example. But mostly, it’s moved
to OAuth 2.0. But OAuth is like giving the
keys to your house to a real estate agent to show
people around. Those people can come
to your house. They can see what’s there. But they don’t know
who you are. They just have access. So on top of OAuth,
we need to layer a service to give us identity. And in fact, there’s
standardization happening in that area as well. From the OpenID group, there’s
OpenID Connect, which is adding standardized identity
services which you can call with OAuth authorization. And we’re involved in it. Facebook are involved in it. A lot of the big systems
are moving that way. And I think that combination
of OAuth 2.0 and OpenID Connect is very, very
interesting. There’s a lot of very valuable
and powerful concepts that come out of it. And you’ll see those spread
through more of the more recent systems and services. But if you you’ve done OAuth 2.0
before, you might think of a flow something like this. There’s an app. It generates a URL. User clicks on the URL,
goes to the provider, authenticates, comes back. Sends a code to the
application. The application then exchanges
it with an identity provider. Straightforward, right? And this is well covered
by libraries. There’s tons of libraries out
here who will do OAuth exchange for you. But even on the web, it’s
not that simple. If you look at more modern
implementations, like Google+ Sign-In, like Facebook’s
client-side sign-in, you’ll see they don’t actually
redirect the user. They spin up an iframe. And in the iframe, the user
communicates directly with the identity provider. And then they communicate with
that iframe via the HTML5 post message API. That’s really cool. It’s faster. You get bi-directional
origin verification. You get an ability to do things
like seamlessly sign the user in when they
visit a site. You like those things. But it means this flow
isn’t quite right. On mobile, it’s even worse. On mobile, we have the
same flow, maybe. But how we actually deal
with that varies. Perhaps we’d want to bring a
browser up in the application. That could be a WebView in
Android or a UIWebView in iOS. We’ll have that flow,
and that will work. But that’s a terrible experience
for the users. They definitely don’t
have a cookie. So they’re going to have
to type in their username and password. And when they do that,
they can’t see where they’re typing it into. They can’t see the URL bar. They can’t check the
certificate. So maybe it’s better to send
them to the system browser. They may have cookies there. That’s great. And they can check
the certificate. They can see where they are. And that helps. It’s a better experience. But the user can still kind
of decide to go and do something else. So in a lot of cases, it’s
actually nicer to authenticate via another application. If you try and sign in on iOS
with Google+, we’ll actually take you to the Google+
iOS app. And you’ll sign in there. And that’s great because when
you have a nice, fast consent screen, you’re pretty much
guaranteed to be signed in to the actual application. And there’s no other
navigation. You’re not going to go off and
look at a bookmark bar or something like that. And of course, you could have
the actual authentication in the device itself. And that’s something like the
account manager on Android or the Social Framework on iOS,
where the accounts live with the device. And all of these complicate
how we implement even a straightforward flow. So what we’re trying to get
to is something like this. People don’t use your
app to sign in. They sign in to use your app. They sign in to get value
out of your app. And that’s all happening up in
the controllers, in a standard sort of MVC pattern. The controllers and the users. The UI, it’s the UX, it’s the
logic of what it’s doing. You don’t want to be thinking
in there about how your user came to be, about the process
of identification. You just want to think about
what you can do with the user. So what we want is for that
user to be generic– well, specific to your app, but
generic to the provider– and useful. Down here, though, is where the
actual user is generated. That happens in the identity
providers. You know they’re going to have
to actually sign in there. And we don’t want that leaking
all the way into the controller. So we need to put some
layer in between. And that’s the idea that really
underpins everything I’m going to talk about. If you take one thing away,
just take that away. Try and separate the
provisioning of identity from the usage of the user that
has been identified. So I’ve got some code
examples in here. And don’t worry if you wonder–
you know, you want to note some things
or take photos. All of the slides will
be online afterwards. The video for this talk
will be on YouTube. And there is code in here. I’ve got a bit of PHP for the
web, a bit of Java for Android and a bit of Objective-C
for iOS. But little sample apps will
all be up on GitHub afterwards. So don’t feel like you have
to follow every line. But this is kind of what we
want to be able to do. We want to be able to
just get a user. If I got a user? No. If I don’t, redirect them. If I do, use them. I just get the name. I activate it. I don’t have to think about
how this user came to be. I just have to use it. So to do that, we
need to mediate access to these things. Down this side is roughly
the user’s flow if they’re not logged in. They’ll come to some part of
your application where they need to be logged in. They’ll be redirected to a login
controller to choose their sign-in provider. Then something will happen,
depending on the provider. And eventually, they’ll come
back to the callback, where they will be given
back that code. They will be given back
some kind of token. And we will need to bring that
back into the application and sign them in. In between, we have this
authenticator. And the authenticator is
handling all of the identity stuff for the vast majority
of our app. In our sample apps, there’s
probably more identity code than anything else. But in reality, the vast
majority of your code should be business code, should be
doing what you want it to do. So we can get the
user from here. We can list the providers so
that we can create the sign-in options for them. We can take the response from
the outside world and route it to the appropriate provider. And in all of these cases, we
don’t want to have to know which each provider is– what they’re doing,
how they work. We want it to be hidden. So we need an interface. We need to separate the generic
parts of going through a sign-in process, checking
whether the user is authenticated, signing them in,
verifying that response to make sure they’re the
user we expect. And we need to provide a user. That’s at the heart of it. If we can’t provide
a user, we’re not doing anything useful. But then for each individual
provider, we need to implement a specific strategy of how to
go and do those things for this provider. So we have an interface. It’s how we decompose things
in an OO system. We have an interface which
defines exactly that thing. These are the functions. Now this is PHP, and it’s the
web, and it’s a slightly noddy demo example, so I’m just
getting a markup and getting script to actually
do the request. You might prefer to get a URL
or to return an object or to return a reference
to a template. There’s 100 different
ways of doing it. But the general idea is, you’re
going to need something that will initiate
the process. And that’s what that does
in this example. So even for a nice,
standards-compliant, OAuth 2.0 implementation like
GitHub, there’s things that are specific. GitHub have a certain way of
dealing with redirect URIs that’s not necessarily
the same way every other provider does. So we need to take that
into consideration. They also have their own URLs
for getting a token in the OAuth flow. They have their own URLs
for exchanging– for sending the user
to so that they can actually sign in. And we want to encapsulate
all that. So we have logic like this. This is just going to create a
token to avoid CSRF attacks. Put that into a URL along with
our client ID, our identifier of which application we are with
GitHub, our state value there, and the URL we’d like
users to be redirected to afterwards. All of this is private. All of this stays inside
our GitHub class. The external surface area
is getting markup. And in this case, we’re just
going to return a button. It’s a thing someone
can click. It’s not complex. We just get that URL, whack
it into some HTML, someone clicks it, fine. When they’ve done that,
they’re going to go away to GitHub. They’ll approve this
access, hopefully. And when they come back, they’re
going to come back with a code. That code is going to be sent
to our authenticator. Our authenticator is going to
work out which provider it needs to go to and
send it to that. And at that point, we
need to verify it. So in this case, we’re going
to do a token exchange. And we’re going to look at the
results of the token that comes back. So we take the short-lived
code we’re given. We send it off to GitHub. We get back an access token. And we can look at that and see
what we can do with it. For example, we can go and get
the user’s profile so we know their name. We know they are. Now if we do this with Google+,
we probably want to do it a little bit
differently. In Google+, we’d like to use
this nice JavaScript postMessage flow. So the markup isn’t a link. It’s this tag, which has the
g-signing class on it. And that’s going to generate a
button that’s going to trigger a JavaScript callback
once they click it. And then we can send the
response of that callback back to our server. So in this case, the user isn’t
getting redirected. We’re handling that through
JavaScript. But the same end result
kind of happens. Some information comes back to
our server, and we need to validate it. So we can send it through to our
validate function, which looks a bit like this. Same idea. Exchange token, get the
user’s profile. In this case, we can use the
Google PHP API client library to do that for us. But in either case, we
don’t have to care. We’ve done that. We’ve got that information. We can generate a user and
return it, and our controller code just deals with the user. Doesn’t have to think about
how that user came to be. But in our little example, I
was just getting the name. And the name’s not
very interesting. We want to do more interesting
things with the APIs we’ve exposed by signing in
with a provider. And that’s tricky because when
we’re doing that, we need to think about what specific
functionality each provider provides. There’s very little that is
shared between everyone you could sign in with. All we need to do, though, is
to think about what we’re trying to do rather than how
we’re actually doing it. If you imagine you had a section
on a site that had a kind of “Recommended For You,”
and there was a provider that returned an interest list, and
that was a list of entries in a database in some graph
database somewhere that said what you were interested in or
a list of entities that you were interested in, and you were
extracting tags out of that and using those
tags to look up content in your database. If you model it mentally as,
I get that information from there, you’re limited. You can only do it with them. If you think about, I just need
a list of tags, then you can do it a number of
different ways. You could get those tags
by looking at a social bookmarking site. You could get it from posts
or hashtags on a social networking site. You could go and look
at someone’s YouTube watch history. Once you think about it in terms
of the feature you’re actually trying to provide, you
then have the flexibility to implement it different ways
with different providers. It’s the same idea of separating
and abstraction there and not leaking the
details of that provider through to your application. So that means we need to
represent the user. And we do that, again, with an
interface because each of these providers is going to
return their own concrete user object which provides
this interface. So we’ve got the name. We’ve got the provider ID. We’ve got whether they can
do a certain feature. And we’ve got signOut and
disconnect so we can obey the various rules for various
networks on what options should be given to users. But you’ll note that we’ve made
a decision here which is a little bit subtle in that this
user has a provider and a ID, just the one. We’ve made the decision that
what’s happening here is you are signing in, not
signing up. And both models are common. When you sign in, there is a
one-to-one mapping between an identity provider account and
an application account. When you sign up, there is a
many-to-one mapping between identity providers and
a single app account. So each case is valid. Each case is a reasonable
thing. I can sign in with GitHub and
be me and sign in as Google+ and be me, or I can sign in with
those two networks and be two different users
on the system. It depends on what
you’re doing. And communicating this is part
of what the user story is, making them understand what’s
valuable for them. But who is the user, anyway? What are we actually storing? What are we actually
working with? A lot of the time when people
implement a provider, they take the ID, and they stick it
in the database column, and they’re done. And that’s bad. Because when you do that, you’ve
coupled yourself to that provider. As soon as you add another
one, that ID is no longer enough information. You need to always store a
tuple, a pair of the provider and the provider user ID. So in this case, this is Google
and my Google ID, Facebook and my Facebook ID,
LinkedIn and my LinkedIn ID. Those are all identifiers. And I can have multiple of those
referring to the same app user if I want to. And this is why things like
upgrade are not a problem. If you already had an OAuth 2.0
login, and you wanted to go to Google+ Sign-In, it’s
not a problem because the provider is still Google. The user ID is still
that user ID. It’s just a different way
of getting there. And thinking about it that way
means that you don’t have to worry about the exact strategy
being used to sign a user in. If you use a completely
different system on mobile than you do on the web, as long
as it results in that pair, you know it’s
the same user. And that’s great. Now the other thing people
look at is email. And email is often used to
combine accounts, which feels like a good thing. But it’s tricky. When you have an email address,
you have some knowledge about that user. That user probably had
that email address. Most providers will do
some verification. But the verification is likely
to be point in time. So at some point, the identity
provider sent an email to that address. The user clicked the email. They had that address then. But particularly with corporate
email, with email on free providers, sometimes
things get reused. Sometimes email belongs
to a different person. But it doesn’t mean that all the
other identities that have been associated with that
email get invalidated. So it can be a little risky
at times to rely on email. The OpenID Connect spec actually
says, do not assume email to be a unique
identifier. It is totally fine for an
identity provider to return an email address– the same email address– for
two different accounts. You should always look for
that ID and that provider identification. That’s the most reliable way
of dealing with them. But the way of having multiple
accounts is nice. So the Android code is in the
GitHub repo, the sort of sample we’re working with. That has this basic idea. You can sign in, and there’s a
bunch of features, pretty much the same as PHP. And when you sign in, we enable
the features that go with that network. But at this point,
we’ve created an app account as well. That’s why it can say, thank
you for using our app. Because it knows I’m new. I have local state to go with
my identity provider state. And that means I can attach
other identity providers as well. And then I get more features
available to me because those providers provide additional
features. And this pattern is very, very
common in the real world. This is TuneIn Radio, The Fancy,
and Banjo, all who implement pretty much
this structure. And you’ll see it in
many, many apps. All of them allowing you to
map multiple identity providers to a single
user account. And that means you need to think
about how the data is structured differently. You can’t think about
one table of a user. You have to have a separation
between the identity provider and the user. And it’s many-to-one. This is good, though, because
once you have this second table that has the provider user
ID, you can then key data against it. So if you retrieve some
information, you can put it into another table keyed against
the provider user ID. Which means if you need to
disconnect a user, and you have to follow data deletion
rules, it’s easy. You just look up everything
attached to that ID. If you have to expire a cache
after a certain amount of time, then it’s easy. You just look up everything
connected to that ID. So having this separation makes
it easier to structure your applications and structure
the data retrieved from your applications and the
provenance of that data. So to do this, we’re going
to do things a little bit differently. We’ve still got the
same basic model. We’ve got our authenticator
layer in the middle. Though in this case, it’s
going to be a fragment. We’ve got our providers, which
are going to be fairly dumb. And we’ve got our activity. But we know that our providers
are going to want to hold a little bit more state. We’d like our providers to be
able to be signed in, so that when you go in and attach
them, if you’ve already authenticated with that app in
that device, it’s quick. It’s a quick thing to do. So it speeds the process
for the user. And we know we’re going to
have to pass around some information. Activity results are going to
have to flow all the way back from the outside world, if it’s
going out to the system browser, back in to
our provider. But it’s roughly
the same idea. We’re sending information
back to be verified. And when we’re done, we
send the user back. But there’s an extra
complication in it. In this middle layer, we
don’t just send the user straight back. It’s the same as in PHP. We have a user created
in our provider. But we don’t just send
it straight back out to our main activity. Instead, we have this account
user concept, because we need to be able to deal
with those cases. We need to be able to go, does
this identity provider user map to an account user? Does it map to an account user
when one is already signed in? Is it the same user? We need to consider that state
before we return anything. And we won’t return anything
until we’ve resolved it into a central reliable application
user. So it’s pretty straightforward
for our activities. They get to do things
like this. They get a callback. They can get the name. They can test the features. They can see if the
user’s new. Simple. They don’t have to
do much at all. Our sign-in user, however, has
to do a lot more work. Rather than just being an
interface, it’s now a concrete object because it needs to carry
with it information. It needs to carry with it the
provider data for all of the providers that are attached. Previously, that was
kind of built in. If you had a Google user,
that Google user came with that data. In this case, we want to attach
Google data or LinkedIn data or Facebook data into
the same object. And we need access
to a database. Now in this case, this is
just a local SQLite. In reality you’d probably be
using Cinque to sync down to a web service somewhere or other
kind of communication. And your user store would
be on a server. But the basic concept
is similar. You’re going to have this
representation of a user stored away in a database. So to add a provider, all we
need to do is put their information into that hash we
defined earlier, and then, if the user ID is null– and that
ID, that mId, is the account user ID, is the app user ID. It’s not a provider one. That’s why there’s just an
ID no matching provider. If it’s null, we’re going
to then go and retrieve a user ID. Say, has this user signed
in with this provider? If they have, great. We know who this is. We can go with it. If they haven’t, we
can create a user. And that’s when we can
set the IsNew flag. We know we’ve had to build
a user for this. And all that’s doing is just
insert some reads on those database tables. And then it’s easy. Dealing with things like
features, all the features are is just a set of features
provided by each connected provider. So we just loop over the
providers we have in our object, and we can test
them to see, do you provide this feature? If you do, I’m good to go. Very simple for our object. And note, it doesn’t have to
know anything about who these providers are. The user never has to care about
who the providers are. They just follow
the interface. So you don’t have to leak that
provider-specific code into anywhere else in your
application. But the provider-specific code
gets to be relatively straightforward as well. You don’t have to do too much
with it because it doesn’t have to carry much more than
just its general state. So when we want to attempt to
sign in, to see if we’ve got a connection using Facebook,
we can just use the openActiveSession call with
allowLoginUI set to false. So that’s that middle
parameter there. And that means, we’ll try and
see whether we have a valid Facebook session running. If we do, cool. We’ve gotten a user account
ready to go. So if the user taps on us, we
can immediately serve it. If not, fine. We’ll just leave it. In the sign-in, though, where
a user action has been requested, we make the same
call but with that allowLoginUI set to true. So we’ll actively go
and make a call. We’ll actively present dialogue
to the users for them to sign in with. It’s precisely the same
with Google+. When we go in, we have
a connect call. That’s going to connect to
Google Play services. That’s where our authentication
has kind of been held. We go to Google Play services. We see whether we’re
signed in. If we’re not, we’re going to get
a call back with an error. And that error can be resolved
into an intent which will display some dialogue
to the user. So we just won’t do that. When the user signs in, we know
they’ve taken an action. So we can display that dialogue
to them and let them sign in and let them
authenticate with us. So that’s fine. And most of the time, we’re
in a really easy state. The user goes to the choose
a page, taps a sign-in, an account is created or looked
up, and there we are. We have an identity provider
and an app account. You come back another day,
or another user comes in, identity provider account,
app account, great. But sometimes you’ve
got this situation. And then the top user signs
in with the same identity provider, the same identity
provider account, which now maps to a second account. We’ve now got a conflict. And what we do with that depends
on the application and what you want to do with it. Most of the time,
you can go, ah, these users don’t conflict. We can just merge them. Whether that’s something the
user would be involved with or not, that’s up to you. But you know they’ve
signed in. You know they have
authenticated on both these systems. So they have access. So you can choose to merge
it if you want. And that’s roughly
what we do here. We just present a dialogue
to the user. Hey, this user already exists. But we can have those
map to the same app account if you want. Do you want to merge, or
do you want to switch? Because maybe you’d just
like to be this other user right now. We can give them that option. But sometimes we can’t. It’s easy to think of cases, but
there’s likely to be more app-specific cases in your
application, where there are things between accounts
that don’t allow them to be merged well. In this case, imagine there was
a third identity provider connected, and on that third
identity provider, two different users were
signed in. In that case, we couldn’t
combine them. We can’t merge those accounts
automatically. But we can still prompt
the user. They’ve done a legitimate action
by signing in with another provider. They genuinely have
access to that. We just can’t fix the
situation for them. So we can just say to them, hey,
do you want to switch? Or just cancel, stay
where you are. And all of that is mediated
by this authenticator. All of that is mediated in the
fragment, in this middle layer, without needing to
know about the provider. We can go in. We can see, is the
user ID null? If it is, we just take that
user, whatever’s been given to us by a provider. If it isn’t null, then
is it the same as the user that’s come in? So I’ve signed in
with Google+. I’ve signed in with Facebook. Both look up to the
same app user. It just connects the accounts. It doesn’t have to
do anything. If that’s not true, then
can I merge the users? What logic is required
to test that? That logic doesn’t have to
involve knowing anything about who the providers are. It can just be testing, is there
a conflict between these two sets of providers? And it can be doing
application-specific information. But again, we don’t have to look
into the provider to see how to do this. So I wanted to give you one
other way of looking at this kind of problem. Which is the idea that having
state for the identity provider user separate than
having application state is kind of beneficial. And you can use that to handle a
whole bunch of applications. So you might think of
a TV Guide that lives on a tablet app. TV Guide, different family
members want to see their chosen shows. But they don’t– it’s
not secret, right? They just don’t want to see
the other person’s. They want be able to switch. So that means it’s an
identity problem. You need to know who they are. But you don’t really care
about separating that data too much. You just want to make sure they
only see the stuff they want to see. So you can build something
like this. And this is in iOS. And we’ve just got our screen. It’s anonymous. You can tap Choose Account. When you choose account,
you get a list of attached accounts. In this case, there’s
my Facebook account and a Twitter account. And Google+ isn’t signed in. So I tap Google+. And then I sign in. I go through the regular flow. So even though these two
providers were signed in, that doesn’t automatically sign
me in to the app. I have to choose. I have to go through
an account chooser. Once I do it, I’m signed
in, and I can use the application as me. But if I want to change, I just
hit Choose Account and can switch again. This is very much like
the fast account switching in Gmail– in the Gmail app, where
you can choose what you’re using it is. That’s a really valuable
model. And it brings home the point
that identity doesn’t have to be like this huge lock and key
way of getting into systems. It can be anything that helps
the user use your application, helps them get what they
need out of it. So in this case, to keep it
lightweight, rather than have the view controller know
anything about our authentication layer in the
middle, I thought, why not use a message bus? And in iOS, NSNotification
Center is the sort of standard way of doing it. On Android, you could use any
EventBus type library. Otto Square is a good one. And in this case, the
user might go to the account chooser. The account chooser will communicate with the providers. If the user taps on one of them,
they just signal the authenticator which puts
a message onto the bus. And anyone that happens to be
listening that wants to know about it, knows. Very cheap, very
easy switching. Subscribing is as simple as
registering an observer of yourself with
kUserStatusNotification. That’s just the message type
you want to listen for. And checkUser is the function
that should be called when the message comes in. And publishing is pretty
much the same. So we don’t have to know
about what’s going on between those two. And in this case, we
need the identity provider to hold state. It has to know whether it’s
signed in because that doesn’t mean that we’re signed into
the app with that user. It just means they’re
available. So each of our identity
providers, when you sign in, may already have a user. They can return it right away. You want to track
that separately. And then if the user
signed in, we can actually prompt some UI. We can bring something up. And in fact, this is from
an example with Twitter. So with Twitter, we’re using the
built-in integration into the OS with the Social Framework
in iOS 5 and 6. So we can go in. We can request from the account
store accounts of type Twitter, see if we’re
granted access. If we are, we can retrieve
that user. Now we’ll do that either way. We’ll do that if we’ve started
the app right away, and we’ll do it when the user
taps Sign In. If we’ve started the app right
away, and the user has previously granted access, and
we retrieve a user, we won’t do anything with it. We’ll just keep it locally. And then when they sign
in, we return it. If this is happening once
they’ve already– once they’ve tapped
the button, we know it’s a user action. So down here, we’ll actually
take that user and return it back to our object. But again, wrapped in an
interface, wrapped in a way that means the actual view
controller doesn’t have to understand how that identity
was provisioned. They just have to use it. Google+, pretty much
the same thing. We return the user if we
have it available. Otherwise, we just call the
authenticate method on the shared instance of the
GPPSignIn object. Very straightforward. And that will kick off
the process for us. So I kind hope that’s given you
some ideas about ways you can think about combining
different providers. It doesn’t have to be all or
nothing incredibly complex integration. It can be simple and
lightweight, and you can just let users choose. And I hope it gives you some
ideas about benefits. I appreciate it is difficult. If you are doing a situation
where you’re merging multiple identity provider accounts onto
a single app account, there are edge cases. There are conflicts. And you’ll have to
resolve those. And that will take time. But if done right, I do believe
that it will not just give your users a better
experience. It will actually help the
structure of your applications. It’ll help you provide a good
system and a scalable system that is going to be flexible
when demands come up for you to change it, for you to change
versions, for you to upgrade, or to add
new providers. So that’s about it for me. We’ll do– got a few minutes
for questions. But I’ll be at the Google+
sandbox on the second floor afterwards if you
have any more. If you’re interested in this
kind of thing, Eric Sachs from our Identity team wrote a
really good document on running a login system with
an account chooser. It’s kind of web-centric. But the concepts and ideas
are fantastic. And it’s really, really helpful
if you want to think about this in more detail. If you’re interested in Google+
Sign-In, all of the documentation is on, and there’s sessions on it today. We had Android earlier. IOS at the end of the day
with XT and Silvano. We’ve got web with Ade up
next in here, I think. And then there’s a few other
sessions on things like best practices and how to integrate
throughout the day. All of the code for this talk,
if you are interested in it, is on GitHub. Or it will be as soon as I go
and make the repo public. And that is at that URL. And that’s about it for me. Thank you. [APPLAUSE] IAN BARBER: Yeah,
so questions. And as this gentleman has, if
you could come to the mic if you have questions, just so that
they’re on the recording, that’d be great. AUDIENCE: Thanks, Ian. It was a very practical
discussion. I really appreciate it. Yesterday, in Tim Bray’s talk
in the morning, I saw something really interesting,
something I didn’t really think you could do. He logged in to a demo
app that he’d written in Ruby with Google+. Then he set a preference, logged
out, and then logged in to it again with Facebook, and
it recognized that he was the same person both ways. And I’m kind of curious can you
give some practical advice on how to do stuff like that? IAN BARBER: Tim’s actually
just over there. So I don’t know– how did you
do it in your example? TIM BRAY: Well, exactly
what you said. There’s a layer of abstraction
in there that auto-merges these people if it detects
they’re the same person. Now I confess that because this
was a cheap demo app, I used email. Which is bad. IAN BARBER: Yeah. So yeah, Tim was just saying
that it’s exactly that kind of thing. He auto-merged people. And in that case, he used the
email address as the key. But it’s finding an identifier
and using that to go back and forth. I think there’s a lot of
different ways you can do it. And though I might say email
address is a problem in some cases, there are some cases
where you don’t actually care that much, right? If you just want a lightweight
way, and you’re not that bothered if some other
user gets access to it, it might be fine. And there’s loads of legitimate
cases for that, where you do want something
a bit lighter. So there’s always tradeoffs. There’s always what do you want
to do, and what the level of confidentiality and security
and functionality you need to provide is. TIM BRAY: Whereas it’s a bad
practice to rely on the email address, it’s also probably not
a good practice to ignore the case when you happen to
get two that are the same. A very reasonable course of
action might be something you suggested to us, which is to pop
up a dialogue, saying, oh, hey, you’re just signing in
as Tim Bray on Facebook. And I noticed you’ve been
signing in as Tim Bray as Google for the last
three weeks. Would you like to merge these? That’s a very reasonable
course of action. IAN BARBER: Yeah, absolutely. That’s a really good point. I think one of the subtleties
that tends to come into it which when you’ve got things
like multiple sign-in, is what do you do when users
kind of forget what they signed in with? And so that kind of
case really helps, if you can go, hmm. You’re a new user, but you
look like this user. Are you really them? And then give them the
option to merge. Luke Wroblewski actually had a
really interesting model he did where you could start typing
in your email address, and it would show you which
providers you’ve signed in with, which obviously could
be a privacy leak. So it’s something you have to
think about whether that fits for your app. But it was a really nice idea
where you could start typing things in and go, oh
yeah, that’s me. So that they hint which the user
should use if you do have that situation. Cool. Is there any other questions? Otherwise, I think
that’s about it. OK, thank you very much. [APPLAUSE]

Leave a Reply

Your email address will not be published. Required fields are marked *

Back To Top