WWDC2018 Session 721

Transcript

[ Music ]
>> Hello, and welcome to the
session on implementing AutoFill
Credential Provider Extensions.
In this video, I'll first give
an overview of the Password
AutoFill feature and how it is
improved in iOS 12.
After that I'll go into detail
about how Password Manager apps
can now integrate with Password
AutoFill using new APIs in iOS
12.
And along the way, I will
recommend a few best practices
to take as you adopt these new
APIs.
First, let's talk about Password
AutoFill.
iOS 11 brought two major
improvements to Password
AutoFill.
First, the most relevant
credentials were displayed
directly on the QuickType bar,
so they're only one tap away,
and second, iOS 11 brought
password AutoFill to apps.
This makes it super convenient
to use credentials from iCloud
keychain, whether they're needed
on the web or in apps, like the
shiny app you just saw.
And new in iOS and tvOS 12, you
can also use password AutoFill
in Apple TV apps by selecting
credentials to fill from an iOS
device.
These features are great for
users of iCloud keychain, but
some users rely on other
password manager apps to store
their credentials.
To make it just as convenient
for these users to access their
safe credentials, iOS 12 allows
password manager apps to
participate in AutoFill for the
same experience as iCloud
Keychain.
In iOS 12, there is a new UI for
password AutoFill settings,
which allows users to select an
app to provide credentials to
AutoFill, in addition to or
instead of iCloud Keychain.
Using the QuickType bar, the
user can bring up a list of
their credentials saved in the
password manager.
This UI is provided by an
extension bundled with the
password manager app.
When a credential is selected,
the extension hands it back to
AutoFill, and the username and
password are filled in the app.
Of course, this also works with
the QuickType bar suggestions as
well.
AutoFill can now surface the
best credentials as defined by
the app, so they're accessible
with just one tap.
When using these credentials,
the app extension can optionally
show its own UI to authenticate
the user before filling the
credential.
This integration makes logging
into apps even easier for users
of password manager apps, as
they no longer need to switch
apps to copy their credentials.
It also makes Password AutoFill
available in more apps.
Any app that supports AutoFill
from iCloud Keychain will now
work with Password Manager apps,
without any additional work.
With that overview, let's dive
into how you can implement these
capabilities in your password
manager app.
There are four main steps I'll
cover.
First, you'll need to configure
your project to take advantage
of some new APIs.
This involves adding a
capability to your app and an
extension to your project.
AutoFill will use this extension
when it needs to consult your
app or show its UI across the
system.
Next, your extension will need
to support showing the user a
list of their credentials to
choose from when they open your
extension from the QuickType
bar.
After that, if you want AutoFill
to show your app's credentials
in the QuickType bar, you will
need to add support for this by
telling the system about the
credentials you want to show,
and implementing another API in
your extension to respond to
users selecting those
credentials.
And finally, you may want to
take advantage of an API that
will allow you to present your
extension's UI when users enable
your Password Manager in
Settings.
Let's talk about these steps in
more detail.
First, you will need to make a
few changes to your project.
This starts with enabling
AutoFill Credential Provider in
your app's capabilities.
This adds a required entitlement
to your app, and links it to the
new authentication services
framework, which provides the
APIs for Password Autofill
integration.
Next, you will need to add an
AutoFill Credential Provider
Extension target to your
project.
Xcode 10 includes a new template
for this extension.
The template will create a view
controller class for you.
A subclass of AS credential
provider view controller.
When AutoFill needs to invoke
your extension, it will create
an instance of this class and
call certain methods on it,
which your subclass will
override.
So once you've configured your
project, the first thing to
implement in your extension is
the list of credentials that the
user can bring up from the
QuickType bar.
Here is how this works.
When the user is signing into an
app, they can use the QuickType
bar to bring up your credential
list.
At this point, AutoFill will
launch your app extension and
let it know where the user is
logging in, so you can suggest
the most relevant credentials.
AutoFill will do this by
preparing a list of AS
credentials service identifier
objects, representing the
service the user is currently
using.
Your extension may receive
multiple service identifiers, if
AutoFill can determine multiple
better [inaudible] to use in the
current context.
In apps, service identifiers are
based on the app's associated
domains.
Apps that have adopted universal
links hand-off or shared web
credentials will have associated
domains.
For example, the Shiny app is
associated with
shiny.example.com, so AutoFill
will provide your extension a
service identifier of type
domain for shiny.example.com.
In Safari, the service
identifiers are based on the URL
of the current page the user is
logging into.
AutoFill will send the service
identifiers to your extension by
calling the prepared credential
list for service identifiers
method on your view controller.
Here, your extension should set
up its UI for displaying the
user's credentials, and it can
use the provided service
identifiers to prioritize the
most relevant ones.
From here, two things can
happen.
If the user chooses to dismiss
your extension, you tell the
system about this by calling
Cancel Request With Error on
your view controller's extension
context, and AutoFill will
dismiss your extension.
Otherwise, if the user selects a
credential they want to use,
your extension creates an AS
password credential object based
on the user's selection and then
hands it to AutoFill by calling
the complete request with
selected credential method on
the extension context.
And AutoFill will use that
credential to fill the username
and password in the app.
There are a few best practices
the credential list should
adhere to for the best user
experience.
First of all, be sure to include
a button in your UI to cancel
the request.
The user may change their mind
about signing into the service,
or realize they don't have a
credential saved, so you should
support letting the user dismiss
your extension without selecting
a credential.
Also, your credential list UI
should make it possible to see
all credentials, whether or not
they match the service
identifiers.
In some cases, the user may need
to choose a credential from a
different domain.
Allowing the user to access
their entire set of credentials
from the list, ensures your
extension is always useful.
And user authentication is
completely up to your extension.
If you need to authenticate the
user, you should do so when the
credential list is presented.
And that is how you can
implement a credential list in
your extension so your app's
credentials are available to use
when signing in anywhere.
Now we will make this even more
convenient by allowing AutoFill
to surface these credentials
directly on the QuickType bar.
I'll start with an overview of
how this process works,
describing the roles played by
your code, the system, and the
app where the user is signing
in.
To start with, your app needs to
let AutoFill know ahead of time
what credentials it wants to
make available for the QuickType
bar.
Your app provides AutoFill a
list of credential identities.
The credential identity includes
information about a credential,
such as the username and the
service, but not the password.
When the user begins signing
into an app, the app talks to
AutoFill, and lets it know when
a username or password field is
focused.
AutoFill then looks for
appropriate credential
identities to suggest for the
app.
It does this by searching
through the credential
identities that your app has
already provided, so your
extension doesn't need to be
launched yet.
If there are any matching
credential identities to
suggest, AutoFill displays them
on the QuickType bar.
These suggestions are rendered
privately by the system, so the
app isn't yet able to determine
what credentials the user has
saved for the app.
When the user selects one of the
suggestions, AutoFill launches
your app extension to ask it for
the full credential, including
the password.
It will tell your extension
which credential identity the
user chose, then your extension
looks up the password belonging
to the selected credential in
your app's password database.
At this point, the extension has
the option to present its own UI
before returning the password.
This is useful for password
manager apps that ask the user
to enter a master password, or
perform another type of
authentication specific to the
app.
Once your extension has the
password, it packages it in an
AS password credential and hands
it to AutoFill by completing the
extension request.
If the extension didn't show its
own UI, AutoFill will perform
appropriate authentication for
the user.
Depending on the device and the
user's preference, this may be
Face ID, Touch ID, Device
Passcode, or None.
If that authentication is
successful, AutoFill will fill
the username and the password in
the app.
There is a lot going on here, so
I'm going to walk through the
steps you need to take as a
developer to support this
workflow.
The three things you need to do
are provide AutoFill with the
credential identities you want
it to suggest to the user.
Implement support in your
extension to provide the
passwords when those suggestions
are selected, and display custom
UI in your extension to
authenticate the user before
returning the credential, if
your UX requires it.
Once again, this step is
optional.
If you don't show custom UI for
authentication, AutoFill will
perform appropriate
authentication for you.
Credential identities are
represented by instances of AS
Password Credential Identity.
This class contains all the
information about a credential
that AutoFill needs to know in
order to determine where to
offer it.
This includes a service
identifier, which tells AutoFill
which apps or websites to
suggest the credential on.
The username of the credential,
and optional record identifier
string that you can use to
correlate this identity to a
record in your app's own
database, and a rank parameter.
If the user has more credentials
for a particular service than
the QuickType bar can show, you
can use the rank parameter to
mark certain credential
identities as higher or lower
priority.
Credential identities having a
higher rank value will be
ordered before credential
identities with lower ranks.
These credential identities get
saved to the Credential Identity
Store, which is the database
inside your app's container that
you can modify using the AS
Credential Identity Store class.
AutoFill suggests credentials to
the user by searching through
your app's Credential Identity
Store.
The Credential Identity Store is
secured with complete unless
open data protection, so no
operations can start while the
device is locked.
The system never syncs the
Credential Identity Store to the
Cloud or includes it in backups,
so this information never leaves
the device.
Each app has its own Credential
Identity Store, and only the app
and its extensions can modify
it.
The store is only read by
AutoFill for determining which
credentials to suggest to users.
And the Credential Identity
Store can only be modified while
your app's extension has been
enabled by the user.
If your extension is disabled,
attempts to update the store
will fail.
And if the user disables your
extension or deletes your app,
the Credential Identity Store
will be deleted.
Your app should update its
Credential Identity Store when
it has new information about
what credentials it can offer.
As an example, let's say your
app uses an online service to
store the user's credentials.
When the user signs in, your app
would start retrieving the
user's credentials.
At this time, you would update
the list of credential
identities in the store, so the
newly-fetched credentials could
be suggested on the QuickType
bar.
As the user adds, removes, or
modifies their credentials, your
app updates the Credential
Identity Store so it continues
to accurately reflect this set
of credentials that your app can
provide.
These updates might be because
the user locally makes changes
within your app, or perhaps
because your app is
synchronizing changes from other
devices signed into the online
service.
Then, if the user were to sign
out of the online service on the
current device, your app would
remove all the credential
identities from the store, so
the user doesn't continue to see
suggestions for these
credentials.
In your code, you use the AS
Credential Identity Store Class
to interact with the Credential
Identity Store.
Using the Replace Credential
Identities With and Remove All
Credential Identities methods,
you can replace or clear the
list of credential identities
that AutoFill will consider
suggesting.
When individual changes are
made, these saved credential
identities or removed credential
identities methods allow you to
add, update or remove credential
identities without completely
replacing the contents of the
store.
One important aspect of the
system to understand is that the
Credential Identity Store may be
deleted at times that your app
won't be able to predict.
As a few examples, if the user
disables your extension for
AutoFill, then later re-enables
it, the system will have cleared
the store.
If the system determines that
your app provides credential
identities, but consistently
fails to provide the passwords
when the user selects these
credentials, the credential
identity store may be deleted to
prevent the user from seeing
these stale credential
suggestions.
If the user restores their
device from a backup where they
were using your credential
provider extension, the store
won't contain any credential
identities since it wasn't
included in the backup.
Your app should be able to
handle these cases, and AS
Credential Identity Store can
help you detect these cases, so
you can take the appropriate
action when you need to update
the store.
You can use the Get State method
to ask the system about the
state of your app's Credential
Identity Store, return it as an
AS Credential Identity Store
State Object.
The first thing it tells you is
whether or not the user has your
app extension enabled.
You should check this before
attempting to update the
credential identity store.
If your extension is disabled,
there is no point in trying to
save or remove credential
identities.
The State also has a Supports
Incremental Updates Property,
which you can use to determine
if the Identity Store is intact
since the last time you've
updated it.
If you previously saved any
credential identities to the
store, this will return true,
indicating you should use the
incremental Save Credential
Identities and Remove Credential
Identities methods.
Otherwise, if the Store hasn't
been written to yet, perhaps
because your app was just
disabled and re-enabled,
Supports Incremental Updates
will return false.
And you should populate the
Identity Store by providing the
full list of credential
identities using the Replace
Credential Identities With
method.
Once your app starts saving
credential identities to the
store, AutoFill can start
suggesting your app's
credentials in the QuickType
bar.
Next, you'll need to add support
in your extension to provide the
password when one of these
credential suggestions is
selected.
When this happens, AutoFill will
first launch your extension and
ask it for the password without
presenting your UI on screen.
When it does this, AutoFill will
call the Provide Credential
Without User Interaction For
method on your view controller,
providing an AS Password
Credential Identity,
representing the credential
being filled.
In this method, you will look up
the associated password
belonging to the given
credential and hand it back to
AutoFill using the Complete
Request With Selected Credential
method.
If your extension wants to have
its UI presented at this point,
cancel the extension request
with the User Interaction
Required error code in the
domain AS Extension Error
Domain.
The system will then call the
Prepare Interface To Provide
Credential For method on your
view controller, and present its
UI.
In this method, your extension
sets up its UI for its workflow
to provide the password.
When the password is eventually
available, you return the
credential to AutoFill, also
using the Complete Request With
Selected Credential method.
Once again, if your Extensions
UI was presented, AutoFill won't
perform any authentication
before filling the returned
credential.
It is up to your extension to
decide what type of
authentication is needed.
The most important thing to keep
in mind when implementing this
functionality is that your
extension needs to respond to
the initial non-UI request
quickly, regardless of the
results.
Your UI hasn't been presented
yet, so it's not obvious to the
user that your extension is
working in the background.
If it takes a long time to
return the password, the user
may perceive the system, your
app, or the service they're
using as being unresponsive.
This would be a poor user
experience.
And this is so important.
If a few seconds pass, and your
extension hasn't returned the
password, requested to show its
UI, or canceled with another
error, AutoFill will cancel the
extension without filling the
credential.
However, this timeout doesn't
happen for debug builds, or when
running on the simulator, so you
can take your time to debug the
extension without the system
interrupting.
When you're implementing support
for displaying your app's
credentials on the QuickType
bar, it's essential that you
keep the Credential Identity
Store up to date, and in sync
with the credentials your app
knows about.
If the store becomes out of sync
with your app's data, the user
might not see newly added
credentials on the QuickType
bar, or may continue to see
credentials on the QuickType bar
even after they've been deleted
from your app.
You should take advantage of AS
Credential Identity Store's
incremental update APIs.
Replacing the entire list of
credential identities every time
any credential has changed, may
become expensive the more
credential identities you need
to update.
It's better for performance to
incrementally save new
credential identities or remove
deleted ones as those changes
are made, rather than re-writing
the entire store.
Keep in mind, when your
extension is being called, the
user is in the middle of using
another app.
Keep the interactions and your
UI to a minimum, and only
include what the user needs in
order to user their passwords.
If loading your password
database involves expensive
setup, avoid redoing the setup
in the view load method of your
view controller, and tearing it
down later.
The system may reuse your app
extensions process if the user
sequentially signs into multiple
services using your extension.
Consider using a singleton
pattern, so any work done in one
invocation of your extension can
be reused the next time if it
doesn't need to be repeated.
And that wraps up how you can
display credentials from your
app in the QuickType bar.
Finally, I'll discuss one more
API your extension may find
useful.
When the user enables your app
extension for Password AutoFill,
you may have some setup that
needs to be done before the user
can get the best experience.
For starters, if you support
showing credentials in the
QuickType bar, your app or
extension will need to provide
its credential identities to
AutoFill first.
But it may also be useful to
show other settings at this
point, perhaps to offer the user
the ability to sign in to an
online service to retrieve the
passwords if they haven't
already.
Authentication services provides
an API to support these work
flows.
When these are enabled to your
extension, settings can launch
your extension and present its
UI, so you can let users
configure it.
To opt into this behavior, open
the Info Property List for your
app extension and add a new key
under NS extension attributes.
AS Credential Provider Extension
shows configuration UI with the
bullion value of yes.
This is how the system will know
to launch your extension when
its enabled.
Then, implement the Prepare
Interface For Extension
Configuration method in your
view controller, and set up the
appropriate UI for when your
extension is first enabled.
When your extension is done,
call the Complete Extension
Configuration Request method on
your extension context, and
settings will dismiss your UI.
At this point, your extension is
enabled.
It has provided credential
identities for AutoFill to
suggest for the QuickType bar.
It can provide the passwords
when those suggestions are
chosen, and it can show the user
a list of all their credentials.
You're now done integrating your
app with Password AutoFill and
the users can enjoy the
convenience of AutoFilling
Passwords saved into your app
wherever they're needed.
There are just a few more
general best practices to
consider while developing your
extension.
As discussed before, your
principal view controller may be
responsible for showing the UI
for a diverse set of
functionalities.
To achieve this, we recommend
using separate view controllers
managed by your principal view
controller.
For example, you may want to
have one view controller class
for displaying the credential
list.
And another for authenticating
the user when filling
credentials.
You can either present these
view controllers from your
principal view controller, or
use view controller containment
to embed their views.
And if you prepare your
interface by presenting view
controllers, the presentation
should be done without
animation, since the
presentation of your principal
view controller is already
animated.
In general, extensions should be
lightweight and ready to
terminate when they're done, and
this includes AutoFill
Credential Provider Extensions.
Your extension will be invoked
to perform one particular task,
and you shouldn't include any
unnecessary work flows or user
interactions beyond what is
needed.
Be aware that the system may
terminate or suspend your
extension for various reasons at
any time.
For example, the system will
terminate AutoFill Credential
Provider Extensions while
they're in use if the user
switches apps.
And your extension will have a
separate sign box from your main
app, but it will still need to
share data, such as the user's
credentials.
Use App Groups or Shared
Keychains to share data between
your app and its extensions.
For a review about extension
development in general, refer to
the Creating Extensions for iOS
and OS X part two session from
WWDC 2014.
Finally, you can use Safari if
you need to debug your
credential provider extension
while testing filling
credentials.
To do this, first activate the
extension scheme, select a
target, and select Run.
When you do this, Xcode will ask
you to choose an app to host the
extension.
Choose Safari from the list, and
click the Run button.
Safari will then open, and you
can navigate to a sign-in page
where you want to test your
extension.
When you open your credential
list, or select a credential
from the QuickType bar, your
extension will be launched, and
Xcode will attach the debugger
to it, so you can begin your
debug session.
For debugging your extension in
the other cases, use the Attach
to Process Item in Xcode's debug
menu to start attaching the
debugger.
You can then manually open
Settings to enable your
extension if you want to test
the settings UI, or you can open
any app's login screen if you'd
like to debug AutoFill there.
In summary, iOS 12 enables
Password Manager apps to
integrate with Password
AutoFill.
Using APIs from the New
Authentication Services
framework, your credential
provider extension can show the
user a list of their
credentials.
Show credentials on the
QuickType bar, and optionally
provide a way for the user to
configure the extension from
settings.
For more information, refer to
the Apple Developer Page for
this session.
To learn more about the other
improvements to password
management in iOS 12, see the
Automatic Strong Passwords and
Security Code AutoFill session.
And if you'd like to learn more
about the Password AutoFill
feature and associated domains,
see the Introducing Password
AutoFill for Apps session from
WWDC 2017.