Learn how you can provide safe and fast authentication in your app using Sign in with Apple. We'll show you how you can upgrade password-based accounts into secure, single-tap login credentials, and explore how you can seamlessly handle changes to user sessions in your app. We'll also help you take advantage of Sign In with Apple across the web and on other platforms.
Ram: Hi. My name is Ram. I'm an engineer on the account experiences team. I'll be joined by my colleague Patrick to talk about how you can enhance your Sign in with Apple experience for your app. Since Sign in with Apple was introduced in iOS 13, people love the fast, easy account setup and sign-in. With just a few lines of code, you can enable quick, one-tap account setup with no forms or passwords. Every Sign in with Apple account is protected by a strong two-factor authentication that is already used to secure the user's Apple ID. If you need to communicate with your users, Sign in with Apple provides you with an email address that just works. There is no additional verification required. Sign in with Apple also provides an indicator for how likely the user is indeed real. This can help you combat fraud. And Sign in with Apple works everywhere, including your managed Apple IDs that you use for work and school. To learn more about how you can integrate your app with work and school accounts, check out the session "Discover Sign in with Apple at Work & School." In this session, we are going to talk about how you can enhance and streamline your Sign in with Apple experience.
First, I will discuss how you can prevent account duplication by checking for existing credentials in your app. Next, I'll take a deep dive into the Apple ID credential, and then, I'll talk about some of the ways you can monitor credential changes and discuss how to handle scenarios like account deletion. And finally, Patrick will discuss how to integrate Sign in with Apple on the web and other platforms. Let's get started. Sign in with Apple is a convenient and secure alternative to traditional username- and-password-based authentication, but your users could still have accounts that are unlocked with passwords. So if your user already has an account that works for them, it is important not to create a second account for your app.
I'll explore how you can guide someone to make the right decision while signing in.
This is Juice, a sample app that uses Sign in with Apple. You can find its source code in the related links for this video.
You can sign in to Juice either using traditional email and password or using Sign in with Apple. If your user has either of these credentials already, it is in your hands to help them sign into the right account. To start with, be sure to implement password autofill so that existing password credentials are displayed on the keyboard for your login screen.
This way, the user can autofill the credential with just one tap.
Also, you should provide your users to upgrade their password-based accounts to Sign in with Apple. Once upgraded, your users will get an account that has security built in, and they have one less password to remember. This is implemented using the Account Authentication Modification Extension. The extension-based API provides seamless experience for your users to upgrade the way they sign in using Sign in with Apple.
For more information on providing security upgrades for your users' accounts, check out the docs "Get the most out of Sign in with Apple" and "One-tap account security upgrades." Apart from providing password autofill, you can go a step further by presenting existing credentials as soon as your app launches. This way, your users can sign in using the right account even before they reach the login screen.
The Authentication Services API is really flexible this way. Besides allowing a user to create a Sign in with Apple credential, the API can also present existing credentials, including password-based credentials.
Adopting this is really easy. Let me take you through some code on how to achieve this. If you're already using the Authentication Services API, this code should be very familiar.
You start by creating an instance of ASAuthorizationController and include both ASAuthorizationAppleIDProvider as well as an ASAuthorizationPasswordProvider in the authorization request array. Then you'll need to set up a delegate and an object to help with presenting the interface. And finally, you'll need to call performRequests with the option preferImmediatelyAvailableCredentials on your authorization controller. This option is new on iOS 16. It tells the system that you only want credentials that are immediately available on the device. It is intended specifically to be called on app launch.
If you want to support previous iOS versions, you can use performRequests. When you do this, you will be presented with a list of existing credentials. Your user can now select either an existing Sign in with Apple credential or an existing password credential. After the user has selected a credential, the system will call didCompleteWithAuthorization on the ASAuthorizationController delegate. If the user chose a Sign in with Apple account, you continue with the appleIDCredential. If the user chose a password-based account, you sign in with the passwordCredential returned. If the user has no existing credential, the API will not present the user to create a Sign in with Apple account. Instead, the system will call didCompleteWithError. You should fall back to showing standard login flows in such scenarios.
By the way, the same Authentication Services API also works seamlessly for passkeys. To learn more about passkeys, a next-generation authentication technology to replace passwords, check out the session "Meet passkeys." With just a few lines of code, you can take full advantage of the sign-in experience. You can now help your users select the right account, and hopefully, this prevents duplicate accounts from being created in your system.
Next, I'd like to take you on a deep dive on Apple ID credential.
As you know, the response you get after a successful authorization using Sign in with Apple is an ASAuthorizationAppleIDCredential object. It contains values like user, fullName, email, realUserStatus, identityToken, and authorizationCode.
I'll cover each of them briefly. User is a unique and stable identifier. It is the same identifier across all the apps in your developer team.
Use this to uniquely identify users in your system. You should ask for fullName only if you need it. If requested, your users can share any name they want. If you want to communicate with your users, you should ask for the email. When requested, your users have two options to share their email address. One option is to share the email associated with their Apple ID. The other option is to use the "hide my email" feature. This creates a hidden email address that routes to their inbox.
It is a two-way relay, so it can handle replies, too.
Regardless of which option is chosen, the email address has been previously verified by Apple, and it is ready to use. Also, not all accounts have an associated email, so be prepared to handle scenarios where there is no value for email, even if you requested it.
RealUserStatus is a high-confidence indicator on how likely the user is real. It is calculated using on-device machine learning, account history, and hardware attestation whilst preserving the user's privacy. There's three types for realUserStatus. "Likely real" means the user appears to be a real person. Provide this user with the best experience, such as skipping additional fraud verification checks like CAPTCHAs. "Unknown" is when the system hasn't determined whether the user is a real person. Trust this user as you would for any account with limited information that requires additional verification steps. The user could still be real, so do not block them from using your app.
And finally, "unsupported" means the system is not capable of this determination.
I should take a moment to call out that the properties like fullName, email, and realUserStatus are only returned when an account is created for the very first time.
They're not returned upon subsequent sign-ins, so make sure to securely cache properties like fullName and email until you can verify that an account has been created in your system.
The identityToken is a JSON web token that contains most of the data that the app server needs, including the user information. This is an industry-standard approach to authentication.
The JSON web token, or JWT, consists of three parts: a base-64 URL encoded header, a base-64 URL encoded payload, and a signature signed by Apple.
You should verify the signature with Apple's public key to ensure that the response has not been tampered with and is indeed from Apple ID servers. It is also equally important that your app server checks the validity of the token. Once you decode the payload, you should verify the issuer is appleid.apple.com, verify the audience field is your app's bundle identifier, then make sure the expiry timestamp is greater than the current time so that you know the token is valid. Subject will be your user identifier. If you requested for the user's email address, it will also be included. You can also find the realUserStatus. The value will be 0 for "unsupported," 1 for "unknown," 2 for "likely real." And finally, verify that the nonce is the same as the one generated prior to the creation of the authorization request.
For more information on nonce and how to secure your authorization process to mitigate replay attacks, check out the session "Get the most out of Sign in with Apple." AuthorizationCode is a short-lived, single-use token that you can provide Apple ID servers in exchange for refresh tokens.
If your systems already use open standards like OAuth 2.0, this might be familiar for you.
To generate a refresh token, you should send a post request to the auth/token endpoint.
You pass on the client ID and the client secret along with the authorization code that you just received. A detailed description on how to create the client secret is available in the Apple Developer documentation. In the response, you will get a refresh token, an access token, and a new identity token similar to the one you received earlier. If you have an expired access token, you can use the refresh token to obtain a new access token using the same endpoint. You can also continue to use the same refresh token until it gets invalidated. The refresh token could get invalidated if the token verification fails or if there are changes around your user's session.
Speaking of user session, next, I’ll talk about handling and monitoring changes around the credential state.
After verifying the identity token, your app is responsible for managing the user session.
There are various scenarios that can trigger user session changes. For example, a user could stop using Apple ID with your app from Settings, or they could have been signed out of the device.
To handle session changes gracefully, call the getCredentialState(forUserID:) on the ASAuthorizationAppleIDProvider. This API is recommended to be called as soon as your app launches or at any point where you wish to check the state. You should also observe for credentialRevokedNotification so that your app is notified when the credential is revoked. If you observe any change in the state, you should assume that a different user has signed in and sign the current user out of the app. If you have an app server, you should subscribe to server-to-server notifications. Your server will receive important updates about your users and their accounts. Notifications are sent to each group of apps for the following scenarios: when the user disables or enables their mail forwarding preference; when the user stops using their Apple ID with your app; or when the user permanently deletes their Apple ID.
To start receiving notifications, you should first register an endpoint URL in the Apple Developer portal. All events arrive at the same endpoint URL.
The events are sent as JSON web tokens signed by Apple. If mail forwarding is disabled, in the payload of the JWT, you will receive an email-disabled event.
When the user stops using their Apple ID with your app, you will get a consent-revoked event.
It is important to invalidate any active user session when you get this event.
And if the user deletes their Apple ID, you will get an account-delete event. Again, be sure to invalidate any active user session and update their accounts according to your process.
Now I'd like to focus on account deletion. Accounts are part of our identities, and we use them to manage some of our most personal and private data. Someone might want to delete their account, and you need to support this in your app.
You should provide a way to initiate account deletion from your app, and it is your responsibility to manage the entire deletion process.
If you have an app server that stores user information, typically, the app notifies the server to delete user accounts. Now, you can include Sign in with Apple as part of your deletion process. This is done using a new REST endpoint that your server can use to delete an account associated with your app. Let me briefly take you through this API.
In order to delete an account, you must have either a valid refresh token or a valid access token for the user. If you don't have either of the tokens, you can generate using the auth/token endpoint. Once you have either of the tokens, you can use the auth/revoke endpoint with the required parameters. When using the refresh token, set the token type to REFRESH_TOKEN.
If you want to delete using the access token, set the token type to ACCESS_TOKEN.
If you get a successful response, the tokens and the user's active sessions will be instantly invalidated.
Once deleted, the user returning to your app and using Sign in with Apple will have an experience similar to when they first created the account with the app.
With that, I will sign out and pass it on to my colleague Patrick to discuss how you can use Sign in with Apple on the web and other platforms.
Patrick: Thank you, Ram! People love how Sign in with Apple works seamlessly across all of Apple's platforms. But it doesn’t stop there. Sign in with Apple also works seamlessly on the web and other platforms. Let’s discuss how you can enhance your Sign in with Apple experience to support the web and other platforms.
We have an existing iOS app that Ram introduced to you earlier, called Juice. We’d like to bring Juice to even more users by expanding to the web. Let’s begin by discussing how to group our similar apps together.
It is recommended that you group related apps together to streamline the user experience. By grouping related apps together, your users only need to provide their consent once to share their information with your app.
For example, your app may be available on iOS and macOS but use different bundle identifiers for each platform.
It’s recommended that you group these apps together.
When using Sign in with Apple, your users will see the App Icon for the app you set as the primary app.
Let’s discover how you can configure a Services ID to support Sign in with Apple on your website.
To begin, log into the Apple Developer Portal and navigate to "Certificates, Identifiers & Profiles." Select the radio button next to Services IDs and then click "Continue." Enter a description for your Service.
Enter a unique identifier for your Service and click Continue.
Click on the checkbox next to Sign in with Apple and then click the Configure button.
On the Web Authentication Configuration screen, select a Primary App ID from the drop-down menu.
Next, input the domains and subdomains your website will use to support Sign in with Apple. Last, enter a redirect URL for Apple to redirect your user back to your app or website after a successful authorization. That’s it! You’ve configured a Services ID to support Sign in with Apple on your website.
You’ll need a button to show users your website supports Sign in with Apple.
Apple provides a highly configurable button API to generate Sign in with Apple button images.
For example, with the current properties, you’ll get a white "Sign in with Apple" button with a border and a default corner radius.
By changing the data-color property, we can choose a different background color for the button.
If we change the data type to "continue", the button text will update to show "Continue with Apple." Alternatively, you can create a logo-only button by setting the data mode property to logo-only.
If you’d prefer to use a REST API to generate your Sign in with Apple button, you can use one of the Apple ID button endpoints to generate a button. There are separate endpoints for center-aligned, left-aligned, and logo buttons.
You can customize the button by using query parameters. In this example request, I customize a white Sign in with Apple button with a border. I receive a response with the customized button as a PNG image. Now that you have personalized your Sign in with Apple button, it's time to authenticate your user.
You’ll need to send an authorization request with the required parameters to Apple. These are the parameters you need in order to successfully log in a user.
Since you have already implemented Sign in with Apple on an Apple platform, these parameters are very familiar.
First, we’ll need to set the “clientID”. This will be the Services ID that you created on the Apple Developer Portal for your app or website.
Next, if your app or website requires email or name, fill in the "scope" parameter. If you are requesting multiple scopes, use a space to separate each scope.
It is important that you only request the data you need.
The “redirectURI” parameter is where you will add the URL you registered previously on the Apple Developer Portal and informs Apple where to direct the user to on your website.
You can also add a “state” and “nonce” to secure your request.
And finally, with the "usePopup" parameter, you can choose to display the login screen in a separate pop-up window or have the existing window redirect to the Apple Sign in website.
If someone is using Safari, they’ll see a native screen like this one providing them a first-class experience to sign into your website.
After the Apple ID server processes the authorization request, you’ll receive a DOM event containing the results of the authorization.
To handle a success response, add an event listener for "AppleIDSignInOnSuccess." To handle a failure response, add an event listener for "AppleIDSignInOnFailure." If the authorization was a success, you’ll receive a response that contains the authorization code, the identity token, and the user information if requested. This is similar to the response you are already used to on Apple platforms. If you’d prefer to use a REST API to integrate directly with Apple ID servers, direct the authorization request to the authorize endpoint with the required parameters. If the authorization is successful, you’ll get a response that contains the authorization code, the identity token, and the user information. This is very similar to the response you're already used to on Apple platforms. That’s it! You’ve successfully adopted Sign in with Apple on your website! To wrap up, I’d like to highlight some important things to keep in mind while implementing Sign in with Apple.
Unless your app requires significant account-based features, let people use your app without a login. For example, you may allow a user to purchase an item using Apple Pay and then optionally offer them to tie their purchase to an account after the purchase is complete.
Offer existing users the ability to upgrade the security of their account by switching away from username and password authentication to Sign in with Apple.
If you just need a unique identifier to identify the user, don't collect name or email.
And if you do collect email through Sign In with Apple, make sure that you respect the user's choice.
You should not prompt for an additional email.
It’s important to implement Sign in with Apple across all of the platforms your app or website is available.
Your users may use multiple platforms, and they will expect to use Sign in with Apple everywhere.
We’re really excited to see what you do with Sign in with Apple in your apps, and we look forward to your feedback. Thank you for watching, and enjoy the rest of WWDC!
Looking for something specific? Enter a topic above and jump straight to the good stuff.
An error occurred when submitting your query. Please check your Internet connection and try again.