Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Discussion Sign in with Apple Unity Plugin v1.4.3 [Unofficial]

Discussion in 'iOS and tvOS' started by lupidan, May 18, 2020.

  1. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
    Sign in with Apple Unity Plugin v1.4.3 [Unofficial]

    RECOMMENDED: GitHub (v1.4.3): https://github.com/lupidan/apple-signin-unity

    Asset store (v1.4.2): https://assetstore.unity.com/packages/tools/integration/sign-in-with-apple-unity-plugin-152088 (Unity rejected 1.4.3 upgrade...‍)

    Overview


    This is a FREE, UNOFFICIAL, MIT licensed, open source plugin, to support Sign In With Apple in iOS, tvOS and macOS. The plugin is developed by the community, and it´s not the same one as the official plugin from Unity available in the Asset Store.

    The main purpose for this plugin is to expose Apple's newest feature, Sign in with Apple, to the Unity game engine. The plugin started development as soon as Apple announced the feature and has been around for a while already. Version v1.2.0 was released recently, adding macOS support, that´s why I decided to also post it here as well.

    On WWDC19, Apple announced Sign in with Apple, and on top of that, they announced that every iOS/tvOS/macOS Application that used any kind of Third party sign-ins (like Sign in with Facebook, or Sign in with Google), will have to support Sign in with Apple in order to get approved for the App Store, making it mandatory.

    The plugin is available on GitHub:
    https://github.com/lupidan/apple-signin-unity

    Features
    • Support for iOS/tvOS/macOS
    • Supports Sign in with Apple, with customizable scopes (Email and Full name).
    • Supports Get Credential status (Authorized, Revoked and Not Found).
    • Supports Quick login (including iTunes Keychain credentials).
    • Supports adding Sign In with Apple capability to Xcode project programatically in a PostBuild script.
    • Supports listening to Credentials Revoked notifications
    • Supports setting custom Nonce and State for authorization requests when Signing In, and attempting a Quick Login.
    • NSError mapping 1:1 so no details are missing.
    • NSPersonNameComponents support (for ALL different styles).
    • Customizable serialization (uses Unity default serialization, but you can add your own implementation)
    Installation options
    • Unity Package Manager, just edit your Packages/manifest.json file.
    • Asset store (link at the begining)
    • OpenUPM
    • Unity package file
     
    Last edited: Oct 31, 2023 at 7:37 AM
  2. Neonlyte

    Neonlyte

    Joined:
    Oct 17, 2013
    Posts:
    505
    Nice work!!
     
    lupidan likes this.
  3. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
    v1.3.0 Released

    Added
    • Adds support to set the State when making a Login or a Quick Login request to sign in with Apple.
    • Improves deserialization for the data.
    Changed
    • Makes the parsed classes internal to force the usage of the interfaces.
    • Minor changes for lower C# compatibility
    • GetAuthorizationErrorCode no longer returns a nullable reference type. If the error can't be obtained, it returns Unknown instead.
     
    James15478 and Neonlyte like this.
  4. James15478

    James15478

    Joined:
    Apr 2, 2013
    Posts:
    91
    @lupidan this looks really cool, thank you for sharing it. Does the keychain feature mean that if you load the same game where the user already authenticated on a different device with the same itunes account that the user will already be considered authenticated (or that userID will be available) on that device as well?
     
  5. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
    Hi @James15478
    Once you login using Sign In With Apple in device A, when you go and install the app in device B, Quick Login should detect your Apple ID was already used for that app, and allow to login again instead of creating a new account. The result of it will be the same user ID.
    https://github.com/lupidan/apple-signin-unity#quick-login
     
    masterton likes this.
  6. James15478

    James15478

    Joined:
    Apr 2, 2013
    Posts:
    91
    Thanks @lupidan . I noticed you recommend quick login at every app open. But I haven't really seen this in other apps, they just open without asking for re-authorization (re-signing in). Do you think those apps just save the credentials locally then?
     
  7. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
  8. James15478

    James15478

    Joined:
    Apr 2, 2013
    Posts:
    91
    Thanks @lupidan . I'm experimenting with it now. Just using the sample scene atm. It all worked as expected, except after a few tries of revoking permissions and returning to the app, at one point I am just continuingly authorized (I open the app and the user ID shows). I check on device for "Apps using Apple ID" and my app is no longer there, since I revoked permissions, but still shows as authorized in the Unity app. If I reinstall, it seems the quick login pops up as opposed to the "full" login (where it asks for name etc). Do you know why that might be?

    Thanks again for the help and cool tool :)
     
  9. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
    v1.3.0 is now available in the Asset Store!

    https://assetstore.unity.com/packages/tools/integration/sign-in-with-apple-unity-plugin-152088

    @James15478

    If the Sign in with Apple credentials for your app are not granted or revoked, QuickLogin will fail with an error, which is expected. That's when you redirect the user to the login screen for a Sign In With Apple scenario

    If the Sign in with apple credentials are still valid, QuickLogin will display a screen with just the option to proceed (since they were given in the past for yout app and they are still valid)

    Basically, if you don't see the option to give the name, as well as the email selection option, it's a QuickLogin scenario, where credentials already given in the past, period.
     
    nilsdr and James15478 like this.
  10. GuiMidiaDub

    GuiMidiaDub

    Joined:
    Jun 21, 2021
    Posts:
    1
    Hi! I'm developing a sign logic for our project using your plugin with Firebase.
    To be able to create and login with Apple on Firebase, their documentation requires that we use "appleIdToken" and "rawNonce".

    I'm assuming "appleIdToken" would be the "appleUserId" used through out your plugin to identify the user, correct?
    How can I request the "rawNonce" mentioned in Firebase documentation?

    For reference: https://firebase.google.com/docs/auth/unity/apple?authuser=2
     
  11. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
  12. KristoferBoman

    KristoferBoman

    Joined:
    Feb 16, 2016
    Posts:
    60
  13. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
    As far as I know, the authorization code is something that's only provided to you when requesting access with Apple actively (first login only) which will trigger the authentication window.

    After the first login/sign in, and successfuly first login/sign in with Gamesparks, your user should be saved in the device and you should just check if the apple user ID is still valid in order to keep that user logged in, or force a logout. (With the CheckCredentialStatus call)

    I made a diagram on how I think it should work, make sure you go through it, and adapt it to the needs of Gamespark:
    https://github.com/lupidan/apple-signin-unity#implement-sign-in-with-apple
     
    Last edited: Oct 5, 2021
  14. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
    v1.4.2 Released (only on Github)

    It's been a while since I updated the thread. So here is the missing changelog since 1.3.0.
    I plan to update the asset store version at some point, Unity's publishing tools don't get along well with the project. In the meantime, you can keep using the unity package manager, or download the unity package manually from the releases page on github.

    [1.4.2] - 2020-07-17
    Changed
    - Handles empty `NSPersonNameComponents` sent by Apple when not requesting a name, to be `nil` natively.
    - Updated `MacOSAppleAuthManager.bundle` with the updated native code

    Removed
    - Removes `FixSerializationForFullPersonName` and any usage of it when deserializing to avoid NRE

    [1.4.1] - 2020-11-28
    Added
    - Updates plugin's main `MacOSAppleAuthManager.bundle` to support Apple Silicon `arm64` architecture

    Changed
    - Updates some elements in the dedicated macOS documentation file that were incorrect

    [1.4.0] - 2020-10-18
    Added
    - Adds static class `AppleAuthMacosPostprocessorHelper`, so now there should always be an AppleAuth.Editor namespace independent of the current platform.
    - Adds static method to `AppleAuthMacosPostprocessorHelper`, `FixManagerBundleIdentifier` is a method to change the plugin's bundle identifier to a custom one based on the current project's application identifier. This should avoid CFBundleIdentifier collision errors when uploading to the MacOS App Store.
    - Adds enum value for `LoginOptions` to not request full name or email, `LoginOptions.None`.

    Changed
    - Updates sample code Postprocessor script to support the new recommended post processing for macOS builds
     
    realragnvaldr likes this.
  15. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
    realragnvaldr likes this.
  16. Alexander21

    Alexander21

    Joined:
    Dec 14, 2015
    Posts:
    301
    Hi All i have a doubt. I have installed in the plugin... but it shows the error. Metal Api is needed and it works only ios 14 version.

    My ipad wont support metal api and my ipad version is only 10.4...

    Is there any way that sign in apple works without metal api.. or it works only with metal api...

    can any one clarify it....
     
  17. realragnvaldr

    realragnvaldr

    Joined:
    Jul 21, 2019
    Posts:
    40
    @lupidan

    Thanks for creating this package! It all seems quite straightforward, but i have one problem: i can't figure out where to find the PayloadDeserializer -- i get this error:

    The type or namespace name 'PayloadDeserializer' could not be found (are you missing a using directive or an assembly reference?)

    ... so it seems like i'm missing a "using directive", but i'm having the same as in your example code. And pointers on how i can solve this would be appreciated. Thanks!
     
  18. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
    tamassengel and realragnvaldr like this.
  19. Joyal14

    Joyal14

    Joined:
    Jun 10, 2020
    Posts:
    1
    IOS build failing with Undefined symbols for architecture arm64

    Undefined symbols for architecture arm64:
    "_UnitySignInWithApple_Login", referenced from:
    _SignInWithApple_LoginInternal_mF47ED0923886387AC79573DD52A2A75D6D8F1FFD in Assembly-CSharp38.o
    _SignInWithApple_UnitySignInWithApple_Login_m5A2EF436C683C71D2D6E034D838FD05FDA6F6D3C in Assembly-CSharp38.o
    (maybe you meant: _SignInWithApple_UnitySignInWithApple_Login_m5A2EF436C683C71D2D6E034D838FD05FDA6F6D3C)
    "_UnitySignInWithApple_GetCredentialState", referenced from:
    _SignInWithApple_GetCredentialStateInternal_mE7725CD83B2C11D10EC76EB24DC795ADBE20DB27 in Assembly-CSharp38.o
    _SignInWithApple_UnitySignInWithApple_GetCredentialState_m2DC81A39E66199A01BC2B1B0CBD3C0EB811137D8 in Assembly-CSharp38.o
    (maybe you meant: _SignInWithApple_UnitySignInWithApple_GetCredentialState_m2DC81A39E66199A01BC2B1B0CBD3C0EB811137D8)
    ld: symbol(s) not found for architecture arm64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
     

    Attached Files:

  20. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
    Those symbols are from Unity's official Sign in With Apple package. This package is for a completely different plugin.
    Please refer your request to Unity support.

     
  21. guneyozsan

    guneyozsan

    Joined:
    Feb 1, 2012
    Posts:
    99
    Unity's plugin is discontinued and not supported any more.
     
  22. Yagrr

    Yagrr

    Joined:
    May 27, 2018
    Posts:
    1
    Hi All. Does it have support for android?
     
  23. guneyozsan

    guneyozsan

    Joined:
    Feb 1, 2012
    Posts:
    99
    As far as I know, there is no Android support. On Android, you should do a regular Oauth request to Apple servers.
     
    lupidan likes this.
  24. wagenheimer

    wagenheimer

    Joined:
    Jun 1, 2018
    Posts:
    318
    Hi! Thanks for the plugin!
    I'm trying to make it work with my game, but It fails on the AttempQuickLogin method.

    [Authorization] ASAuthorizationController credential request failed with error: Error Domain=com.apple.AuthenticationServices.AuthorizationError Code=1001 "(null)"

    I saw some reports of the same problem where it says that error 1001 is because it was canceled. But no pop up is shown and the error happens before the pop up is shown.

    Is there anything I can check?

    I'm testing on a real device, an iPad.
     
  25. Gillissie

    Gillissie

    Joined:
    May 16, 2011
    Posts:
    294
    I'm wondering if @lupidan could chime in on this topic, where the capability isn't being properly added: https://forum.unity.com/threads/pro...postprocess-not-working.1259091/#post-8010227

    [Edit] I was able to get this working by looking at OneSignal's iOS build postprocessing code, which uses or creates the entitlements file at Unity-iPhone/Unity-iPhone.entitlements and adds that path to the project as the CODE_SIGN_ENTITLEMENTS, so the project actually uses it.

    By using the same technique as the OneSignal code, the capability is added as expected, and it's combined with what OneSignal adds as expected. I'll likely use this postprocessing code for everything moving forward.
     
    Last edited: Apr 7, 2022
  26. shrinebot

    shrinebot

    Joined:
    Sep 12, 2014
    Posts:
    16
    Im facing the same issue @Gillissie, I cant build with Unity Cloud build because the AppleSignIn capability isnt added. I've looked at the OneSignal code, but there's a lot to parse. Could you post some code of how you got it to work? Thanks
     
  27. Gillissie

    Gillissie

    Joined:
    May 16, 2011
    Posts:
    294
    Sure. I'm working on cleaning up the code so it's easier for others to implement and expand on. Will post in a bit.
     
  28. Gillissie

    Gillissie

    Joined:
    May 16, 2011
    Posts:
    294
    I've attached a unity package that contains two classes in 4 code files:

    BuildPostProcessorBase is the base class does almost everything you need to do for iOS and Android build post processing. You can modify as necessary if you do some things differently on every game you make.

    The iOS-specific stuff is found in BuildPostProcessorBase_iOS, and Android-specific stuff is found in BuildPostProcessorBase_Android. As of now, there is nothing in the Android code since I didn't need to do any postprocessing for it, but I included the stubbed-in functions for the sake of completeness.

    MyBuildPostProcessor is your game-specific implementation, which includes adding capabilities such as "Sign In With Apple".

    Both classes are in my "gilligames" namespace, but you can change that to anything if you want.
     

    Attached Files:

  29. shrinebot

    shrinebot

    Joined:
    Sep 12, 2014
    Posts:
    16
    Thanks for the package Todd, I installed and used it but was still getting the problem where the Apple Sign in capability still wasnt showing up in the signing & capabilities panel in xcode.

    However I did find the root cause of my issue - I am also using Firebase applinks which had its own postprocess step which was conflicting with the Sign in with Apple Unity Plugin v1.4.2 postprocess, once I changed so both were writing to the same entitlements file the Sign in with Apple appeared in xcode and started working flawlessly

    Thanks again @lupidan and @Gillissie for all your efforts & help.
     
  30. Gillissie

    Gillissie

    Joined:
    May 16, 2011
    Posts:
    294
    I'm very curious what path to entitlements Firebase uses, since I don't use that library. It's definitely annoying that all postprocesses must use the same path, and it seems that whichever one goes first wins. Unity should just standardize on a path to entitlements instead of allowing the path to be specified.
     
  31. doganakdag

    doganakdag

    Joined:
    Oct 25, 2019
    Posts:
    14
  32. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
  33. boggart

    boggart

    Joined:
    Jun 17, 2013
    Posts:
    4
    Hi @lupidan and everyone, I have implemented this plugin on a game where we give the option to player to login with Apple to secure their account. Recently, we have been notified about the new account deletion requirement from Apple, and they say that if we have used the Sign in with Apple feature, we have to revoke user tokens using the Sign in with Apple REST API.

    Do you guys have already done this?, if so, how exactly did you manage to use the Identity Token, Authorization Code and User Id provided by the Sign In with Apple to do the Revoke Token REST API?

    We are having issues trying to follow the Apple Documentation about this, as they say, we have to send a client_id, which it is supposed is the AppID but without TeamID, and according their documentation, this would be then the bundleId; besides we have to send a client_secret, which according again to their documentation, in the Creating the Client Secret section , there are some very specific values to create that client_secret, which it is a Json Web Token (JWT). We haven't been able to create this properly, since they mention it has to be created using algorithm ES256 and we have to sign using the private key downloaded from Apple Developer portal.

    The last parameter that we have to send is the token which we are not really sure what it is supposed this is. Is this the Identity Token we get from the Sign in with Apple?

    We tried using this plugin, but we have to generate the client_secret (JWT) on Editor and hardcoded to use it in the POST call. Why created on Editor and hardcoded instead of generate it on real time? Well, we had difficulties using this plugin due some index out of range caused by Newtownsoft JSON, which the plug in depends on.

    From the test we did hardcoding the client_secret (JWT) created on Editor, which was not using the right algorithm (RS256) and was not sign at all with the private key created on Apple Developers portal, we could do properly the post request, however, even when we got a response 200 OK, nothing happened, no CredentialsRevokedCallback and the app was still listed in the Apps using Apple ID from iPhone's settings. But I'm not really sure that this should had happened if the API call was correctly done.

    Well, we tried then with another plugin that didn't require Newtonsoft Json, but we couldn't figure out how to use the private key we created on Apple Developer portal to sign the JWT and use properly the ES256 algorithm.

    Maybe @lupidan or anyone else can help me to understand and how exactly I should do what Apple is requesting?

    If someone has already implemented the Account Deletion requirements, how exactly should be done from Unity if the Sign in with Apple plugin was used?

    and, once thise Revoke Tokens API is correctly called, this will trigger the
    CredentialsRevokedCallback and remove the game from the list of apps that appear listed on iPhone's Settings->Account->Passwords & Security-> Apps that use Apple ID?

    If someone has done already this, which plugin or library did you use to generate the client_secret (JWT) on Unity and how exactly did you use the private key to sign it?

    Thank you @lupidan and eveyone in advance. Any advise or guidance will be very helpful.
     
  34. BlueHK

    BlueHK

    Joined:
    Feb 4, 2022
    Posts:
    6
    I'm looking for more info on this also. I feel like the issue is I don't know exactly what values match up to the values that need to be passed with the rest API call. And it's odd that I can pass values that don't seem correct, but it always returns success, but it doesn't appear successful as it still shows up in the Apps that use Apple ID on the phone and the website.
     
  35. Vladnee

    Vladnee

    Joined:
    Apr 28, 2017
    Posts:
    26
    Hi. Do you have any update on this?
     
  36. BlueHK

    BlueHK

    Joined:
    Feb 4, 2022
    Posts:
    6
    Vladnee likes this.
  37. BlueHK

    BlueHK

    Joined:
    Feb 4, 2022
    Posts:
    6
    It took a bit, but this does work. The issue is making sure the "axios" package is also included when you push out the cloud script. Hope that helps.
     
  38. RendergonPolygons

    RendergonPolygons

    Joined:
    Oct 9, 2019
    Posts:
    98
    I implemented with azure function apps. Hope it helps, prepared some steps below:

    1. Using Lupidan's asset Apple sign in, get and store identity token, authorization code and UserID

    2. Pass in https://jwt.io/ the identity token to get "aud" claim which is the client_id: https://developer.apple.com/documen.../sign_in_with_apple_rest_api/verifying_a_user . Or if you know it it's just com.organization.app_name

    3. Generate a p8 key https://stackoverflow.com/questions/44631803/ios-swift-how-to-create-p8-file

    4. Generate client_secret: C# code found here: https://stackoverflow.com/questions...sp-net-framework-unsupported-grant-type-error

    Use this data:
    _config.ClientId = com.organization.ios.app_name (the aud claim above)
    _config.PrivateKeyId - .p8 file key id (generated above)
    _config._DevelopmentTeam - code located before client id name ,X.com.organization.ios.app_name that X (go to https://developer.apple.com/ in Membership it's Team ID)
    _config.PrivateKey - private key from .p8 file

    To generate the client secret I used this code:

    Code (CSharp):
    1. private string GenerateAppleJwtToken()
    2. {
    3.     var issueTime = DateTime.Now;
    4.     var zeroTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
    5.     var iat = (int) issueTime.Subtract(zeroTime).TotalSeconds;
    6.     var exp = (int) issueTime.AddMinutes(5).Subtract(zeroTime).TotalSeconds;
    7.     var headers = new Dictionary<string, object>()
    8.     {
    9.         { "alg", "ES256" },
    10.         { "typ", "JWT" },
    11.         { "kid", _config.PrivateKeyId },
    12.     };
    13.     var payload = new Dictionary<string, object>()
    14.     {
    15.         { "sub", _config.ClientId },
    16.         { "aud", "https://appleid.apple.com" },
    17.         { "iss", _config.DevelopmentTeam },
    18.         { "exp", exp },
    19.         { "iat", iat }
    20.     };
    21. var cngKey = CngKey.Import(Convert.FromBase64String(privateKey), CngKeyBlobFormat.Pkcs8PrivateBlob);
    22.             var ecdsa = new ECDsaCng(cngKey);
    23.             byte[] headerBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(headers, Formatting.None));
    24.             byte[] claimsBytes = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(payload, Formatting.None));
    25.             var base64Payload = Base64UrlEncoder.Encode(headerBytes) + "." + Base64UrlEncoder.Encode(claimsBytes);
    26.             var signature = ecdsa.SignData(Encoding.UTF8.GetBytes(base64Payload), HashAlgorithmName.SHA256);
    27.             string result = base64Payload + "." + Base64UrlEncoder.Encode(signature);
    28.             return Task.FromResult<string>(result.ToString());
    29. }
    5. Get access token and refresh token as per https://developer.apple.com/documentation/sign_in_with_apple/generate_and_validate_tokens

    string grant_type = "authorization_code";
    clientID = com.organization.app_name

    Code (CSharp):
    1. public async Task<AppleAccessAndRefreshTokenData> Get_Refresh_Access_IDTokens(string clientSecret, string clientID, string authorizationCode, string grant_type, ILogger log)
    2.         {
    3.             string AppleGenerateTokensAPIAddress = "https://appleid.apple.com/auth/token";
    4.             string url = AppleGenerateTokensAPIAddress;
    5.             var formContent = new FormUrlEncodedContent(new[]
    6.             {
    7.             new KeyValuePair<string, string>("client_id", clientID),
    8.             new KeyValuePair<string, string>("client_secret", clientSecret),
    9.             new KeyValuePair<string, string>("code", authorizationCode),
    10.             new KeyValuePair<string, string>("grant_type", grant_type),
    11.             });
    12.  
    13.             //Create object to hold token json data
    14.             AppleAccessAndRefreshTokenData thisAppleAccessAndRefreshTokenData = new AppleAccessAndRefreshTokenData();
    15.             using (HttpClient client = new HttpClient())
    16.             {
    17.                 using (HttpResponseMessage response = await client.PostAsync(url, formContent))
    18.                 {
    19.                     using (HttpContent content = response.Content)
    20.                     {
    21.                         var stringContent = await content.ReadAsStringAsync();
    22.                         // Asynchronously get the JSON response.
    23.                         string contentString = await response.Content.ReadAsStringAsync();
    24.                         var jsonResult = JObject.Parse(contentString);
    25.                         try
    26.                         {
    27.                             thisAppleAccessAndRefreshTokenData.access_token = jsonResult["access_token"].ToString();
    28.                             thisAppleAccessAndRefreshTokenData.token_type = jsonResult["token_type"].ToString();
    29.                             thisAppleAccessAndRefreshTokenData.expires_in = jsonResult["expires_in"].ToString();
    30.                             thisAppleAccessAndRefreshTokenData.refresh_token = jsonResult["refresh_token"].ToString();
    31.                             thisAppleAccessAndRefreshTokenData.id_token = jsonResult["id_token"].ToString();
    32.                             if (thisAppleAccessAndRefreshTokenData.refresh_token == null)
    33.                             {
    34.                                 log.LogInformation("Get_Refresh_Access_IDTokens Fail. refresh_token empty." + stringContent);
    35.                                 return thisAppleAccessAndRefreshTokenData;
    36.                             }
    37.                             return thisAppleAccessAndRefreshTokenData;
    38.                         }
    39.                         catch (Exception e)
    40.                         {
    41.                             log.LogError($"Fail Get_Refresh_Access_IDTokens: {stringContent}. Exception {e.Message}");
    42.                             return thisAppleAccessAndRefreshTokenData;
    43.                         }
    44.                     }
    45.                 }
    46.             }
    47.         }
    6. When you need to revoke, we used an azure function app that calls Apples REST API to revoke: https://developer.apple.com/documentation/sign_in_with_apple/revoke_tokens . When the call to api is successful the user's credentials are revoked (you can see the device notify revoked credentials on the app if logged on and on debug and running).

    string token_type_hint = "refresh_token";

    Code (CSharp):
    1. public async Task<string> RevokeAppleUserKeyHelper(string clientId, string token_type_hint, string client_secret, string appleRefreshToken)
    2.         {
    3.             string AppleRevokeTokensAPIAddress = "https://appleid.apple.com/auth/revoke";  //https://developer.apple.com/documentation/sign_in_with_apple/revoke_tokens
    4.             string url = AppleRevokeTokensAPIAddress;
    5.             var formContent = new FormUrlEncodedContent(new[]
    6.             {
    7.                 new KeyValuePair<string, string>("client_id", clientId),
    8.                 new KeyValuePair<string, string>("client_secret", client_secret),
    9.                 new KeyValuePair<string, string>("token", appleRefreshToken),
    10.                 new KeyValuePair<string, string>("token_type_hint", token_type_hint),
    11.             });
    12.             using (HttpClient client = new HttpClient())
    13.             {
    14.                 using (HttpResponseMessage response = await client.PostAsync(url, formContent))
    15.                 {
    16.                     using (HttpContent content = response.Content)
    17.                     {
    18.                         var stringContent = await content.ReadAsStringAsync();
    19.                         if (response.StatusCode == HttpStatusCode.OK)
    20.                         {
    21.                             return "Revoke HttpStatusCode=200";
    22.                         }
    23.                         else
    24.                         {
    25.                             try
    26.                             {
    27.                                 return $"Fail revoke";
    28.                             }
    29.                             catch (Exception e)
    30.                             {
    31.                                 return $"Fail revoke. Exception:{e.Message}";
    32.                             }
    33.                         }
    34.                     }
    35.                 }
    36.             }
    37.         }
     
    Last edited: Jul 19, 2022
    Ollie64 likes this.
  39. Zychew

    Zychew

    Joined:
    Feb 23, 2014
    Posts:
    6
    I m not so familiar to Firebase cloud function, may I know how to communicate between unity app (c# script) to the cloud function…
     
  40. cratica

    cratica

    Joined:
    Dec 11, 2016
    Posts:
    55
    Thank you for making this available. Unfortunately, I have been unable to get this to work properly (my error I'm sure). The problem is that is will not retrieve the apple id.

    I have gone through the directions for setting it up and I *think* I have done everything as required. However, when I try to login, its not providing the id, in fact, its skipping the portion of the login script that would grab the id. Have no idea what is going on here. Oddly, it seems to be logging in as the app does appear in settings/passwords & security/apps using apple id on my iphone when testing. If I remove the app (revoke) and re-run the app, then press the apple login button, the app will again appear in this settings area on the phone. However, none of the expected code is executed per below... (it also does not give an error, just oddly skips the code altogether)

    This is the code that is executed when pressing the login button ...


    Code (CSharp):
    1. public void signIn()
    2.     {
    3.         Debug.Log("0801 appleManager signIn");
    4.  
    5.         var loginArgs = new AppleAuthLoginArgs(LoginOptions.None);
    6.  
    7.         this.appleAuthManager.LoginWithAppleId(
    8.             loginArgs,
    9.             credential =>
    10.             {
    11.                 // Obtained credential, cast it to IAppleIDCredential
    12.                 var appleIdCredential = credential as IAppleIDCredential;
    13.                 Debug.Log("0801 appleManager appleIdCredential = " + appleIdCredential);
    14.                 if (appleIdCredential != null)
    15.                 {
    16.                     // Apple User ID
    17.                     // You should save the user ID somewhere in the device
    18.                     var userId = appleIdCredential.User;
    19.                     ZPlayerPrefs.SetString(AppleUserIdKey, userId);
    20.                     // Email (Received ONLY in the first login)
    21.                     var email = appleIdCredential.Email;
    22.                     // Full name (Received ONLY in the first login)
    23.                     var fullName = appleIdCredential.FullName;
    24.                     // Identity token
    25.                     var identityToken = Encoding.UTF8.GetString(
    26.                     appleIdCredential.IdentityToken,
    27.                     0,
    28.                     appleIdCredential.IdentityToken.Length);
    29.                     // Authorization code
    30.                     var authorizationCode = Encoding.UTF8.GetString(
    31.                     appleIdCredential.AuthorizationCode,
    32.                     0,
    33.                     appleIdCredential.AuthorizationCode.Length);
    34.                     // And now you have all the information to create/login a user in your system
    35.  
    36.                     Debug.Log("0801 appleManager APPLE ID = " +     userId);
    37.                     FBlogin.FBuserID = userId;
    38.                     FBlogin.AppleUserID = userId;
    39.                 }
    40.                 else
    41.                     Debug.Log("0801 appleIDCredential is NULL = " + appleIdCredential);
    42.             },
    43.             error =>
    44.             {
    45.                 // Something went wrong
    46.                 var authorizationErrorCode = error.GetAuthorizationErrorCode();
    47.                 Debug.Log("0801 appleManager APPLE ID GET ERROR = " + authorizationErrorCode);
    48.             });
    49.         Debug.Log("AFTER apple login credential attemp AppleUserIdKey = " + AppleUserIdKey);
    50.         Debug.Log("AFTER apple login credential attemp FBlogin.FBuserID = " + FBlogin.FBuserID);
    51.  
    52.     }

    > The 1st debug.log IS executed and prints in Xcode.
    > NONE of the following debug.logs are executed and they do not print in Xcode... therefore my userId is never grabbed.
    > The last 2 Debug.Logs are executed and prints in Xcode.

    So basically, none of the auth code appears to be executing based on it not printing any of the Debug logs yet it is registering the app as a Log in as Apple ID app.

    Can someone help me please? Thank you VERY much!!
     
    Last edited: Aug 3, 2022
  41. cratica

    cratica

    Joined:
    Dec 11, 2016
    Posts:
    55
    Anyone? I am stuck and cannot get this resolved.

    I have made sure the entitlements file has been created.
    Xcode has the iphone target > Sign i with Apple capability added
    Xcode UnityFramework > build phases > link binary with libraries has the authentication services framework added
    I have added sign in with apple on the project account on Apple dev page
     
  42. cratica

    cratica

    Joined:
    Dec 11, 2016
    Posts:
    55
    I tried redirecting code to quick login and at least I have an error this time. This is the error I get...

    2022-08-03 15:13:15.204512-0500 MMAFightClub2[32138:1295171] [Authorization] ASAuthorizationController credential request failed with error: Error Domain=com.apple.AuthenticationServices.AuthorizationError Code=1001 "(null)"
     
  43. Vladnee

    Vladnee

    Joined:
    Apr 28, 2017
    Posts:
    26
    Hi, thanks for your solution, great work!

    So I have couple of questions:

    1. Do we need to get a refresh token immediately after the first user login and store it? Because I am don't found how to update auth code after it expires. If true then for all users who already log in with apple in my app, I can not revoke the account.

    2. Do you update the refresh token once per day? I found this on apple forum, I don't understand refresh token is always valid or not, and what we will do if the user doesn't enter the app for more than 1 day)
    1. Validate the refresh token up to once per day with Apple servers (to manage the lifetime of your user session and for future token revocation requests), and obtain access tokens (for future token revocation, app transfer, or user migration requests).
    Thank you very much!!
     
  44. hippogames

    hippogames

    Joined:
    Feb 5, 2015
    Posts:
    228
  45. smithmw9

    smithmw9

    Joined:
    Feb 9, 2018
    Posts:
    4
    Has anyone got this working well with Unity Gaming Services, specifically properly managing the linking of the AppleID with a new or existing anonymous account? What's the best practice for creating new accounts, make the anonymous first and then link it? This doesn't seem to do what it is saying for me.. "If no Unity Authentication user in your project is associated with the credentials, then SignInWithAppleAsync will create a new user. If a Unity Authentication user in your project is associated with the credentials, then SignInWithAppleAsync will sign into that user's account. This function doesn't take into consideration the cached user, and SignInWithAppleAsync will replace the cached user." After I have Apple Login set up and linked, do I "login with Apple ID" first each time the game loads, or login with the Unity Gaming Services account? The documentation gets me about 90% there, thank you!
     
  46. smithmw9

    smithmw9

    Joined:
    Feb 9, 2018
    Posts:
    4
    I finally got a successful Link from the Apple account to a UGS anonymous account! I was having the same issue as some other users. I was using the appleIdCredential.User instead of the appleIdCredential.IdentityToken. Thanks to minus4games and MichalMarsalek for figuring this out here: https://forum.unity.com/threads/request-failed-401-on-ios.1322685/
    I was able to use the idToken with:
    var identityToken = Encoding.UTF8.GetString(appleIdCredential.IdentityToken, 0, appleIdCredential.IdentityToken.Length);
    And pass that into LinkWithAppleAsync
    await AuthenticationService.Instance.LinkWithAppleAsync(idToken);
    In the UGS Dashboard, I finally see my used with a Linked identities: Sign in with Apple
     
    guneyozsan likes this.
  47. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
  48. lupidan

    lupidan

    Joined:
    Jan 14, 2014
    Posts:
    47
    v1.4.3 Released (only on Github)

    [1.4.3] - 2023-09-30
    Changed
    - Updates `AddSignInWithAppleWithCompatibility` to support new public constructor for `PBXCapabilityType` introduced in Unity 2022.3.10
    - Increases minimum target for the macOS bundle to 10.13

    Added
    - Add `ToString` override to `AppleError`