At Worldwide Developers Conference (WWDC) in June, Apple announced a new product: Sign in with Apple. With the imminent release of iOS 13 on September 19, Apple has updated the App Store Review Guidelines and they now require any new applications that use third-party or social login services to offer Sign in with Apple as an equivalent option. Existing applications will be required to comply by April 2020. You can read more about this change on Apple’s developer site.
We know many Unity developers depend on third-party sign-in services. To make complying with these new guidelines easier, we have created a new asset store package. You can add the package to new or existing projects to leverage the new Sign in with Apple feature easily.
Below you will find the following:
- A step by step guide of how to use the new asset store plugin
- Links to important guidelines
- For more advanced use cases, an overview of how you can perform server-side validation
Player identity is a core part of many mobile games and is increasingly important in the context of player privacy. Whether you maintain an in-house system or rely on third-party login services, we want to help make the player experience more seamless while providing flexibility for game developers. With that in mind, we also want to take this opportunity to share plans for our upcoming User Authentication solution, available later this year.
Getting started
To get started with Sign in with Apple in we have created a new Asset Store package. The purpose of this package is to make available the newly added iOS 13 API’s required to use Sign in with Apple.
You will also need Xcode 11, which will work on either macOS 10.14 (Mojave) or 10.15 (Catalina) and a device that has iOS 13.0 installed. You can find downloads for Xcode and iOS 13 here. We also recommend that you read and review the Sign in With Apple Getting Started Guide. This guide covers Apple’s Human Interface Guidelines and App Store Review Guidelines. Your application will also need to have the Sign in with Apple capability enabled in Apple’s developer portal.
You can download the new package from the Unity Asset Store.
To use the package:
1. Import the package into an existing Unity project.
2. Create a script that has a callback to receive data about the login from Apple. See the sample script “SignInWithApple.cs” for an example of how the API is used.
3. Rebuild your Unity project and open the Xcode project created by Unity.
4. Within Xcode entitlements and framework dependencies need to be configured.
a. In the Project Settings “Sign in with Apple” capability must be added.
b. You must add the AuthenticationServices framework to the project. You will want to mark this framework optional if you plan to target prior versions of iOS.
See the video below to help locate the steps described above.
Note: Xcode projects created with Unity 2019.2 or lower will not have the UnityFramework target. The AuthenticationServices framework should be added to the Unity-iPhone target instead.
5. With your project configured, you can now extract any data made available in the callbacks to be used with the projects existing codebase.
Server-side validation
For games or applications which also require server-side identity validation, you can pass the identityToken to a server for validation.
Apple’s identityToken is a JSON Web Token (JWT) token which the client-side cannot generate. To validate that JWT token is issued by Apple and intended to be used by your app, you must verify:
- Apply the standard JWT validation:
- Validate that token is in a valid format.
- Validate that the token’s signature is valid.
- Validate that the issuer (iss) is: https://appleid.apple.com
- Validate that the token is not expired.
- Make sure the exp claims must be after the current time.
- Check the audience of the JWT token is for your app.
- The token you get back from Sign in with Apple uses your iOS app ID as the audience. Your server-side needs to validate the token to make sure it is intended to your app.
The Apple JWT payload claims are:
Claim | Column Name | Type | Example | Description |
iss | Issuer | string | https://appleid.apple.com | The value is always https://appleid.apple.com |
aud | Audience | string | com.unity.testApp | The audience of the token. |
exp | Expiration Time | number | 1568671600 | The expiration time in epoch (seconds since 1970-01-01 00:00:00Z) of the token. |
iat | Issued At | number | 1568671000 | The time in epoch at which the token is issued. |
sub | Subject | string | 001999.80b18c74c3264cad895d0eae181d8f50.1909 | The user ID of the authenticated user. |
c_hash | Code Hash | string | agyAh42GdE-O72Y4HUHypg | The hash of the authorization code. It’s only used when you need to validate the authorization code. |
string | xxx@privaterelay.appleid.com | The email address of the user. | ||
email_verified | Email Verified | string | true | Whether the email is verified. Note that it’s a string JSON type. |
auth_time | Auth Time | number | 1568671000 | The time in epoch at which the authentication happened. |
There are JWT libraries available in most programming languages. These libraries can help you parse and validate the token.
If you use javascript, the following is an example of how to validate the token. It reads the token from stdin, and try to validate the token. Replace “your.app.id” with your real app ID from Apple.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
const jwt = require('jsonwebtoken') const jwksClient = require('jwks-rsa'); fs = require('fs'); var token = fs.readFileSync('/dev/stdin').toString().trim(); console.log(token); var client = jwksClient({ jwksUri: 'https://appleid.apple.com/auth/keys' }); function getApplePublicKey(header, callback) { client.getSigningKey(header.kid, function (err, key) { var signingKey = key.publicKey || key.rsaPublicKey; callback(null, signingKey); }); } jwt.verify(token, getApplePublicKey, null, function (err, decoded) { if (err) { console.error(err); process.exit(1); } if (decoded.iss !== "https://appleid.apple.com") { console.error("unexpected issuer (iss claim): ", decoded.iss); process.exit(1); } if (decoded.aud !== "your.app.id") { console.error("unexpected audience (aud claim): ", decoded.aud); process.exit(1); } console.log("Validated Apple token: ", decoded); }); |
Looking forward
The upcoming User Authentication solution will consist of Unity hosted authentication and authorization APIs, a Unity package that implements login and key auth workflows independent of backend implementation, and a drop-in Prefab to address UX specific requirements such as those required by Sign in with Apple.
Our first release of User Authentication will provide support for authentication via email id/password and Sign in with Apple (including support on Android) as a federated identity provider. Additionally, this new solution will be extensible, enabling you to integrate any additional custom or third-party federated identity providers of your choice. User Authentication will allow you to configure identity providers across multiple platforms within the Unity Editor using a common, simplified API. This will reduce development time from weeks to days while also enabling you to provide your customers with more choices for authentication easily. As consumers become more privacy-conscious there will be a growing need for authentication alternatives.
The alpha release for User Authentication will be available later this year. Please sign up for early access.
Crocblanc
outubro 9, 2019 às 8:53 pmHello, is it possible to get an identity token from “apple sign in” without getting the apple popup each time ?
Roy Luo
outubro 6, 2019 às 10:05 amit crashed when login success.
Sylec
outubro 9, 2019 às 2:48 pmFigured out why it’s crashing, I’m getting the same issue.
Inside of Bulk_Assembly-CSharp_0.cpp, line 21015 there is a method called extern “C” void UserInfo_tC46F8D8850FF36FFAD9060EF32007B2A7F920041_marshal_pinvoke_back. Inside of this method an error is being set on line 21021 unmarshaled.set_error_4(il2cpp_codegen_marshal_string_result(marshaled.___error_4));
The crash is occurring here because the error is NULL when returned from the server because of a successful login, thus when the parameter is set and returned as null, it triggers a crash.
Here’s what I did as a temporary workaround:
Inside of UnitySignInWithApple.m, go to line 92, inside of the UserInfo struct, set data.error hardcoded to “NULL” (string). This no longer crashed after I was successfully signed in. I don’t know what other adverse effects this would have (if any) as I haven’t fully read through the code to see where else this method was invoked, but knowing this delegate method is presented on completion of a login, and there is already a check that verifies success, it should be fine.
Hope this helps, I’ll submit a bug report to Unity about this.
Raged Programmer
outubro 12, 2019 às 3:34 amHow can Unity release an official plugin with so many problems?! The two login functions are calling each other infinitely. The native callback functions don’t manage the memory correctly and cause crashes. The coding style is also terrible. Does Unity development team even do code review?
Scott Flynn
outubro 15, 2019 às 5:49 pmSorry you are having trouble! We have posted an updated asset store plugin which fixes a number of issues. Please try it out and let us know if you still have any problems.
Aman kumar
setembro 20, 2019 às 10:58 amGreat Piece of content, Thanks for sharing with us.
– https://themawto.com
Marcin
setembro 20, 2019 às 9:19 am> Rebuild your Unity project and open the Xcode project created by Unity…
Does that mean that building with Unity Cloud Build wont work?
Sandeep Vaviya
setembro 20, 2019 às 8:01 amGood old Apple. Keeps forcing everyone to stay in their ecosystem. They never change.
Yuriy
setembro 19, 2019 às 7:35 pmWhy this package is not in Package manager but in Asset store?
Scott Flynn
setembro 19, 2019 às 8:06 pmWe wanted to make this available to all versions of Unity not just newer versions with Package Manager. User Authentication coming later this year will be shipped as a package.
James McGhee
outubro 2, 2019 às 5:46 pmWas just digging for a solution like this … we where looking for a WebAuthenticationBroker / Web Authentication solution for standalone Unity. Is there somewhere we can learn more about the state of this, check out its roadmap, etc.?