Apple - hippogamesunity/SimpleSignIn GitHub Wiki
Welcome to Simple Apple Sign-In wiki!
The asset provides [Sign in with Apple] using OAuth 2.0 for Android, iOS, Windows, macOS, Universal Windows Platform (UWP) and WebGL apps made with Unity.
Benefits
- Cross-platform user auth for cross-platform games and apps
- No plugins, no 3rd party auth libs, no dependencies
- No impact to build size
- Get access tokens for integration with other Apple services
- More security for client-server apps (get an access token on a client, get all user data on a server to avoid tampering)
- Apple Id Token (JWT) validation
- SFSafariViewController is used on iOS (required by App Store review)
- Deep linking for Windows (UNITY_STANDALONE_WIN)
Alternatives
- Native iOS SDK
Sign in with Apple Plugin for Unitywhich is based on native SDK and works only on iOS, tvOS and macOS
Terminology
- Please visit Terminology section
Understanding how it works
- Your app navigates users to Apple
Authorization Endpointin a web browser - Users perform sign-in using their login and password
- Apple
Authorization Endpointredirects users toReturn URL(which isAuthorization Middleware) and provides an authorizationcode(which can be later exchanged foraccess_token),id_token(if requested) and user info likefirst_name,last_nameandemail(if requested and only once at first sign-in) Authorization Middlewaretransmitscodeand user info to your app (using deep linking when possible)- The app exchanges
codeforaccess token(and may receiveid_tokenas well) by creating JWT signed with p8 private key (ES256)
Preconditions
- For Android, iOS, macOS, Windows and UWP (platforms that support deep linking): COME UP WITH your
Custom URI scheme(orProtocol). It MUST contain the period symbol.and small alphanumeric symbols only (no spaces, no undercores). In my example it issimple.oauth, but it can bejelly.bean(note thatCustom URI schemeis not the same as your actual package name or bundle id). - For Android, iOS, UWP: enable deep linking as described in Unity documentation or as described below.
- For Android: create
AndroidManifest.xmlinsideAssets/Plugins/Android/, SET yourCustom URI schemeinside, like<data android:scheme="simple.oauth" />. You can useAndroidManifestExample.xmlfrom the asset as an example, just copy, rename and edit. AGAIN, DON'T FORGET TO REPLACEsimple.oauthwith yourCustom URI scheme! - For iOS and macOS: navigate to
Player Settings > Other > Configurationand add yourCustom URI schemetoSupported URL schemes. In Xcode, make sure that the URL scheme is added (Register your URL scheme). - For Universal Windows Platform: navigate to
Player Settings > Publishing Settingsand setProtocol(it MUST contain a period symbol, for examplesimple.oauth), then enableInternetClientinCapabilities. - For Windows: navigate to
Player Settingsand enableResolution and Presentation > Force Single Instanceand setOther Settings > Api Compatibility Level = .NET Framework
Setup steps
- Visit App Store Connect, create a new account if needed
- Create a new app if needed, or use an existing app (currently sign-in works for unpublished apps, in fact you can even skip creating a new app)
- Visit Apple Developer > Certificates, Identifiers & Profiles
- Select your app in
App IDsand enable and configureSign In with AppleinCapabilities(you should create a newApp IDif you didn't create a new app in Step 2) - Return to
Certificates, Identifiers & Profilesand pressRegister a new identifier - Select
Services IDsand pressContinue - Fill
DescriptionandIdentifierand pressRegister(Identifiermay be the same asCustom URI scheme, but not necessarily) - Return to
Certificates, Identifiers & Profilesand select your service identifier - Enable
Sign In with Appleand pressConfigure - Select
Primary App ID, addhippogames.devtoDomains and Subdomains, addhttps://hippogames.dev/api/oauth/apple_redirecttoReturn URLs(later you can replace it with your website, please refer to Authorization-Middleware) - Save changes
- Return to
Certificates, Identifiers & Profilesand select theKeyssection - Perform
Register a New KeywithSign in with Appleenabled and configured - Download p8 private key
- Copy
Key ID(10 digits) - Copy
Team IDat the top right (10 digits) - Return to Unity and configure
Resources/AppleAuthSettings.asset- set
Client IDwhich isIdentifierfrom Step 7 (note thatClient IDisServices ID, notApp ID) - set
Team IDfrom Step 16 - set
Private Key Idfrom Step 15 - set
Private Key(copy entire content of the p8 file downloaded in Step 14) - set
Custom URI Schemefrom Preconditions
- set
- Make sure that system time on your device is synchronized and has a valid Time Zone (it's important for
client_secretgeneration)
Checklist
-
Custom URI schemeis picked, and it has a different value thansimple.oauth -
Custom URI schemeis set in 2 places: [1] Resources/AppleAuthSettings.asset, [2] your application manifest (AndroidManifest.xml for Android,Supported URL schemesfor iOS,Protocolfor UWP) -
Resources/AppleAuthSettings.assetcontains valid settings different from that come with the asset
Usage
- Check our
Examplescene and C# code ofExample.cs - Create an instance of
AppleAuth - Call
AppleAuth.SignInorAppleAuth.GetTokenResponse - Create
OnSignInorOnGetTokenResponsecallbacks - Build and test
- Write a review on the Asset Store :)
API reference for AppleAuth class
| Method | Arguments | Description |
|---|---|---|
| AppleAuth (constructor) | AppleAuthSettings settings = null | A constructor that accepts an instance of AppleAuthSettings. If Null is passed, it will load default settings from Resources (AppleAuthSettings scriptable object). |
| SignIn | Action<bool, string, UserInfo> callback, bool caching = true, string nonce = null | Performs sign-in and returns an instance of UserInfo with callback. If caching is True, it will return the previously saved UserInfo. If nonce is provided, it will be hashed (SHA256), URL encoded and passed to Apple in an authorization request (otherwise, a random value will be generated). |
| SignOut | bool revokeAccessToken = false | Performs sign-out. Can revoke Access Token if requested. |
| GetTokenResponse | Action<bool, string, TokenResponse> callback | Returns an instance of TokenResponse which contains AccessToken and other related information (expiration, type and other). It may also contain IdToken (JWT), if requested with openid scope, which contains information about the user. |
| TryResume | Refer to code | This can be called on app startup to continue OAuth. In some scenarios, the app may be terminated while the user performs sign-in on Apple ID website. |
| SignInAsync | Async version of SignIn. | |
| GetTokenResponseAsync | Async version of GetTokenResponse. |
Best practices
- Call
AppleAuth.SignInwithcaching: trueto return cachedUserInfo. - Call
AppleAuth.GetTokenResponseinstead ofAppleAuth.SignInif you need an access token or an ID token only (and don't needUserInfo). - You can use
AppleAuth.SavedAuthto getTokenResponseorUserInfo(don't forget to check all values for null). - Disable debug logs for production by setting
AppleAuth.DebugLog = false. - Check Manual cancellation if needed.
Unity Authentication Service
Security concerns
- Please refer to User data disclosure
- It's recommended to deploy your own trusted
Authorization Middlewareto handle sensitive data. Please refer to Authorization Middleware article. - Another concern is storing p8
Private Keyinside the app, and the solution is moving all code responsible for exchanging access tokens (AppleAuth.PerformCodeExchange) to your backend. - You can implement
id_tokensignature validation.
Known issues
- Please visit Common issues section
- Apple only returns the user object the first time the user authorizes the app. Validate and persist this information from your app to your server. Subsequent authorization requests do not contain the user object, however, the user's email is provided in the identity token for all requests (more info). For debugging, you can get user name again by visiting
Apple ID > Sign-In and Security > Sign in with Apple > Select app > Stop using Sign in with Apple. Alternatively, Apple will return user name again after revoking access tokens. - The App Store review team may reject your app if you don't use native SDK for
Sign in with Apple. BouncyCastle.Crypto.dllis used to create JWT signed with ES256 (client_secretrequired for making API calls). This results in build size overhead. No .NET alternatives found yet.- Validating
id_tokensignature is not implemented yet.BouncyCastle.Crypto.dllcan be used for this. - When exchanging an auth code, it's important to have valid system time on client's device, otherwise you will get
invalid_clienterror.
Supported browsers
- Please visit Supported browsers section