Browse Source

登录和支付

master
azazaz123456 1 week ago
parent
commit
381c65efb1
137 changed files with 7926 additions and 2 deletions
  1. +8
    -0
      Assets/AppleAuth.meta
  2. +163
    -0
      Assets/AppleAuth/CHANGELOG.md
  3. +7
    -0
      Assets/AppleAuth/CHANGELOG.md.meta
  4. +8
    -0
      Assets/AppleAuth/Editor.meta
  5. +16
    -0
      Assets/AppleAuth/Editor/AppleAuth.Editor.asmdef
  6. +7
    -0
      Assets/AppleAuth/Editor/AppleAuth.Editor.asmdef.meta
  7. +105
    -0
      Assets/AppleAuth/Editor/AppleAuthMacosPostprocessorHelper.cs
  8. +11
    -0
      Assets/AppleAuth/Editor/AppleAuthMacosPostprocessorHelper.cs.meta
  9. +90
    -0
      Assets/AppleAuth/Editor/ProjectCapabilityManagerExtension.cs
  10. +11
    -0
      Assets/AppleAuth/Editor/ProjectCapabilityManagerExtension.cs.meta
  11. +9
    -0
      Assets/AppleAuth/LICENSE.md
  12. +7
    -0
      Assets/AppleAuth/LICENSE.md.meta
  13. +532
    -0
      Assets/AppleAuth/README.md
  14. +7
    -0
      Assets/AppleAuth/README.md.meta
  15. +8
    -0
      Assets/AppleAuth/Runtime.meta
  16. +3
    -0
      Assets/AppleAuth/Runtime/AppleAuth.asmdef
  17. +7
    -0
      Assets/AppleAuth/Runtime/AppleAuth.asmdef.meta
  18. +21
    -0
      Assets/AppleAuth/Runtime/AppleAuthLoginArgs.cs
  19. +11
    -0
      Assets/AppleAuth/Runtime/AppleAuthLoginArgs.cs.meta
  20. +338
    -0
      Assets/AppleAuth/Runtime/AppleAuthManager.cs
  21. +11
    -0
      Assets/AppleAuth/Runtime/AppleAuthManager.cs.meta
  22. +14
    -0
      Assets/AppleAuth/Runtime/AppleAuthQuickLoginArgs.cs
  23. +11
    -0
      Assets/AppleAuth/Runtime/AppleAuthQuickLoginArgs.cs.meta
  24. +8
    -0
      Assets/AppleAuth/Runtime/Enums.meta
  25. +33
    -0
      Assets/AppleAuth/Runtime/Enums/AuthorizationErrorCode.cs
  26. +11
    -0
      Assets/AppleAuth/Runtime/Enums/AuthorizationErrorCode.cs.meta
  27. +28
    -0
      Assets/AppleAuth/Runtime/Enums/CredentialState.cs
  28. +11
    -0
      Assets/AppleAuth/Runtime/Enums/CredentialState.cs.meta
  29. +23
    -0
      Assets/AppleAuth/Runtime/Enums/LoginOptions.cs
  30. +11
    -0
      Assets/AppleAuth/Runtime/Enums/LoginOptions.cs.meta
  31. +33
    -0
      Assets/AppleAuth/Runtime/Enums/PersonNameFormatterStyle.cs
  32. +11
    -0
      Assets/AppleAuth/Runtime/Enums/PersonNameFormatterStyle.cs.meta
  33. +23
    -0
      Assets/AppleAuth/Runtime/Enums/RealUserStatus.cs
  34. +11
    -0
      Assets/AppleAuth/Runtime/Enums/RealUserStatus.cs.meta
  35. +8
    -0
      Assets/AppleAuth/Runtime/Extensions.meta
  36. +20
    -0
      Assets/AppleAuth/Runtime/Extensions/AppleErrorExtensions.cs
  37. +11
    -0
      Assets/AppleAuth/Runtime/Extensions/AppleErrorExtensions.cs.meta
  38. +91
    -0
      Assets/AppleAuth/Runtime/Extensions/PersonNameExtensions.cs
  39. +11
    -0
      Assets/AppleAuth/Runtime/Extensions/PersonNameExtensions.cs.meta
  40. +25
    -0
      Assets/AppleAuth/Runtime/IAppleAuthManager.cs
  41. +11
    -0
      Assets/AppleAuth/Runtime/IAppleAuthManager.cs.meta
  42. +8
    -0
      Assets/AppleAuth/Runtime/Interfaces.meta
  43. +35
    -0
      Assets/AppleAuth/Runtime/Interfaces/IAppleError.cs
  44. +11
    -0
      Assets/AppleAuth/Runtime/Interfaces/IAppleError.cs.meta
  45. +42
    -0
      Assets/AppleAuth/Runtime/Interfaces/IAppleIDCredential.cs
  46. +11
    -0
      Assets/AppleAuth/Runtime/Interfaces/IAppleIDCredential.cs.meta
  47. +10
    -0
      Assets/AppleAuth/Runtime/Interfaces/ICredential.cs
  48. +11
    -0
      Assets/AppleAuth/Runtime/Interfaces/ICredential.cs.meta
  49. +11
    -0
      Assets/AppleAuth/Runtime/Interfaces/ICredentialStateResponse.cs
  50. +11
    -0
      Assets/AppleAuth/Runtime/Interfaces/ICredentialStateResponse.cs.meta
  51. +10
    -0
      Assets/AppleAuth/Runtime/Interfaces/ILoginWithAppleIdResponse.cs
  52. +11
    -0
      Assets/AppleAuth/Runtime/Interfaces/ILoginWithAppleIdResponse.cs.meta
  53. +7
    -0
      Assets/AppleAuth/Runtime/Interfaces/IPasswordCredential.cs
  54. +11
    -0
      Assets/AppleAuth/Runtime/Interfaces/IPasswordCredential.cs.meta
  55. +8
    -0
      Assets/AppleAuth/Runtime/Interfaces/IPayloadDeserializer.cs
  56. +11
    -0
      Assets/AppleAuth/Runtime/Interfaces/IPayloadDeserializer.cs.meta
  57. +43
    -0
      Assets/AppleAuth/Runtime/Interfaces/IPersonName.cs
  58. +11
    -0
      Assets/AppleAuth/Runtime/Interfaces/IPersonName.cs.meta
  59. +8
    -0
      Assets/AppleAuth/Runtime/Native.meta
  60. +41
    -0
      Assets/AppleAuth/Runtime/Native/AppleError.cs
  61. +11
    -0
      Assets/AppleAuth/Runtime/Native/AppleError.cs.meta
  62. +51
    -0
      Assets/AppleAuth/Runtime/Native/AppleIDCredential.cs
  63. +11
    -0
      Assets/AppleAuth/Runtime/Native/AppleIDCredential.cs.meta
  64. +29
    -0
      Assets/AppleAuth/Runtime/Native/CredentialStateResponse.cs
  65. +11
    -0
      Assets/AppleAuth/Runtime/Native/CredentialStateResponse.cs.meta
  66. +21
    -0
      Assets/AppleAuth/Runtime/Native/FullPersonName.cs
  67. +11
    -0
      Assets/AppleAuth/Runtime/Native/FullPersonName.cs.meta
  68. +32
    -0
      Assets/AppleAuth/Runtime/Native/LoginWithAppleIdResponse.cs
  69. +11
    -0
      Assets/AppleAuth/Runtime/Native/LoginWithAppleIdResponse.cs.meta
  70. +24
    -0
      Assets/AppleAuth/Runtime/Native/PasswordCredential.cs
  71. +11
    -0
      Assets/AppleAuth/Runtime/Native/PasswordCredential.cs.meta
  72. +18
    -0
      Assets/AppleAuth/Runtime/Native/PayloadDeserializer.cs
  73. +11
    -0
      Assets/AppleAuth/Runtime/Native/PayloadDeserializer.cs.meta
  74. +37
    -0
      Assets/AppleAuth/Runtime/Native/PersonName.cs
  75. +11
    -0
      Assets/AppleAuth/Runtime/Native/PersonName.cs.meta
  76. +47
    -0
      Assets/AppleAuth/Runtime/Native/SerializationTools.cs
  77. +11
    -0
      Assets/AppleAuth/Runtime/Native/SerializationTools.cs.meta
  78. +8
    -0
      Assets/AppleAuth/Runtime/Native/iOS.meta
  79. +55
    -0
      Assets/AppleAuth/Runtime/Native/iOS/AppleAuthManager.h
  80. +114
    -0
      Assets/AppleAuth/Runtime/Native/iOS/AppleAuthManager.h.meta
  81. +393
    -0
      Assets/AppleAuth/Runtime/Native/iOS/AppleAuthManager.m
  82. +105
    -0
      Assets/AppleAuth/Runtime/Native/iOS/AppleAuthManager.m.meta
  83. +62
    -0
      Assets/AppleAuth/Runtime/Native/iOS/AppleAuthSerializer.h
  84. +114
    -0
      Assets/AppleAuth/Runtime/Native/iOS/AppleAuthSerializer.h.meta
  85. +151
    -0
      Assets/AppleAuth/Runtime/Native/iOS/AppleAuthSerializer.m
  86. +105
    -0
      Assets/AppleAuth/Runtime/Native/iOS/AppleAuthSerializer.m.meta
  87. +78
    -0
      Assets/AppleAuth/Runtime/Native/iOS/PersonNameComponentsFormatting.m
  88. +105
    -0
      Assets/AppleAuth/Runtime/Native/iOS/PersonNameComponentsFormatting.m.meta
  89. +8
    -0
      Assets/AppleAuth/Runtime/Native/macOS.meta
  90. +101
    -0
      Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle.meta
  91. +8
    -0
      Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents.meta
  92. BIN
      Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/CodeResources
  93. +2
    -0
      Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/CodeResources.meta
  94. +48
    -0
      Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/Info.plist
  95. +2
    -0
      Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/Info.plist.meta
  96. +8
    -0
      Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/MacOS.meta
  97. BIN
      Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/MacOS/MacOSAppleAuthManager
  98. +2
    -0
      Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/MacOS/MacOSAppleAuthManager.meta
  99. +8
    -0
      Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/_CodeSignature.meta
  100. +115
    -0
      Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/_CodeSignature/CodeResources

+ 8
- 0
Assets/AppleAuth.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 91b206d67c05b48dbaaf58ddab34a634
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 163
- 0
Assets/AppleAuth/CHANGELOG.md View File

@@ -0,0 +1,163 @@
# Changelog
## [Unreleased]
### Added
### Changed
### Removed

## [1.5.0] - 2025-06-08
### Breaking ⚠️⚠️⚠️
- **GitHub import URL updated.** The package must now be imported using a `?path=Source` URL suffix, and tags no longer include a `v` prefix. This is a breaking change for users importing directly from GitHub.

#### Previous GitHub import (before 1.5.0):
```jsonc
"dependencies": {
"com.lupidan.apple-signin-unity": "https://github.com/lupidan/apple-signin-unity.git#v1.4.4"
}
```

#### Updated GitHub import (starting from 1.5.0):
```jsonc
"dependencies": {
"com.lupidan.apple-signin-unity": "https://github.com/lupidan/apple-signin-unity.git?path=Source#1.5.0"
}
```

### Changed
- Fixed issue with native files not being included in visionOS builds.
- Fixed issue with header files not being included in tvOS builds.
- Reworked package structure and folders to more closely follow Unity's package layout guidelines.
- Updated macOS helper method in `AppleAuthMacosPostprocessorHelper.FixManagerBundleIdentifier` to better locate the `.app` or `.xcodeproj` bundle.

### Removed
- Removed unnecessary `.meta` files inside the `MacOSAppleAuthManager.bundle` to avoid unintended asset import or warnings in Unity.

## [1.4.4] - 2024-11-03
### Changed
- Updates `AddSignInWithAppleWithCompatibility` to support new public constructor for `PBXCapabilityType` introduced in Unity 6000.0.23f1
- Updates `AddSignInWithAppleWithCompatibility` to automatically handle the target to add the compatibility and add the framework. It´s no longer required to provide manually the Unity Framework target.
- Added basic support for visionOS
- Increased minimum Unity Version to 2020.3.48f1

## [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`

## [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

## [1.3.0] - 2020-07-18
### 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.

## [1.2.0] - 2020-05-16
### Added
- Updates native code to support macOS, including NSPersonNameComponents support.
- Adds Xcode project `MacOSAppleAuthManager/MacOSAppleAuthManager.xcodeproj` to generate `MacOSAppleAuthManager.bundle` reusing existing iOS objective-c files. Bundle identifier is `com.lupidan.MacOSAppleAuthManager`. Minimum macOS version supported is 10.9.
- Makes it so compiling the Xcode project automatically updates the `MacOSAppleAuthManager.bundle` inside `AppleAuth/Native/macOS`
- Adds *unsigned precompiled* `MacOSAppleAuthManager.bundle`.
- Adds `LandscapeSampleScene.unity` scene for a Landscape version to use on macOS builds.
- Adds `macOS_NOTES.md` readme dedicated to macOS codesigning.
- Adds details to install the plugin with ![OpenUPM](https://openupm.com/) in `README.md`

### Changed
- Fixes PostProcessing for Unity 2019.3
- Renamed plugin´s extension method for `ProjectCapabilityManager` to avoid conflicts with the method added in Unity 2019.3. New method name is `AddSignInWithAppleWithCompatibility`.
- Namespace `AppleAuth.IOS.NativeMessages` becomes `AppleAuth.NativeMessages`
- Modified slightly implementation for Person name formatting
- Modified native implementation of AppleAuthManager to support macOS

## [1.1.0] - 2020-02-20
### Added
- Adds a CHANGELOG.md file
- Adds support for tvOS (Experimental)
- Adds new v2 diagram files (`.drawio` and `.png`)
- Adds `AppleAuthQuickLoginArgs` struct containing arguments for Quick Login. (With optional `Nonce`)
- Adds `AppleAuthLoginArgs` structure containing arguments for Normal Login like `LoginOptions`. (With optional `Nonce`)
- Adds support in native code to receive and set a `Nonce` for the Authorization Requests in both Quick Login and Sign in With Apple
- Adds `Update` method to `IAppleAuthManager` to update pending callbacks
- Better API version handling in native objective-c code

### Changed
- Namespace `AppleAuth.IOS` becomes `AppleAuth`
- Namespace `AppleAuth.IOS.Enums` becomes `AppleAuth.Enums`
- Namespace `AppleAuth.IOS.Extensions` becomes `AppleAuth.Extensions`
- Namespace `AppleAuth.IOS.Interfaces` becomes `AppleAuth.Interfaces`
- Namespace `AppleAuth.IOS.Interfaces` becomes `AppleAuth.Interfaces`

- `QuickLogin` now requires a `AppleAuthQuickLoginArgs` to perform the call. Other `QuickLogin` method marked as obsolete.
- `LoginWithAppleId` now requires a `AppleAuthLoginArgs` to perform the call. Other `LoginWithAppleId` method marked as obsolete.
- `AppleAuthManager` no longer requires a Scheduler, the scheduling is built in the manager instance with the method `Update`
- When receiving a completely empty `FullPersonName`, the instance is cleared after deserialization.
- Fixes bug when setting credentials revoked callback between multiple instances of `AppleAuthManager`

- Updates main package file to include both `CHANGELOG.md` and `CHANGELOG.md.meta files`
- Updates the sample project to better resemble the expected Apple flow
- Updates README.md with up to date documentation

### Removed
- Removes Schedulers to simplify the callback handling. `Update` call was moved to `IAppleAuthManager`.

## [1.0.0] - 2020-01-23
- No plugin code changes. Just making the v1.0.0 release. No more "preview package"
- Adding FAQ to the README

## [0.4.0] - 2019-09-24
- Support to stop listening to credential revoked notifications by setting the callback to null
- Implemented a nicer example of the plugin, and rearranged the code

## [0.3.0] - 2019-09-20
- Rearranged files to support for Unity Package Manager
- Made code more compatible with earlier C# versions
- Updated logic for the whole flow
- More documentation in the Readme

## [0.2] - 2019-08-04
- Some more documentation was added
- Added support to listen to Revoked Credentials notifications
- Solved possible crashes that could happen when trying to execute a callback in the Native Message Handler, if the callback was to throw an exception, the application would crash.

[Unreleased]: https://github.com/lupidan/apple-signin-unity/compare/1.5.0...HEAD
[1.5.0]: https://github.com/lupidan/apple-signin-unity/compare/v1.4.5...1.5.0
[1.4.4]: https://github.com/lupidan/apple-signin-unity/compare/v1.4.3...v1.4.4
[1.4.3]: https://github.com/lupidan/apple-signin-unity/compare/v1.4.2...v1.4.3
[1.4.2]: https://github.com/lupidan/apple-signin-unity/compare/v1.4.1...v1.4.2
[1.4.1]: https://github.com/lupidan/apple-signin-unity/compare/v1.4.0...v1.4.1
[1.4.0]: https://github.com/lupidan/apple-signin-unity/compare/v1.3.0...v1.4.0
[1.3.0]: https://github.com/lupidan/apple-signin-unity/compare/v1.2.0...v1.3.0
[1.2.0]: https://github.com/lupidan/apple-signin-unity/compare/v1.1.0...v1.2.0
[1.1.0]: https://github.com/lupidan/apple-signin-unity/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/lupidan/apple-signin-unity/compare/v0.4.0...v1.0.0
[0.4.0]: https://github.com/lupidan/apple-signin-unity/compare/0.3.0...v0.4.0
[0.3.0]: https://github.com/lupidan/apple-signin-unity/compare/0.2...0.3.0
[0.2]: https://github.com/lupidan/apple-signin-unity/releases/tag/0.2

+ 7
- 0
Assets/AppleAuth/CHANGELOG.md.meta View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 47ff82dfcc8d54955808810c30492220
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 8
- 0
Assets/AppleAuth/Editor.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 2683684c06ae246f782efec99ab8b10a
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 16
- 0
Assets/AppleAuth/Editor/AppleAuth.Editor.asmdef View File

@@ -0,0 +1,16 @@
{
"name": "AppleAuth.Editor",
"references": [
"AppleAuth"
],
"optionalUnityReferences": [],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": []
}

+ 7
- 0
Assets/AppleAuth/Editor/AppleAuth.Editor.asmdef.meta View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 7c9906f2a983d41fca79999faa6934e6
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 105
- 0
Assets/AppleAuth/Editor/AppleAuthMacosPostprocessorHelper.cs View File

@@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEngine;

namespace AppleAuth.Editor
{
public static class AppleAuthMacosPostprocessorHelper
{
/// <summary>
/// Use this script to change the bundle identifier of the plugin's library bundle to replace it with a personalized one for your product.
/// This should avoid CFBundleIdentifier Collision errors when uploading the app to the macOS App Store
/// </summary>
/// <remarks>Basically this should replace the plugin's bundle identifier from "com.lupidan.MacOSAppleAuthManager" to "{your.project.application.identifier}.MacOSAppleAuthManager"</remarks>
/// <param name="target">The current build target, so it's only executed when building for MacOS</param>
/// <param name="path">The path of the built .app file</param>
public static void FixManagerBundleIdentifier(BuildTarget target, string path)
{
if (target != BuildTarget.StandaloneOSX)
{
throw new Exception(GetMessage("FixManagerBundleIdentifier should only be called when building for macOS"));
}

try
{
var macosAppleAuthManagerInfoPlistPath = GetInfoPlistPath(path);
var macosAppleAuthManagerInfoPlist = File.ReadAllText(macosAppleAuthManagerInfoPlistPath);
var regex = new Regex(@"\<key\>CFBundleIdentifier\<\/key\>\s*\<string\>(com\.lupidan)\.MacOSAppleAuthManager\<\/string\>");
var match = regex.Match(macosAppleAuthManagerInfoPlist);
if (!match.Success)
{
throw new Exception(GetMessage("Can't locate CFBundleIdentifier in MacOSAppleAuthManager's Info.plist"));
}
var modifiedMacosAppleAuthManagerInfoPlist = macosAppleAuthManagerInfoPlist
.Remove(match.Groups[1].Index, match.Groups[1].Length)
.Insert(match.Groups[1].Index, PlayerSettings.applicationIdentifier);

File.WriteAllText(macosAppleAuthManagerInfoPlistPath, modifiedMacosAppleAuthManagerInfoPlist);
Debug.Log(GetMessage($"Renamed MacOSAppleAuthManager.bundle bundle identifier from \"com.lupidan.MacOSAppleAuthManager\" -> \"{PlayerSettings.applicationIdentifier}.MacOSAppleAuthManager\""));
}
catch (Exception exception)
{
throw new Exception(GetMessage(
$"Error while fixing MacOSAppleAuthManager.bundle bundle identifier :: {exception.Message}"));
}
}

private static string GetMessage(string message) => $"{nameof(AppleAuthMacosPostprocessorHelper)}: {message}";

private static string GetInfoPlistPath(string path)
{
const string bundleName = "MacOSAppleAuthManager.bundle";
var possibleRootPaths = new List<string>();
if (Directory.Exists(path))
{
possibleRootPaths.Add(path);
}
if (Directory.Exists($"{path}.app"))
{
possibleRootPaths.Add($"{path}.app");
}

var bundleDirectories = possibleRootPaths
.SelectMany(possibleRootPath => Directory.GetDirectories(
possibleRootPath,
bundleName,
SearchOption.AllDirectories))
.ToArray();

if (bundleDirectories.Length == 0)
{
throw new Exception(GetMessage($"Can't locate any {bundleName}"));
}

if (bundleDirectories.Length > 1)
{
var allPaths = string.Join("\n", bundleDirectories);
throw new Exception(GetMessage($"Located multiple {bundleName}!\n{allPaths}"));
}
var bundlePath = bundleDirectories[0];
Debug.Log(GetMessage($"Located {bundleName} at {bundlePath}"));
var infoPlistPath = Path.Combine(
bundlePath,
"Contents",
"Info.plist");

if (!File.Exists(infoPlistPath))
{
throw new Exception(GetMessage("Can't locate MacOSAppleAuthManager's Info.plist"));
}
Debug.Log(GetMessage($"Located Info.plist at {infoPlistPath}"));
return infoPlistPath;
}
}
}

+ 11
- 0
Assets/AppleAuth/Editor/AppleAuthMacosPostprocessorHelper.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 244ee337f35d04f1c91b7f450fb421e0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 90
- 0
Assets/AppleAuth/Editor/ProjectCapabilityManagerExtension.cs View File

@@ -0,0 +1,90 @@
#if UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS

using System;
using System.Reflection;
using UnityEditor.iOS.Xcode;

namespace AppleAuth.Editor
{
public static class ProjectCapabilityManagerExtension
{
/// <summary>
/// Extension method for ProjectCapabilityManager to add the Sign In With Apple capability in compatibility mode.
/// In particular, adds the AuthenticationServices.framework as an Optional framework, preventing crashes in
/// iOS versions previous to 13.0
/// </summary>
/// <param name="manager">The manager for the main target to use when adding the Sign In With Apple capability.</param>
public static void AddSignInWithAppleWithCompatibility(this ProjectCapabilityManager manager)
{
const BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
var managerType = typeof(ProjectCapabilityManager);
var projectField = managerType.GetField("project", bindingFlags);
var entitlementFilePathField = managerType.GetField("m_EntitlementFilePath", bindingFlags);
var targetGuidField = managerType.GetField("m_TargetGuid", bindingFlags);
var getOrCreateEntitlementDocMethod = managerType.GetMethod("GetOrCreateEntitlementDoc", bindingFlags);
if (projectField == null ||
entitlementFilePathField == null ||
targetGuidField == null ||
getOrCreateEntitlementDocMethod == null)
throw new Exception("Can't Add Sign In With Apple programatically in this Unity version.");
var entitlementFilePath = entitlementFilePathField.GetValue(manager) as string;
var entitlementDoc = (PlistDocument) getOrCreateEntitlementDocMethod.Invoke(manager, new object[] { });
if (entitlementDoc != null)
{
var plistArray = new PlistElementArray();
plistArray.AddString("Default");
entitlementDoc.root["com.apple.developer.applesignin"] = plistArray;
}

var project = (PBXProject) projectField.GetValue(manager);
var emptyCapability = GetEmptyCapabilityWithReflection();
var mainTargetGuid = (string)targetGuidField.GetValue(manager);
#if UNITY_2019_3_OR_NEWER
var frameworkTargetGuid = project.GetUnityFrameworkTargetGuid();
#else
var frameworkTargetGuid = mainTargetGuid;
#endif
project.AddFrameworkToProject(frameworkTargetGuid, "AuthenticationServices.framework", true);
project.AddCapability(mainTargetGuid, emptyCapability, entitlementFilePath);
}
private static PBXCapabilityType GetEmptyCapabilityWithReflection()
{
// For Unity version >= 6000.0.23f1
var constructorInfo = typeof(PBXCapabilityType)
.GetConstructor(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null,
new[] {typeof(bool), typeof(string), typeof(bool)},
null);

if (constructorInfo != null)
{
return (PBXCapabilityType) constructorInfo
.Invoke(new object[] {true, string.Empty, true});
}
// For Unity version < 6000.0.23f1
constructorInfo = typeof(PBXCapabilityType)
.GetConstructor(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance,
null,
new[] {typeof(string), typeof(bool), typeof(string), typeof(bool)},
null);

if (constructorInfo != null)
{
return (PBXCapabilityType) constructorInfo
.Invoke(new object[] {"com.lupidan.apple-signin-unity.empty", true, string.Empty, true});
}

throw new Exception("Can't create empty capability in this Unity version.");
}
}
}

#endif

+ 11
- 0
Assets/AppleAuth/Editor/ProjectCapabilityManagerExtension.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f6bbae2bfef6749998d8b2f368d2aaff
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 9
- 0
Assets/AppleAuth/LICENSE.md View File

@@ -0,0 +1,9 @@


Copyright (c) 2019 Daniel Lupiañez Casares

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 7
- 0
Assets/AppleAuth/LICENSE.md.meta View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 42adfd64036c64657b1ece38984402c3
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 532
- 0
Assets/AppleAuth/README.md View File

@@ -0,0 +1,532 @@
<p align="center">
<img src="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/SignInWithApple.png" alt="Sign in With Apple"/><img src="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/UnityIcon.png" alt="Unity 3D"/>
</p>

# Sign in with Apple Unity Plugin

by **Daniel Lupiañez Casares**


[![Sponsor](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub)](https://github.com/sponsors/lupidan)


[![Release](https://img.shields.io/github/v/release/lupidan/apple-signin-unity?style=for-the-badge!)](https://github.com/lupidan/apple-signin-unity/releases)
[![License](https://img.shields.io/github/license/lupidan/apple-signin-unity.svg)](https://github.com/lupidan/apple-signin-unity/blob/master/LICENSE.md)
[![CHANGELOG](https://img.shields.io/badge/-CHANGELOG-informational)](https://github.com/lupidan/apple-signin-unity/blob/master/CHANGELOG.md)


[![openupm](https://img.shields.io/npm/v/com.lupidan.apple-signin-unity?label=openupm&registry_uri=https://package.openupm.com)](https://openupm.com/packages/com.lupidan.apple-signin-unity/)


[![Stars](https://img.shields.io/github/stars/lupidan/apple-signin-unity.svg?style=social)](https://github.com/lupidan/apple-signin-unity/stargazers)
[![Followers](https://img.shields.io/github/followers/lupidan.svg?style=social)](https://github.com/lupidan?tab=followers)


<p align="center">
<a href="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/SCRN01.png"><img src="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/SCRN01.png" alt="Screenshot1" height="400"/></a>
<a href="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/SCRN02.png"><img src="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/SCRN02.png" alt="Screenshot1" height="400"/></a>
<a href="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/SCRN03.png"><img src="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/SCRN03.png" alt="Screenshot2" height="400"/></a>
</p>



* [Overview](#overview)
* [Features](#features)
+ [Native Sign in with Apple](#native-sign-in-with-apple)
* [Installation](#installation)
+ [Unity Package Manager](#unity-package-manager)
- [Install via Git URL](#install-via-git-url)
- [Install via OpenUPM](#install-via-openupm)
+ [Unity Package File](#unity-package-file)
* [Plugin setup (iOS/tvOS)](#plugin-setup-iostvos)
+ [Programmatic setup with a Script](#programmatic-setup-with-a-script)
+ [Manual entitlements setup](#manual-entitlements-setup)
+ [Enabling Apple capability](#enabling-apple-capability)
+ [Final notes regarding setup](#final-notes-regarding-setup)
* [Plugin setup (macOS)](#plugin-setup-macos)
* [Implement Sign in With Apple](#implement-sign-in-with-apple)
+ [Initializing](#initializing)
+ [Perform Sign In With Apple](#perform-sign-in-with-apple)
+ [Quick login](#quick-login)
+ [Checking credential status](#checking-credential-status)
+ [Listening to credentials revoked notification](#listening-to-credentials-revoked-notification)
+ [Nonce and State support for Authorization Requests](#nonce-and-state-support-for-authorization-requests)
* [FAQ](#faq)
+ [Does it support landscape orientations?](#does-it-support-landscape-orientations)
+ [How can I Logout? Does the plugin provide any Logout option?](#how-can-i-logout-does-the-plugin-provide-any-logout-option)
+ [I am not getting a full name, or an email, even though I am requesting them in the LoginWithAppleId call](#i-am-not-getting-a-full-name-or-an-email-even-though-i-am-requesting-them-in-the-loginwithappleid-call)
+ [Is it possible to NOT request the user's email or full name?](#is-it-possible-to-not-request-the-users-email-or-full-name)
+ [Does the plugin use UnitySendMessage?](#does-the-plugin-use-unitysendmessage)
+ [Why do I need to call Update manually on the AppleAuthManager instance?](#why-do-i-need-to-call-update-manually-on-the-appleAuthManager-instance)
+ [What deserialization library does it use by default?](#what-deserialization-library-does-it-use-by-default)
+ [Any way to get a refresh token after the first user authorization?](#any-way-to-get-a-refresh-token-after-the-first-user-authorization)
+ [I am getting a CFBundleIdentifier Collision error when uploading my app to the macOS App Store](#i-am-getting-a-cfbundleIdentifier-collision-error-when-uploading-my-app-to-the-macos-app-store)

## Overview
Sign in with Apple plugin to use with Unity 3D game engine.

This plugin supports the following platforms:
* **iOS**
* **macOS** Intel `x86_64` AND Apple Silicon `arm64`(Experimental) ([NOTES](./docs/macOS_NOTES.md))
* **tvOS** (Experimental)
* **visionOS** (Experimental)

The main purpose for this plugin is to expose Apple's newest feature, Sign in with Apple, to the Unity game engine.

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**.

## Features
### Native Sign in with Apple
- Support for iOS
- Support for macOS: Intel `x86_64` AND Apple Silicon `arm64`(Experimental) ([NOTES](./docs/macOS_NOTES.md))
- Support for tvOS (Experimental)
- Support for visionOS (Experimental)
- 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 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

> Current stable version is 1.5.0

There are two options available to install this plugin. Either using the Unity Package Manager, or the traditional `.unitypackage` file.

### Unity Package Manager

#### Install via Git URL

Available starting from Unity 2020.3.

Just add this line to the `Packages/manifest.json` file of your Unity Project:

```json
"dependencies": {
"com.lupidan.apple-signin-unity": "https://github.com/lupidan/apple-signin-unity.git?path=Source#1.5.0",
}
```

#### Install via OpenUPM

The package is available on the [openupm registry](https://openupm.com). You can install it via [openupm-cli](https://github.com/openupm/openupm-cli).

```
openupm add com.lupidan.apple-signin-unity
```

### Unity Package File
1. Download the most recent Unity package release [here](https://github.com/lupidan/apple-signin-unity/releases)
2. Import the downloaded Unity package in your app. There are two main folders:

* The `AppleAuth` folder contains the **main plugin**.
* The `AppleAuthSample` folder contains **sample code** to use as a reference, or to test the plugin.

![Import detail](https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/ImportPlugin.png)

## Plugin setup (iOS/tvOS)

To be able to use Apple's platform and framework for Authenticating with an Apple ID, we need to set up our Xcode project. Two different options are available to set up the entitlements required to enable Apple ID authentication with the iOS SDK.

### Programmatic setup with a Script

*RECOMMENDED*

This plugin **provides an extension method** for `ProjectCapabilityManager` ([docs](https://docs.unity3d.com/ScriptReference/iOS.Xcode.ProjectCapabilityManager.html)), used to add this entitlement programatically after an Xcode build has finished.

Simply create a Post Processing build script ([more info](https://docs.unity3d.com/ScriptReference/Callbacks.PostProcessBuildAttribute.html)) that performs the call. If you already have a post process build script, it should be simple to add to your code.

The provided extension method is `AddSignInWithAppleWithCompatibility`.

Sample code:
```csharp
using AppleAuth.Editor;

public static class SignInWithApplePostprocessor
{
[PostProcessBuild(1)]
public static void OnPostProcessBuild(BuildTarget target, string path)
{
if (target != BuildTarget.iOS)
return;

var projectPath = PBXProject.GetPBXProjectPath(path);
var project = new PBXProject();
project.ReadFromString(System.IO.File.ReadAllText(projectPath));
var manager = new ProjectCapabilityManager(projectPath, "Entitlements.entitlements", null, project.GetUnityMainTargetGuid());
manager.AddSignInWithAppleWithCompatibility();
manager.WriteToFile();
}
}
```

### Manual entitlements setup

The other option is to manually setup all the entitlements in our Xcode project. Note that when making an iOS Build from Unity into the same folder, if you choose the option to overwrite, you will need to perform the Manual setup again.

1. In your generated Xcode project. Select the main app Unity-iPhone target and select the option *Signing And Capabilities*. You should see there an option to add a capability from a list. Just locate *Sign In With Apple* and add it to your project.

<p align="center">
<a href="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/AddEntitlements.png"><img src="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/AddEntitlements.png" alt="Add Entitlements" width="400"/></a>
</p>


2. This should have added an Entitlements file to your project. Locate it on the project explorer (it should be a file with the extension `.entitlements`). Inside it you should see an entry like this one:

<p align="center">
<a href="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/EntitlementsDetail.png"><img src="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/EntitlementsDetail.png"/></a>
</p>

3. You need to import the `AuthenticationServices.framework` library in the Build Phases->Link Binary with Libraries. **If you are targeting older iOS versions**, mark the library as `Optional`.

For **Unity 2019.3** onwards, add it to the UnityFramework target

For **previous Unity versions**, add it to the main Unity-iPhone target

<p align="center">
<a href="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/AddFramework20193.png"><img src="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/AddFramework20193.png" alt="Add Framework 2019.3" width="400"/></a>
<a href="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/AddFrameworkPrevious.png"><img src="https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/AddFrameworkPrevious.png" alt="Add Framework Previous versions" width="400"/></a>
</p>

### Enabling Apple capability

You will also need to **setup everything** in the Apple's developer portal. More information can be found [here](https://help.apple.com/developer-account/#/devde676e696). Please remember this plugin only supports native Sign In With Apple on iOS (no REST API support).

There is also a [Getting Started site](https://developer.apple.com/sign-in-with-apple/get-started/).

### Final notes regarding setup

The `AuthenticationServices.framework` should be added as Optional, to support previous iOS versions, avoiding crashes at startup.

The provided extension method uses reflection to integrate with the current tools Unity provides. It has been tested with Unity 2020.x, 2021.x, 2022.x and 6000.0. But if it fails on your particular Unity version, feel free to open a issue, specifying the Unity version.

## Plugin setup (visionOS)

On visionOS, the setup is pretty much the same as the iOS/tvOS setup.
However, due to how Unity's visionOS project is exported, you need to adapt the Postprocess code to find the proper xcode project filename:

if (target == BuildTarget.VisionOS)
{
projectPath = projectPath.Replace("Unity-iPhone.xcodeproj", "Unity-VisionOS.xcodeproj");
}

## Plugin setup (macOS)

An unsigned precompiled `.bundle` file is available. The precompiled `.bundle` should support both architectures: Intel `x86_64` & Apple Silicon `arm64`(Experimental). The bundle should be automatically included in your macOS builds.
However that `.bundle` needs to be modified to avoid issues when uploading it to the MacOS App Store.

In particular, the bundle identifier of that `.bundle` needs to be modified to a custom one.

To automate the process, there is a helper method that will change the bundle identifier to one based on your project's application identifier.
You should call this method on a Postprocess build script of your choice.

```csharp
using AppleAuth.Editor;

public static class SignInWithApplePostprocessor
{
[PostProcessBuild(1)]
public static void OnPostProcessBuild(BuildTarget target, string path)
{
if (target != BuildTarget.StandaloneOSX)
return;

AppleAuthMacosPostprocessorHelper.FixManagerBundleIdentifier(target, path);
}
}
```

The Xcode project with the source code to generate a new bundle file is available at `MacOSAppleAuthManager/MacOSAppleAuthManager.xcodeproj`

To support the feature, **the app needs to be codesigned correctly**, including the required entitlements. For more information regarding macOS codesign, please follow this [link](./docs/macOS_NOTES.md).

## Implement Sign in With Apple

> Currently, it seems Sign In With Apple does not work properly in the simulator. This needs testing on a device with an iOS 13 version.

An overall flow of how the native Sign In With Apple flow could work is presented in this diagram.

![Frameworks detail](https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/AppleSignInFlow_v3.png)

### Initializing
```csharp
private IAppleAuthManager appleAuthManager;

void Start()
{
...
// If the current platform is supported
if (AppleAuthManager.IsCurrentPlatformSupported)
{
// Creates a default JSON deserializer, to transform JSON Native responses to C# instances
var deserializer = new PayloadDeserializer();
// Creates an Apple Authentication manager with the deserializer
this.appleAuthManager = new AppleAuthManager(deserializer);
}
...
}

void Update()
{
...
// Updates the AppleAuthManager instance to execute
// pending callbacks inside Unity's execution loop
if (this.appleAuthManager != null)
{
this.appleAuthManager.Update();
}
...
}
```

### Perform Sign In With Apple

> :warning: You will receive users's email and name **ONLY THE FIRST TIME THE USER LOGINS**. Any further login attempts **will have a NULL Email and FullName**, unless you [revoke the credentials](#how-can-i-logout-does-the-plugin-provide-any-logout-option)

If you want to Sign In and request the Email and Full Name for a user, you can do it like this:

```csharp
var loginArgs = new AppleAuthLoginArgs(LoginOptions.IncludeEmail | LoginOptions.IncludeFullName);

this.appleAuthManager.LoginWithAppleId(
loginArgs,
credential =>
{
// Obtained credential, cast it to IAppleIDCredential
var appleIdCredential = credential as IAppleIDCredential;
if (appleIdCredential != null)
{
// Apple User ID
// You should save the user ID somewhere in the device
var userId = appleIdCredential.User;
PlayerPrefs.SetString(AppleUserIdKey, userId);

// Email (Received ONLY in the first login)
var email = appleIdCredential.Email;

// Full name (Received ONLY in the first login)
var fullName = appleIdCredential.FullName;

// Identity token
var identityToken = Encoding.UTF8.GetString(
appleIdCredential.IdentityToken,
0,
appleIdCredential.IdentityToken.Length);

// Authorization code
var authorizationCode = Encoding.UTF8.GetString(
appleIdCredential.AuthorizationCode,
0,
appleIdCredential.AuthorizationCode.Length);

// And now you have all the information to create/login a user in your system
}
},
error =>
{
// Something went wrong
var authorizationErrorCode = error.GetAuthorizationErrorCode();
});
```

### Quick login

This should be the **first thing to try** when the user first runs the application.

If the user has previously authorized the app to login with Apple, this will open a native dialog to re-confirm the login, and obtain an Apple User ID.

If the credentials were never given, or they were revoked, the Quick login will fail.

![Frameworks detail](https://raw.githubusercontent.com/lupidan/apple-signin-unity/93e79cacc665fcd3930bda9e27e8cb27631ff1f7/Img/QuickLogin.png)

```csharp
var quickLoginArgs = new AppleAuthQuickLoginArgs();

this.appleAuthManager.QuickLogin(
quickLoginArgs,
credential =>
{
// Received a valid credential!
// Try casting to IAppleIDCredential or IPasswordCredential

// Previous Apple sign in credential
var appleIdCredential = credential as IAppleIDCredential;

// Saved Keychain credential (read about Keychain Items)
var passwordCredential = credential as IPasswordCredential;
},
error =>
{
// Quick login failed. The user has never used Sign in With Apple on your app. Go to login screen
});
```

Note that, if this succeeds, you will **ONLY** receive the Apple User ID (no email or name, even if it was previously requested).

#### IOS Keychain Support
When performing a quick login, if the SDK detects [IOS Keychain credentials](https://developer.apple.com/documentation/security/keychain_services/keychain_items?language=objc) for your app, it will return those.

Just cast the credential to `IPasswordCredential` to get the login details for the user.

### Checking credential status

This is used to verify that an Apple User ID is still valid.

Given an `userId` from a previous successful sign in.
You can check the credential state of that user ID like so:

```csharp
this.appleAuthManager.GetCredentialState(
userId,
state =>
{
switch (state)
{
case CredentialState.Authorized:
// User ID is still valid. Login the user.
break;
case CredentialState.Revoked:
// User ID was revoked. Go to login screen.
break;
case CredentialState.NotFound:
// User ID was not found. Go to login screen.
break;
}
},
error =>
{
// Something went wrong
});
```

### Listening to credentials revoked notification

It may be that your user suddenly decides to revoke the authorization that was given previously. You should be able to listen to the incoming notification by registering a callback for it.


```csharp
this.appleAuthManager.SetCredentialsRevokedCallback(result =>
{
// Sign in with Apple Credentials were revoked.
// Discard credentials/user id and go to login screen.
});
```

To clear the callback, and stop listening to notifications, simply set it to `null`

```csharp
this.appleAuthManager.SetCredentialsRevokedCallback(null);
```

### Nonce and State support for Authorization Requests

Both methods, `LoginWithAppleId` and `QuickLogin`, use a custom structure containing arguments for the authorization request.

An optional `Nonce` and an optional `State` can be set for both structures when constructing them:

```csharp
// Your custom Nonce string
var yourCustomNonce = "RANDOM_NONCE_FORTHEAUTHORIZATIONREQUEST";
var yourCustomState = "RANDOM_STATE_FORTHEAUTHORIZATIONREQUEST";

// Arguments for a normal Sign In With Apple Request
var loginArgs = new AppleAuthLoginArgs(
LoginOptions.IncludeEmail | LoginOptions.IncludeFullName,
yourCustomNonce,
yourCustomState);

// Arguments for a Quick Login
var quickLoginArgs = new AppleAuthQuickLoginArgs(yourCustomNonce, yourCustomState);
```

The `State` is returned later in the received Apple ID credential, allowing you to validate that the request was generated in your device.

The `Nonce` is embedded in the IdentityToken, included in the received Apple ID credential. It is important to generate a new random `Nonce` for every request. This is useful for services that provide a built in solution for **Sign In With Apple**, like [Firebase](https://firebase.google.com/docs/auth/ios/apple?authuser=0)

Some tentative guide is available for Firebase integration [here](./docs/Firebase_NOTES.md)

More info about State and Nonce can be found in [this WWDC 2020 session](https://developer.apple.com/videos/play/wwdc2020/10173/) (check at 2m35s)

## FAQ
+ [Does it support landscape orientations](#does-it-support-landscape-orientations)
+ [How can I Logout? Does the plugin provide any Logout option?](#how-can-i-logout-does-the-plugin-provide-any-logout-option)
+ [I am not getting a full name, or an email, even though I am requesting them in the LoginWithAppleId call](#i-am-not-getting-a-full-name-or-an-email-even-though-i-am-requesting-them-in-the-loginwithappleid-call)
+ [Is it possible to NOT request the user's email or full name?](#is-it-possible-to-not-request-the-users-email-or-full-name)
+ [Does the plugin use UnitySendMessage?](#does-the-plugin-use-unitysendmessage)
+ [Why do I need to call Update manually on the AppleAuthManager instance?](#why-do-i-need-to-call-update-manually-on-the-appleAuthManager-instance)
+ [What deserialization library does it use by default?](#what-deserialization-library-does-it-use-by-default)
+ [Any way to get a refresh token after the first user authorization?](#any-way-to-get-a-refresh-token-after-the-first-user-authorization)

### Does it support landscape orientations?
On **iOS 13.0**, Apple does not support landscape orientation for this feature. For more details, check this [issue](https://github.com/lupidan/apple-signin-unity/issues/5).

### How can I Logout? Does the plugin provide any Logout option?

On **iOS 13** Apple does not provide any method to *"logout"* programatically. If you want to *"logout"* and re-test account creation, you need to revoke the credentials through settings.

Go to `Settings` => `Click your iTunes user` => `Password & Security` => `Apple ID logins`. There you can select the app and click on `Stop using Apple ID`.

After this, the credentials are effectively revoked, your app will receive a [Credentials Revoked notification](#listening-to-credentials-revoked-notification). This will allow you to re-test account creation.

### I am not getting a full name, or an email, even though I am requesting them in the LoginWithAppleId call

This probably means that you already used Sign In with apple at some point. Apple will give you the email/name **ONLY ONCE**. Once the credential is created, __it's your app/game's responsibility to send that information somewhere__, so an account is created with the given user identifier.

If a credential was already created, you will only receive a user identifier, so it will work similarly to a Quick Login.

If you want to test new account scenarios, you need to [revoke](#how-can-i-logout-does-the-plugin-provide-any-logout-option) your app credentials for that Apple ID through the settings menu.

### Is it possible to NOT request the user's email or full name?

Yes, just provide `LoginOptions.None` when calling `LoginWithAppleId` and the user will not be asked for their email or full name.
This will skip that entire login step and make it more smooth. It is recommended if the user's email or full name is not used.

```csharp
appleAuthManager.LoginWithAppleId(LoginOptions.None, credential => { ... }, error => { ... });
```

### Does the plugin use UnitySendMessage?

No. The plugin uses callbacks in a static context with request identifiers using JSON strings. Callbacks are scheduled inside `AppleAuthManager`, and calling `Update` on it will execute those pending callbacks.

### Why do I need to call Update manually on the AppleAuthManager instance?

Callbacks from iOS SDK are executed in their own thread (normally the main thread), and outside Unity's engine control. Meaning that you can't update the UI, or worse, if your callback throws an Exception (like a simple NRE), it will crash the Game completely.

It's recommended to update the instance of `AppleAuthManager` regularly in a MonoBehaviour of your choice.

### What deserialization library does it use by default?

If you initialize the `AppleAuthManager` with the built-in `PayloadDeserializer`, it uses Unity JSON serialization system, so **no extra libraries are added**.

You can also implement your own deserialization by implementing an `IPayloadDeserializer`.

### Any way to get a refresh token on iOS to verify a user?

**NO**, That's not how Apple wants you to do it. This is how they want you to verify a user:

_On iOS:_ The first login gives you the Apple User ID and an Authorization Code to send to your backend. Checking the validity of a user on the device, from now on, should be done with `GetCredentialState` and that Apple User ID.

_On the server:_ It receives the data from the first login on iOS to create the user. Uses that received Authorization Code to get a refresh token for the user. Refreshes the token once a day.
[More info here](http://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_rest_api/verifying_a_user)

### I am getting a CFBundleIdentifier Collision error when uploading my app to the macOS App Store:

If you are experiencing an error like this when uploading your macOS app to the App Store
> The info.plist CFBundleIdentifier value 'com.lupidan.MacOSAppleAuthManager" of 'appname.app/Contents/Plugins/MacOSAppleAuthManager.bundle' is already in use by another application"

It probably means that your [postprocess build script for macOS](#plugin-setup-macos) is not setup correctly.

You should call `AppleAuthMacosPostprocessorHelper.FixManagerBundleIdentifier` to fix the plugin's bundle identifier to a custom one for your app.

You can find more details about the bug [here](https://github.com/lupidan/apple-signin-unity/issues/72)


+ 7
- 0
Assets/AppleAuth/README.md.meta View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9a7fbb4b439cc4d329fc4ece08c1d7bb
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 8
- 0
Assets/AppleAuth/Runtime.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e4b3990cf691541809dac7ec03c3ed9d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 3
- 0
Assets/AppleAuth/Runtime/AppleAuth.asmdef View File

@@ -0,0 +1,3 @@
{
"name": "AppleAuth"
}

+ 7
- 0
Assets/AppleAuth/Runtime/AppleAuth.asmdef.meta View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: d2e6cf35637124bd3bae6e7160a590d7
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 21
- 0
Assets/AppleAuth/Runtime/AppleAuthLoginArgs.cs View File

@@ -0,0 +1,21 @@
using AppleAuth.Enums;

namespace AppleAuth
{
public struct AppleAuthLoginArgs
{
public readonly LoginOptions Options;
public readonly string Nonce;
public readonly string State;
public AppleAuthLoginArgs(
LoginOptions options,
string nonce = null,
string state = null)
{
this.Options = options;
this.Nonce = nonce;
this.State = state;
}
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/AppleAuthLoginArgs.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 935e1fe3ddaa24fa986b4a08d16ef677
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 338
- 0
Assets/AppleAuth/Runtime/AppleAuthManager.cs View File

@@ -0,0 +1,338 @@
#if ((UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS || UNITY_STANDALONE_OSX) && !UNITY_EDITOR)
#define APPLE_AUTH_MANAGER_NATIVE_IMPLEMENTATION_AVAILABLE
#endif

using AppleAuth.Enums;
using AppleAuth.Interfaces;
using System;

namespace AppleAuth
{
public class AppleAuthManager : IAppleAuthManager
{
static AppleAuthManager()
{
const string versionMessage = "Using Sign in with Apple Unity Plugin - 1.5.0";
#if APPLE_AUTH_MANAGER_NATIVE_IMPLEMENTATION_AVAILABLE
PInvoke.AppleAuth_LogMessage(versionMessage);
#else
UnityEngine.Debug.Log(versionMessage);
#endif
}

#if APPLE_AUTH_MANAGER_NATIVE_IMPLEMENTATION_AVAILABLE
private readonly IPayloadDeserializer _payloadDeserializer;

private Action<string> _credentialsRevokedCallback;
#endif

public static bool IsCurrentPlatformSupported
{
get
{
#if APPLE_AUTH_MANAGER_NATIVE_IMPLEMENTATION_AVAILABLE
return PInvoke.AppleAuth_IsCurrentPlatformSupported();
#else
return false;
#endif
}
}

public AppleAuthManager(IPayloadDeserializer payloadDeserializer)
{
#if APPLE_AUTH_MANAGER_NATIVE_IMPLEMENTATION_AVAILABLE
this._payloadDeserializer = payloadDeserializer;
#endif
}

public void QuickLogin(Action<ICredential> successCallback, Action<IAppleError> errorCallback)
{
this.QuickLogin(new AppleAuthQuickLoginArgs(), successCallback, errorCallback);
}

public void QuickLogin(
AppleAuthQuickLoginArgs quickLoginArgs,
Action<ICredential> successCallback,
Action<IAppleError> errorCallback)
{
#if APPLE_AUTH_MANAGER_NATIVE_IMPLEMENTATION_AVAILABLE
var nonce = quickLoginArgs.Nonce;
var state = quickLoginArgs.State;
var requestId = CallbackHandler.AddMessageCallback(
true,
payload =>
{
var response = this._payloadDeserializer.DeserializeLoginWithAppleIdResponse(payload);
if (response.Error != null)
errorCallback(response.Error);
else if (response.PasswordCredential != null)
successCallback(response.PasswordCredential);
else
successCallback(response.AppleIDCredential);
});

PInvoke.AppleAuth_QuickLogin(requestId, nonce, state);
#else
throw new Exception("AppleAuthManager is not supported in this platform");
#endif
}

public void LoginWithAppleId(LoginOptions options, Action<ICredential> successCallback, Action<IAppleError> errorCallback)
{
this.LoginWithAppleId(new AppleAuthLoginArgs(options), successCallback, errorCallback);
}

public void LoginWithAppleId(
AppleAuthLoginArgs loginArgs,
Action<ICredential> successCallback,
Action<IAppleError> errorCallback)
{
#if APPLE_AUTH_MANAGER_NATIVE_IMPLEMENTATION_AVAILABLE
var loginOptions = loginArgs.Options;
var nonce = loginArgs.Nonce;
var state = loginArgs.State;
var requestId = CallbackHandler.AddMessageCallback(
true,
payload =>
{
var response = this._payloadDeserializer.DeserializeLoginWithAppleIdResponse(payload);
if (response.Error != null)
errorCallback(response.Error);
else
successCallback(response.AppleIDCredential);
});
PInvoke.AppleAuth_LoginWithAppleId(requestId, (int)loginOptions, nonce, state);
#else
throw new Exception("AppleAuthManager is not supported in this platform");
#endif
}
public void GetCredentialState(
string userId,
Action<CredentialState> successCallback,
Action<IAppleError> errorCallback)
{
#if APPLE_AUTH_MANAGER_NATIVE_IMPLEMENTATION_AVAILABLE
var requestId = CallbackHandler.AddMessageCallback(
true,
payload =>
{
var response = this._payloadDeserializer.DeserializeCredentialStateResponse(payload);
if (response.Error != null)
errorCallback(response.Error);
else
successCallback(response.CredentialState);
});
PInvoke.AppleAuth_GetCredentialState(requestId, userId);
#else
throw new Exception("AppleAuthManager is not supported in this platform");
#endif
}
public void SetCredentialsRevokedCallback(Action<string> credentialsRevokedCallback)
{
#if APPLE_AUTH_MANAGER_NATIVE_IMPLEMENTATION_AVAILABLE
if (this._credentialsRevokedCallback != null)
{
CallbackHandler.NativeCredentialsRevoked -= this._credentialsRevokedCallback;
this._credentialsRevokedCallback = null;
}

if (credentialsRevokedCallback != null)
{
CallbackHandler.NativeCredentialsRevoked += credentialsRevokedCallback;
this._credentialsRevokedCallback = credentialsRevokedCallback;
}
#endif
}

public void Update()
{
#if APPLE_AUTH_MANAGER_NATIVE_IMPLEMENTATION_AVAILABLE
CallbackHandler.ExecutePendingCallbacks();
#endif
}

#if APPLE_AUTH_MANAGER_NATIVE_IMPLEMENTATION_AVAILABLE
private static class CallbackHandler
{
private const uint InitialCallbackId = 1U;
private const uint MaxCallbackId = uint.MaxValue;

private static readonly object SyncLock = new object();
private static readonly System.Collections.Generic.Dictionary<uint, Entry> CallbackDictionary = new System.Collections.Generic.Dictionary<uint, Entry>();
private static readonly System.Collections.Generic.List<Action> ScheduledActions = new System.Collections.Generic.List<Action>();

private static uint _callbackId = InitialCallbackId;
private static bool _initialized = false;
private static uint _credentialsRevokedCallbackId = 0U;
private static event Action<string> _nativeCredentialsRevoked = null;

public static event Action<string> NativeCredentialsRevoked
{
add
{
lock (SyncLock)
{
if (_nativeCredentialsRevoked == null)
{
_credentialsRevokedCallbackId = AddMessageCallback(false, payload => _nativeCredentialsRevoked.Invoke(payload));
PInvoke.AppleAuth_RegisterCredentialsRevokedCallbackId(_credentialsRevokedCallbackId);
}

_nativeCredentialsRevoked += value;
}
}

remove
{
lock (SyncLock)
{
_nativeCredentialsRevoked -= value;

if (_nativeCredentialsRevoked == null)
{
RemoveMessageCallback(_credentialsRevokedCallbackId);
_credentialsRevokedCallbackId = 0U;
PInvoke.AppleAuth_RegisterCredentialsRevokedCallbackId(0U);
}
}
}
}

public static void ScheduleCallback(uint requestId, string payload)
{
lock (SyncLock)
{
var callbackEntry = default(Entry);
if (CallbackDictionary.TryGetValue(requestId, out callbackEntry))
{
var callback = callbackEntry.MessageCallback;
ScheduledActions.Add(() => callback.Invoke(payload));

if (callbackEntry.IsSingleUseCallback)
{
CallbackDictionary.Remove(requestId);
}
}
}
}

public static void ExecutePendingCallbacks()
{
lock (SyncLock)
{
while (ScheduledActions.Count > 0)
{
var action = ScheduledActions[0];
ScheduledActions.RemoveAt(0);
action.Invoke();
}
}
}

public static uint AddMessageCallback(bool isSingleUse, Action<string> messageCallback)
{
if (!_initialized)
{
PInvoke.AppleAuth_SetupNativeMessageHandlerCallback(PInvoke.NativeMessageHandlerCallback);
_initialized = true;
}

if (messageCallback == null)
{
throw new Exception("Can't add a null Message Callback.");
}

var usedCallbackId = default(uint);
lock (SyncLock)
{
usedCallbackId = _callbackId;
_callbackId += 1;
if (_callbackId >= MaxCallbackId)
_callbackId = InitialCallbackId;

var callbackEntry = new Entry(isSingleUse, messageCallback);
CallbackDictionary.Add(usedCallbackId, callbackEntry);
}
return usedCallbackId;
}

public static void RemoveMessageCallback(uint requestId)
{
lock (SyncLock)
{
if (!CallbackDictionary.ContainsKey(requestId))
{
throw new Exception("Callback with id " + requestId + " does not exist and can't be removed");
}

CallbackDictionary.Remove(requestId);
}
}

private class Entry
{
public readonly bool IsSingleUseCallback;
public readonly Action<string> MessageCallback;

public Entry(bool isSingleUseCallback, Action<string> messageCallback)
{
this.IsSingleUseCallback = isSingleUseCallback;
this.MessageCallback = messageCallback;
}
}
}

private static class PInvoke
{
#if UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS
private const string DllName = "__Internal";
#elif UNITY_STANDALONE_OSX
private const string DllName = "MacOSAppleAuthManager";
#endif

public delegate void NativeMessageHandlerCallbackDelegate(uint requestId, string payload);

[AOT.MonoPInvokeCallback(typeof(NativeMessageHandlerCallbackDelegate))]
public static void NativeMessageHandlerCallback(uint requestId, string payload)
{
try
{
CallbackHandler.ScheduleCallback(requestId, payload);
}
catch (Exception exception)
{
Console.WriteLine("Received exception while scheduling a callback for request ID " + requestId);
Console.WriteLine("Detailed payload:\n" + payload);
Console.WriteLine("Exception: " + exception);
}
}

[System.Runtime.InteropServices.DllImport(DllName)]
public static extern bool AppleAuth_IsCurrentPlatformSupported();

[System.Runtime.InteropServices.DllImport(DllName)]
public static extern void AppleAuth_SetupNativeMessageHandlerCallback(NativeMessageHandlerCallbackDelegate callback);
[System.Runtime.InteropServices.DllImport(DllName)]
public static extern void AppleAuth_GetCredentialState(uint requestId, string userId);

[System.Runtime.InteropServices.DllImport(DllName)]
public static extern void AppleAuth_LoginWithAppleId(uint requestId, int loginOptions, string nonceCStr, string stateCStr);
[System.Runtime.InteropServices.DllImport(DllName)]
public static extern void AppleAuth_QuickLogin(uint requestId, string nonceCStr, string stateCStr);
[System.Runtime.InteropServices.DllImport(DllName)]
public static extern void AppleAuth_RegisterCredentialsRevokedCallbackId(uint callbackId);

[System.Runtime.InteropServices.DllImport(DllName)]
public static extern void AppleAuth_LogMessage(string messageCStr);
}
#endif
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/AppleAuthManager.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1812ac7eddfab4a23a1cc982cac36051
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 14
- 0
Assets/AppleAuth/Runtime/AppleAuthQuickLoginArgs.cs View File

@@ -0,0 +1,14 @@
namespace AppleAuth
{
public struct AppleAuthQuickLoginArgs
{
public readonly string Nonce;
public readonly string State;

public AppleAuthQuickLoginArgs(string nonce = null, string state = null)
{
this.Nonce = nonce;
this.State = state;
}
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/AppleAuthQuickLoginArgs.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8a61733e4ebb942098197a89f5934c8e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 8
- 0
Assets/AppleAuth/Runtime/Enums.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f4e47df0608a64147a64d38fcc06cb6f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 33
- 0
Assets/AppleAuth/Runtime/Enums/AuthorizationErrorCode.cs View File

@@ -0,0 +1,33 @@
namespace AppleAuth.Enums
{
/// <summary>
/// ASAuthorizationError
/// </summary>
public enum AuthorizationErrorCode
{
/// <summary>
/// The authorization attempt failed for an unknown reason
/// </summary>
Unknown = 1000,

/// <summary>
/// The user canceled the authorization attempt
/// </summary>
Canceled = 1001,

/// <summary>
/// The authorization request received an invalid response
/// </summary>
InvalidResponse = 1002,

/// <summary>
/// The authorization request wasn't handled
/// </summary>
NotHandled = 1003,

/// <summary>
/// The authorization attempt failed
/// </summary>
Failed = 1004,
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Enums/AuthorizationErrorCode.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0c0980d6cfee342fdb99276ff8fb11dd
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 28
- 0
Assets/AppleAuth/Runtime/Enums/CredentialState.cs View File

@@ -0,0 +1,28 @@
namespace AppleAuth.Enums
{
/// <summary>
/// ASAuthorizationAppleIDProvider.CredentialState
/// </summary>
public enum CredentialState
{
/// <summary>
/// Authorization for the given user has been revoked
/// </summary>
Revoked = 0,

/// <summary>
/// The user is authorized
/// </summary>
Authorized = 1,

/// <summary>
/// The user can't be found
/// </summary>
NotFound = 2,
/// <summary>
/// ASAuthorizationAppleIDProviderCredentialTransferred
/// </summary>
Transferred = 3,
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Enums/CredentialState.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3d646586a6b44460cb153db7578ecfc7
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 23
- 0
Assets/AppleAuth/Runtime/Enums/LoginOptions.cs View File

@@ -0,0 +1,23 @@
using System;

namespace AppleAuth.Enums
{
[Flags]
public enum LoginOptions
{
/// <summary>
/// Empty scope. No full name or email
/// </summary>
None = 0,

/// <summary>
/// A scope that includes the user’s full name.
/// </summary>
IncludeFullName = 1 << 0,

/// <summary>
/// A scope that includes the user’s email address
/// </summary>
IncludeEmail = 1 << 1,
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Enums/LoginOptions.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2ef22db01f9c447db85fc3b72dc5260b
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 33
- 0
Assets/AppleAuth/Runtime/Enums/PersonNameFormatterStyle.cs View File

@@ -0,0 +1,33 @@
namespace AppleAuth.Enums
{
/// <summary>
/// NSPersonNameComponentsFormatter
/// </summary>
public enum PersonNameFormatterStyle
{
/// <summary>
/// The minimally necessary features for differentiation in a casual setting. Equivalent to NSPersonNameComponentsFormatterStyleMedium.
/// </summary>
Default = 0,

/// <summary>
/// Relies on user preferences and language defaults to display shortened form appropriate for display in space-constrained settings.
/// </summary>
Short = 1,

/// <summary>
/// The minimally necessary features for differentiation in a casual setting. Equivalent to NSPersonNameComponentsFormatterStyleDefault.
/// </summary>
Medium = 2,

/// <summary>
/// The fully qualified name complete with all known components.
/// </summary>
Long = 3,

/// <summary>
/// The maximally abbreviated form of a name.
/// </summary>
Abbreviated = 4,
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Enums/PersonNameFormatterStyle.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b5b6cd4c6059245f5bf45e2cdf6fd52d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 23
- 0
Assets/AppleAuth/Runtime/Enums/RealUserStatus.cs View File

@@ -0,0 +1,23 @@
namespace AppleAuth.Enums
{
/// <summary>
/// ASUserDetectionStatus
/// </summary>
public enum RealUserStatus
{
/// <summary>
/// The system can't determine this user's status as a real person.
/// </summary>
Unsupported = 0,

/// <summary>
/// The system hasn't determined whether the user might be a real person.
/// </summary>
Unknown = 1,

/// <summary>
/// The user appears to be a real person.
/// </summary>
LikelyReal = 2,
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Enums/RealUserStatus.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 77ef719658b694f05b1647b0bef37987
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 8
- 0
Assets/AppleAuth/Runtime/Extensions.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: e6df00849339b49b282935a9d57d1d04
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 20
- 0
Assets/AppleAuth/Runtime/Extensions/AppleErrorExtensions.cs View File

@@ -0,0 +1,20 @@
using AppleAuth.Enums;
using AppleAuth.Interfaces;
using System;

namespace AppleAuth.Extensions
{
public static class AppleErrorExtensions
{
public static AuthorizationErrorCode GetAuthorizationErrorCode(this IAppleError error)
{
if (error.Domain == "com.apple.AuthenticationServices.AuthorizationError" &&
Enum.IsDefined(typeof(AuthorizationErrorCode), error.Code))
{
return (AuthorizationErrorCode)error.Code;
}
return AuthorizationErrorCode.Unknown;
}
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Extensions/AppleErrorExtensions.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: dbc055864a39a46b4bbec75fe21d9cc8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 91
- 0
Assets/AppleAuth/Runtime/Extensions/PersonNameExtensions.cs View File

@@ -0,0 +1,91 @@
#if ((UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS || UNITY_STANDALONE_OSX) && !UNITY_EDITOR)
#define NATIVE_PERSON_NAME_COMPONENTS_AVAILABLE
#endif

using AppleAuth.Enums;
using AppleAuth.Interfaces;

namespace AppleAuth.Extensions
{
public static class PersonNameExtensions
{
public static string ToLocalizedString(
this IPersonName personName,
PersonNameFormatterStyle style = PersonNameFormatterStyle.Default,
bool usePhoneticRepresentation = false)
{
#if NATIVE_PERSON_NAME_COMPONENTS_AVAILABLE
var jsonString = JsonStringForPersonName(personName);
var localizedString = PInvoke.AppleAuth_GetPersonNameUsingFormatter(jsonString, (int) style, usePhoneticRepresentation);
if (localizedString != null)
{
return localizedString;
}
#endif
var orderedParts = new System.Collections.Generic.List<string>();
if (string.IsNullOrEmpty(personName.NamePrefix))
orderedParts.Add(personName.NamePrefix);
if (string.IsNullOrEmpty(personName.GivenName))
orderedParts.Add(personName.GivenName);
if (string.IsNullOrEmpty(personName.MiddleName))
orderedParts.Add(personName.MiddleName);
if (string.IsNullOrEmpty(personName.FamilyName))
orderedParts.Add(personName.FamilyName);
if (string.IsNullOrEmpty(personName.NameSuffix))
orderedParts.Add(personName.NameSuffix);

return string.Join(" ", orderedParts.ToArray());
}

#if NATIVE_PERSON_NAME_COMPONENTS_AVAILABLE
private const string StringDictionaryFormat = "\"{0}\": \"{1}\",";
private const string StringObjectFormat = "\"{0}\": {1},";

private static string JsonStringForPersonName(IPersonName personName)
{
if (personName == null)
return null;

var stringBuilder = new System.Text.StringBuilder();
stringBuilder.Append("{");
TryAddKeyValue(StringDictionaryFormat, "_namePrefix", personName.NamePrefix, stringBuilder);
TryAddKeyValue(StringDictionaryFormat, "_givenName", personName.GivenName, stringBuilder);
TryAddKeyValue(StringDictionaryFormat, "_middleName", personName.MiddleName, stringBuilder);
TryAddKeyValue(StringDictionaryFormat, "_familyName", personName.FamilyName, stringBuilder);
TryAddKeyValue(StringDictionaryFormat, "_nameSuffix", personName.NameSuffix, stringBuilder);
TryAddKeyValue(StringDictionaryFormat, "_nickname", personName.Nickname, stringBuilder);

var phoneticRepresentationJson = JsonStringForPersonName(personName.PhoneticRepresentation);
TryAddKeyValue(StringObjectFormat, "_phoneticRepresentation", phoneticRepresentationJson, stringBuilder);
stringBuilder.Append("}");
return stringBuilder.ToString();
}

private static void TryAddKeyValue(string format, string key, string value, System.Text.StringBuilder stringBuilder)
{
if (string.IsNullOrEmpty(value))
return;

stringBuilder.AppendFormat(format, key, value);
}
private static class PInvoke
{
#if UNITY_IOS || UNITY_TVOS || UNITY_VISIONOS
private const string DllName = "__Internal";
#elif UNITY_STANDALONE_OSX
private const string DllName = "MacOSAppleAuthManager";
#endif

[System.Runtime.InteropServices.DllImport(DllName)]
public static extern string AppleAuth_GetPersonNameUsingFormatter(string payload, int style, bool usePhoneticRepresentation);
}
#endif
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Extensions/PersonNameExtensions.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d684b62a264c94bd9adc484681cd2864
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 25
- 0
Assets/AppleAuth/Runtime/IAppleAuthManager.cs View File

@@ -0,0 +1,25 @@
using AppleAuth.Enums;
using AppleAuth.Interfaces;
using System;

namespace AppleAuth
{
public interface IAppleAuthManager
{
[Obsolete("This method is deprecated and will be removed soon. Please provide an empty instance of AppleAuthQuickLoginArgs to QuickLogin.")]
void QuickLogin(Action<ICredential> successCallback, Action<IAppleError> errorCallback);
void QuickLogin(AppleAuthQuickLoginArgs quickLoginArgs, Action<ICredential> successCallback, Action<IAppleError> errorCallback);

[Obsolete("This method is deprecated and will be removed soon. Please provide an instance of AppleAuthLoginArgs to LoginWithAppleId with the LoginOptions instead.")]
void LoginWithAppleId(LoginOptions options, Action<ICredential> successCallback, Action<IAppleError> errorCallback);
void LoginWithAppleId(AppleAuthLoginArgs loginArgs, Action<ICredential> successCallback, Action<IAppleError> errorCallback);

void GetCredentialState(string userId, Action<CredentialState> successCallback, Action<IAppleError> errorCallback);

void SetCredentialsRevokedCallback(Action<string> credentialsRevokedCallback);

void Update();
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/IAppleAuthManager.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 69ff4ac90201d4456bec62466fe2a936
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 8
- 0
Assets/AppleAuth/Runtime/Interfaces.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d8d7552c17e7c42198c7fbcc2b5b115f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 35
- 0
Assets/AppleAuth/Runtime/Interfaces/IAppleError.cs View File

@@ -0,0 +1,35 @@
namespace AppleAuth.Interfaces
{
public interface IAppleError
{
/// <summary>
/// The error code.
/// </summary>
int Code { get; }

/// <summary>
/// A string containing the error domain.
/// </summary>
string Domain { get; }

/// <summary>
/// A string containing the localized description of the error.
/// </summary>
string LocalizedDescription { get; }

/// <summary>
/// An array containing the localized titles of buttons appropriate for displaying in an alert panel.
/// </summary>
string[] LocalizedRecoveryOptions { get; }

/// <summary>
/// A string containing the localized recovery suggestion for the error.
/// </summary>
string LocalizedRecoverySuggestion { get; }

/// <summary>
/// A string containing the localized explanation of the reason for the error.
/// </summary>
string LocalizedFailureReason { get; }
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Interfaces/IAppleError.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c98d39aa7be1d4361b09450c4d2316d9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 42
- 0
Assets/AppleAuth/Runtime/Interfaces/IAppleIDCredential.cs View File

@@ -0,0 +1,42 @@
using AppleAuth.Enums;

namespace AppleAuth.Interfaces
{
public interface IAppleIDCredential : ICredential
{
/// <summary>
/// A JSON Web Token (JWT) that securely communicates information about the user to your app.
/// </summary>
byte[] IdentityToken { get; }

/// <summary>
/// A short-lived token used by your app for proof of authorization when interacting with the app’s server counterpart.
/// </summary>
byte[] AuthorizationCode { get; }

/// <summary>
/// An arbitrary string that your app provided to the request that generated the credential.
/// </summary>
string State { get; }

/// <summary>
/// The contact information the user authorized your app to access.
/// </summary>
string[] AuthorizedScopes { get; }

/// <summary>
/// The user’s name
/// </summary>
IPersonName FullName { get; }

/// <summary>
/// The user’s email address
/// </summary>
string Email { get; }

/// <summary>
/// A value that indicates whether the user appears to be a real person.
/// </summary>
RealUserStatus RealUserStatus { get; }
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Interfaces/IAppleIDCredential.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f3b2ea10c99194e828f0b6d77e5410cf
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 10
- 0
Assets/AppleAuth/Runtime/Interfaces/ICredential.cs View File

@@ -0,0 +1,10 @@
namespace AppleAuth.Interfaces
{
public interface ICredential
{
/// <summary>
/// An identifier associated with the authenticated user
/// </summary>
string User { get; }
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Interfaces/ICredential.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aa092eaf7563444788fec832eda94849
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 11
- 0
Assets/AppleAuth/Runtime/Interfaces/ICredentialStateResponse.cs View File

@@ -0,0 +1,11 @@
using AppleAuth.Enums;

namespace AppleAuth.Interfaces
{
public interface ICredentialStateResponse
{
bool Success { get; }
CredentialState CredentialState { get; }
IAppleError Error { get; }
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Interfaces/ICredentialStateResponse.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ad3121cb886334d909ad3942666cd396
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 10
- 0
Assets/AppleAuth/Runtime/Interfaces/ILoginWithAppleIdResponse.cs View File

@@ -0,0 +1,10 @@
namespace AppleAuth.Interfaces
{
public interface ILoginWithAppleIdResponse
{
bool Success { get; }
IAppleError Error { get; }
IAppleIDCredential AppleIDCredential { get; }
IPasswordCredential PasswordCredential { get; }
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Interfaces/ILoginWithAppleIdResponse.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0394fee0ab58b44c4ab2b93c2a81f061
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 7
- 0
Assets/AppleAuth/Runtime/Interfaces/IPasswordCredential.cs View File

@@ -0,0 +1,7 @@
namespace AppleAuth.Interfaces
{
public interface IPasswordCredential : ICredential
{
string Password { get; }
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Interfaces/IPasswordCredential.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 767f76f82bb4a4f8e83678a31afccef2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 8
- 0
Assets/AppleAuth/Runtime/Interfaces/IPayloadDeserializer.cs View File

@@ -0,0 +1,8 @@
namespace AppleAuth.Interfaces
{
public interface IPayloadDeserializer
{
ICredentialStateResponse DeserializeCredentialStateResponse(string payload);
ILoginWithAppleIdResponse DeserializeLoginWithAppleIdResponse(string payload);
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Interfaces/IPayloadDeserializer.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c374a2fc1b8024d1b8aa7755908d3777
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 43
- 0
Assets/AppleAuth/Runtime/Interfaces/IPersonName.cs View File

@@ -0,0 +1,43 @@
namespace AppleAuth.Interfaces
{
/// <summary>
/// PersonNameComponents
/// </summary>
public interface IPersonName
{
/// <summary>
/// The portion of a name’s full form of address that precedes the name itself (for example, “Dr.,” “Mr.,” “Ms.”)
/// </summary>
string NamePrefix { get; }

/// <summary>
/// Name bestowed upon an individual to differentiate them from other members of a group that share a family name (for example, “Johnathan”)
/// </summary>
string GivenName { get; }

/// <summary>
/// Secondary name bestowed upon an individual to differentiate them from others that have the same given name (for example, “Maple”)
/// </summary>
string MiddleName { get; }

/// <summary>
/// Name bestowed upon an individual to denote membership in a group or family. (for example, “Appleseed”)
/// </summary>
string FamilyName { get; }

/// <summary>
/// The portion of a name’s full form of address that follows the name itself (for example, “Esq.,” “Jr.,” “Ph.D.”)
/// </summary>
string NameSuffix { get; }

/// <summary>
/// Name substituted for the purposes of familiarity (for example, "Johnny")
/// </summary>
string Nickname { get; }

/// <summary>
/// The phonetic representation name components of the receiver
/// </summary>
IPersonName PhoneticRepresentation { get; }
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Interfaces/IPersonName.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a7127bb6510c746c5831ca01efa61a71
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 8
- 0
Assets/AppleAuth/Runtime/Native.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: de22a4c26e5ad461dacc44a1d5ed99f1
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 41
- 0
Assets/AppleAuth/Runtime/Native/AppleError.cs View File

@@ -0,0 +1,41 @@
using AppleAuth.Interfaces;
using System;
using UnityEngine;

namespace AppleAuth.Native
{
[Serializable]
internal class AppleError : IAppleError, ISerializationCallbackReceiver
{
public int _code = 0;
public string _domain = null;
public string _localizedDescription = null;
public string[] _localizedRecoveryOptions = null;
public string _localizedRecoverySuggestion = null;
public string _localizedFailureReason = null;
public int Code { get { return this._code; } }
public string Domain { get { return this._domain; } }
public string LocalizedDescription { get { return this._localizedDescription; } }
public string[] LocalizedRecoveryOptions { get { return this._localizedRecoveryOptions; } }
public string LocalizedRecoverySuggestion { get { return this._localizedRecoverySuggestion; } }
public string LocalizedFailureReason { get { return this._localizedFailureReason; } }
public void OnBeforeSerialize() { }

public void OnAfterDeserialize()
{
SerializationTools.FixSerializationForString(ref this._domain);
SerializationTools.FixSerializationForString(ref this._localizedDescription);
SerializationTools.FixSerializationForString(ref this._localizedRecoverySuggestion);
SerializationTools.FixSerializationForString(ref this._localizedFailureReason);
SerializationTools.FixSerializationForArray(ref this._localizedRecoveryOptions);
}

public override string ToString()
{
return $"Domain={_domain} Code={_code} Description={_localizedDescription}";
}
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Native/AppleError.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 66599b6010f2b4ddf968ec5828018bf5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 51
- 0
Assets/AppleAuth/Runtime/Native/AppleIDCredential.cs View File

@@ -0,0 +1,51 @@
using AppleAuth.Enums;
using AppleAuth.Interfaces;
using System;
using UnityEngine;

namespace AppleAuth.Native
{
[Serializable]
internal class AppleIDCredential : IAppleIDCredential, ISerializationCallbackReceiver
{
public string _base64IdentityToken = null;
public string _base64AuthorizationCode = null;
public string _state = null;
public string _user = null;
public string[] _authorizedScopes = null;
public bool _hasFullName = false;
public FullPersonName _fullName = null;
public string _email = null;
public int _realUserStatus = 0;

private byte[] _identityToken;
private byte[] _authorizationCode;

public byte[] IdentityToken { get { return this._identityToken; } }
public byte[] AuthorizationCode { get { return this._authorizationCode; } }
public string State { get { return this._state; } }
public string User { get { return this._user; } }
public string[] AuthorizedScopes { get { return this._authorizedScopes; } }
public IPersonName FullName { get { return this._fullName; } }
public string Email { get { return this._email; } }
public RealUserStatus RealUserStatus { get { return (RealUserStatus) this._realUserStatus; } }
public void OnBeforeSerialize() { }

public void OnAfterDeserialize()
{
SerializationTools.FixSerializationForString(ref this._base64IdentityToken);
SerializationTools.FixSerializationForString(ref this._base64AuthorizationCode);
SerializationTools.FixSerializationForString(ref this._state);
SerializationTools.FixSerializationForString(ref this._user);
SerializationTools.FixSerializationForString(ref this._email);
SerializationTools.FixSerializationForArray(ref this._authorizedScopes);
SerializationTools.FixSerializationForObject(ref this._fullName, this._hasFullName);

this._identityToken = SerializationTools.GetBytesFromBase64String(this._base64IdentityToken, "_identityToken");
this._authorizationCode = SerializationTools.GetBytesFromBase64String(this._base64AuthorizationCode, "_authorizationCode");
}
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Native/AppleIDCredential.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 15941ca67e34e497c9d07d4fcd0a310f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 29
- 0
Assets/AppleAuth/Runtime/Native/CredentialStateResponse.cs View File

@@ -0,0 +1,29 @@
using AppleAuth.Enums;
using AppleAuth.Interfaces;
using System;
using UnityEngine;

namespace AppleAuth.Native
{
[Serializable]
internal class CredentialStateResponse : ICredentialStateResponse, ISerializationCallbackReceiver
{
public bool _success = false;
public bool _hasCredentialState = false;
public bool _hasError = false;
public int _credentialState = 0;
public AppleError _error = null;

public bool Success { get { return this._success; } }
public CredentialState CredentialState { get { return (CredentialState) this._credentialState; } }
public IAppleError Error { get { return this._error; } }
public void OnBeforeSerialize() { }

public void OnAfterDeserialize()
{
SerializationTools.FixSerializationForObject(ref this._credentialState, this._hasCredentialState);
SerializationTools.FixSerializationForObject(ref this._error, this._hasError);
}
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Native/CredentialStateResponse.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 24dd6e2297c95497b94116cd3cb73a1d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 21
- 0
Assets/AppleAuth/Runtime/Native/FullPersonName.cs View File

@@ -0,0 +1,21 @@
using AppleAuth.Interfaces;
using System;

namespace AppleAuth.Native
{
[Serializable]
internal class FullPersonName : PersonName, IPersonName
{
public bool _hasPhoneticRepresentation = false;
public PersonName _phoneticRepresentation = null;

public new IPersonName PhoneticRepresentation { get { return _phoneticRepresentation; } }

public override void OnAfterDeserialize()
{
base.OnAfterDeserialize();
SerializationTools.FixSerializationForObject(ref this._phoneticRepresentation, this._hasPhoneticRepresentation);
}
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Native/FullPersonName.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 23f96edff86ab4667b8690d7d5127edc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 32
- 0
Assets/AppleAuth/Runtime/Native/LoginWithAppleIdResponse.cs View File

@@ -0,0 +1,32 @@
using AppleAuth.Interfaces;
using System;
using UnityEngine;

namespace AppleAuth.Native
{
[Serializable]
internal class LoginWithAppleIdResponse : ILoginWithAppleIdResponse, ISerializationCallbackReceiver
{
public bool _success = false;
public bool _hasAppleIdCredential = false;
public bool _hasPasswordCredential = false;
public bool _hasError = false;
public AppleIDCredential _appleIdCredential = null;
public PasswordCredential _passwordCredential = null;
public AppleError _error = null;

public bool Success { get { return this._success; } }
public IAppleError Error { get { return this._error; } }
public IAppleIDCredential AppleIDCredential { get { return this._appleIdCredential; } }
public IPasswordCredential PasswordCredential { get { return this._passwordCredential; } }
public void OnBeforeSerialize() { }

public void OnAfterDeserialize()
{
SerializationTools.FixSerializationForObject(ref this._error, this._hasError);
SerializationTools.FixSerializationForObject(ref this._appleIdCredential, this._hasAppleIdCredential);
SerializationTools.FixSerializationForObject(ref this._passwordCredential, this._hasPasswordCredential);
}
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Native/LoginWithAppleIdResponse.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 88fccfe9390ad446fb450f04f59a6729
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 24
- 0
Assets/AppleAuth/Runtime/Native/PasswordCredential.cs View File

@@ -0,0 +1,24 @@
using AppleAuth.Interfaces;
using System;
using UnityEngine;

namespace AppleAuth.Native
{
[Serializable]
internal class PasswordCredential : IPasswordCredential, ISerializationCallbackReceiver
{
public string _user = null;
public string _password = null;
public string User { get { return this._user; } }
public string Password { get { return this._password; } }
public void OnBeforeSerialize() { }

public void OnAfterDeserialize()
{
SerializationTools.FixSerializationForString(ref this._user);
SerializationTools.FixSerializationForString(ref this._password);
}
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Native/PasswordCredential.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b38027d09c1a04617b50cc7fa5e01310
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 18
- 0
Assets/AppleAuth/Runtime/Native/PayloadDeserializer.cs View File

@@ -0,0 +1,18 @@
using AppleAuth.Interfaces;
using UnityEngine;

namespace AppleAuth.Native
{
public class PayloadDeserializer : IPayloadDeserializer
{
public ICredentialStateResponse DeserializeCredentialStateResponse(string payload)
{
return JsonUtility.FromJson<CredentialStateResponse>(payload);
}

public ILoginWithAppleIdResponse DeserializeLoginWithAppleIdResponse(string payload)
{
return JsonUtility.FromJson<LoginWithAppleIdResponse>(payload);
}
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Native/PayloadDeserializer.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 06a2a38e685214c3295204c9136940a8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 37
- 0
Assets/AppleAuth/Runtime/Native/PersonName.cs View File

@@ -0,0 +1,37 @@
using System;
using AppleAuth.Interfaces;
using UnityEngine;

namespace AppleAuth.Native
{
[Serializable]
internal class PersonName : IPersonName, ISerializationCallbackReceiver
{
public string _namePrefix = null;
public string _givenName = null;
public string _middleName = null;
public string _familyName = null;
public string _nameSuffix = null;
public string _nickname = null;
public string NamePrefix { get { return _namePrefix; } }
public string GivenName { get { return _givenName; } }
public string MiddleName { get { return _middleName; } }
public string FamilyName { get { return _familyName; } }
public string NameSuffix { get { return _nameSuffix; } }
public string Nickname { get { return _nickname; } }
public IPersonName PhoneticRepresentation { get { return null; } }
public void OnBeforeSerialize() { }

public virtual void OnAfterDeserialize()
{
SerializationTools.FixSerializationForString(ref this._namePrefix);
SerializationTools.FixSerializationForString(ref this._givenName);
SerializationTools.FixSerializationForString(ref this._middleName);
SerializationTools.FixSerializationForString(ref this._familyName);
SerializationTools.FixSerializationForString(ref this._nameSuffix);
SerializationTools.FixSerializationForString(ref this._nickname);
}
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Native/PersonName.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 0d959c3605b194eac93e208fa33002c6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 47
- 0
Assets/AppleAuth/Runtime/Native/SerializationTools.cs View File

@@ -0,0 +1,47 @@
using System;

namespace AppleAuth.Native
{
internal static class SerializationTools
{
internal static void FixSerializationForString(ref string originalString)
{
if (string.IsNullOrEmpty(originalString))
originalString = null;
}

internal static void FixSerializationForArray<T>(ref T[] originalArray)
{
if (originalArray != null && originalArray.Length == 0)
originalArray = null;
}

internal static void FixSerializationForObject<T>(ref T originalObject, bool hasOriginalObject)
{
if (!hasOriginalObject)
originalObject = default(T);
}

internal static byte[] GetBytesFromBase64String(string base64String, string fieldName)
{
if (base64String == null)
{
return null;
}

var returnedBytes = default(byte[]);
try
{
returnedBytes = Convert.FromBase64String(base64String);
}
catch (Exception exception)
{
Console.WriteLine("Received exception while deserializing byte array for " + fieldName);
Console.WriteLine("Exception: " + exception);
returnedBytes = null;
}

return returnedBytes;
}
}
}

+ 11
- 0
Assets/AppleAuth/Runtime/Native/SerializationTools.cs.meta View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c90c4bb9b4fc94c32adf26b8cbf97cb6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

+ 8
- 0
Assets/AppleAuth/Runtime/Native/iOS.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 687423b5bd2394931962eb42f71aba99
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 55
- 0
Assets/AppleAuth/Runtime/Native/iOS/AppleAuthManager.h View File

@@ -0,0 +1,55 @@
//
// MIT License
//
// Copyright (c) 2019-2020 Daniel Lupiañez Casares
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

typedef NS_OPTIONS(int, AppleAuthManagerLoginOptions) {
AppleAuthManagerIncludeName = 1 << 0,
AppleAuthManagerIncludeEmail = 1 << 1,
};

typedef void (*NativeMessageHandlerDelegate)(uint requestId, const char* payload);

@interface AppleAuthManager : NSObject

+ (instancetype) sharedManager;

- (void) quickLogin:(uint)requestId withNonce:(NSString *)nonce andState:(NSString *)state;
- (void) loginWithAppleId:(uint)requestId withOptions:(AppleAuthManagerLoginOptions)options nonce:(NSString *)nonce andState:(NSString *)state;
- (void) getCredentialStateForUser:(NSString *)userId withRequestId:(uint)requestId;
- (void) registerCredentialsRevokedCallbackForRequestId:(uint)requestId;

@end

bool AppleAuth_IsCurrentPlatformSupported(void);
void AppleAuth_SetupNativeMessageHandlerCallback(NativeMessageHandlerDelegate callback);
void AppleAuth_GetCredentialState(uint requestId, const char* userId);
void AppleAuth_LoginWithAppleId(uint requestId, int options, const char* _Nullable nonceCStr, const char* _Nullable stateCStr);
void AppleAuth_QuickLogin(uint requestId, const char* _Nullable nonceCStr, const char* _Nullable stateCStr);
void AppleAuth_RegisterCredentialsRevokedCallbackId(uint requestId);
void AppleAuth_LogMessage(const char* _Nullable messageCStr);

NS_ASSUME_NONNULL_END

+ 114
- 0
Assets/AppleAuth/Runtime/Native/iOS/AppleAuthManager.h.meta View File

@@ -0,0 +1,114 @@
fileFormatVersion: 2
guid: 06c81bcee738c4a2dbc125bd0bfc9929
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude Linux: 1
Exclude Linux64: 1
Exclude LinuxUniversal: 1
Exclude OSXUniversal: 1
Exclude VisionOS: 0
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 0
Exclude tvOS: 0
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux
second:
enabled: 0
settings:
CPU: x86
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: LinuxUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
VisionOS: VisionOS
second:
enabled: 1
settings: {}
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
- first:
tvOS: tvOS
second:
enabled: 1
settings:
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

+ 393
- 0
Assets/AppleAuth/Runtime/Native/iOS/AppleAuthManager.m View File

@@ -0,0 +1,393 @@
//
// MIT License
//
// Copyright (c) 2019-2020 Daniel Lupiañez Casares
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#import "AppleAuthManager.h"
#import "AppleAuthSerializer.h"

#pragma mark - AppleAuthManager Implementation

// IOS/TVOS 13.0 | MACOS 10.15 | VISIONOS 1.0
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 || __TV_OS_VERSION_MAX_ALLOWED >= 130000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500 || __VISION_OS_VERSION_MAX_ALLOWED >= 10000
#define AUTHENTICATION_SERVICES_AVAILABLE true
#import <AuthenticationServices/AuthenticationServices.h>
#endif

@interface AppleAuthManager ()
@property (nonatomic, assign) NativeMessageHandlerDelegate mainCallback;
@property (nonatomic, weak) NSOperationQueue *callingOperationQueue;

- (void) sendNativeMessageForDictionary:(NSDictionary *)payloadDictionary forRequestId:(uint)requestId;
- (void) sendNativeMessageForString:(NSString *)payloadString forRequestId:(uint)requestId;
- (NSError *)internalErrorWithCode:(NSInteger)code andMessage:(NSString *)message;
- (void) sendsCredentialStatusInternalErrorWithCode:(NSInteger)code andMessage:(NSString *)message forRequestWithId:(uint)requestId;
- (void) sendsLoginResponseInternalErrorWithCode:(NSInteger)code andMessage:(NSString *)message forRequestWithId:(uint)requestId;
@end

#if AUTHENTICATION_SERVICES_AVAILABLE
API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0), visionos(1.0))
@interface AppleAuthManager () <ASAuthorizationControllerDelegate, ASAuthorizationControllerPresentationContextProviding>
@property (nonatomic, strong) ASAuthorizationAppleIDProvider *appleIdProvider;
@property (nonatomic, strong) ASAuthorizationPasswordProvider *passwordProvider;
@property (nonatomic, strong) NSObject *credentialsRevokedObserver;
@property (nonatomic, strong) NSMutableDictionary<NSValue *, NSNumber *> *authorizationsInProgress;
@end
#endif

@implementation AppleAuthManager

+ (instancetype) sharedManager
{
static AppleAuthManager *_defaultManager = nil;
static dispatch_once_t defaultManagerInitialization;
dispatch_once(&defaultManagerInitialization, ^{
_defaultManager = [[AppleAuthManager alloc] init];
});
return _defaultManager;
}

- (instancetype) init
{
self = [super init];
if (self)
{
#if AUTHENTICATION_SERVICES_AVAILABLE
if (@available(iOS 13.0, tvOS 13.0, macOS 10.15, visionOS 1.0, *))
{
_appleIdProvider = [[ASAuthorizationAppleIDProvider alloc] init];
_passwordProvider = [[ASAuthorizationPasswordProvider alloc] init];
_authorizationsInProgress = [NSMutableDictionary dictionary];
}
#endif
}
return self;
}

#pragma mark Public methods

- (void) quickLogin:(uint)requestId withNonce:(NSString *)nonce andState:(NSString *)state
{
#if AUTHENTICATION_SERVICES_AVAILABLE
if (@available(iOS 13.0, tvOS 13.0, macOS 10.15, visionOS 1.0, *))
{
ASAuthorizationAppleIDRequest *appleIDRequest = [[self appleIdProvider] createRequest];
[appleIDRequest setNonce:nonce];
[appleIDRequest setState:state];

ASAuthorizationPasswordRequest *keychainRequest = [[self passwordProvider] createRequest];

ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[appleIDRequest, keychainRequest]];
[self performAuthorizationRequestsForController:authorizationController withRequestId:requestId];
}
else
{
[self sendsLoginResponseInternalErrorWithCode:-100
andMessage:@"Native AppleAuth is only available from iOS 13.0"
forRequestWithId:requestId];
}
#else
[self sendsLoginResponseInternalErrorWithCode:-100
andMessage:@"Native AppleAuth is only available from iOS 13.0"
forRequestWithId:requestId];
#endif
}

- (void) loginWithAppleId:(uint)requestId withOptions:(AppleAuthManagerLoginOptions)options nonce:(NSString *)nonce andState:(NSString *)state
{
#if AUTHENTICATION_SERVICES_AVAILABLE
if (@available(iOS 13.0, tvOS 13.0, macOS 10.15, visionOS 1.0, *))
{
ASAuthorizationAppleIDRequest *request = [[self appleIdProvider] createRequest];
NSMutableArray *scopes = [NSMutableArray array];

if (options & AppleAuthManagerIncludeName)
[scopes addObject:ASAuthorizationScopeFullName];

if (options & AppleAuthManagerIncludeEmail)
[scopes addObject:ASAuthorizationScopeEmail];

[request setRequestedScopes:[scopes copy]];
[request setNonce:nonce];
[request setState:state];

ASAuthorizationController *authorizationController = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
[self performAuthorizationRequestsForController:authorizationController withRequestId:requestId];
}
else
{
[self sendsLoginResponseInternalErrorWithCode:-100
andMessage:@"Native AppleAuth is only available from iOS 13.0"
forRequestWithId:requestId];
}
#else
[self sendsLoginResponseInternalErrorWithCode:-100
andMessage:@"Native AppleAuth is only available from iOS 13.0"
forRequestWithId:requestId];
#endif
}


- (void) getCredentialStateForUser:(NSString *)userId withRequestId:(uint)requestId
{
#if AUTHENTICATION_SERVICES_AVAILABLE
if (@available(iOS 13.0, tvOS 13.0, macOS 10.15, visionOS 1.0, *))
{
[[self appleIdProvider] getCredentialStateForUserID:userId completion:^(ASAuthorizationAppleIDProviderCredentialState credentialState, NSError * _Nullable error) {
NSNumber *credentialStateNumber = nil;
NSDictionary *errorDictionary = nil;

if (error)
errorDictionary = [AppleAuthSerializer dictionaryForNSError:error];
else
credentialStateNumber = @(credentialState);

NSDictionary *responseDictionary = [AppleAuthSerializer credentialResponseDictionaryForCredentialState:credentialStateNumber
errorDictionary:errorDictionary];

[self sendNativeMessageForDictionary:responseDictionary forRequestId:requestId];
}];
}
else
{
[self sendsCredentialStatusInternalErrorWithCode:-100
andMessage:@"Native AppleAuth is only available from iOS 13.0"
forRequestWithId:requestId];
}
#else
[self sendsCredentialStatusInternalErrorWithCode:-100
andMessage:@"Native AppleAuth is only available from iOS 13.0"
forRequestWithId:requestId];
#endif
}

- (void) registerCredentialsRevokedCallbackForRequestId:(uint)requestId
{
#if AUTHENTICATION_SERVICES_AVAILABLE
if (@available(iOS 13.0, tvOS 13.0, macOS 10.15, visionOS 1.0, *))
{
if ([self credentialsRevokedObserver])
{
[[NSNotificationCenter defaultCenter] removeObserver:[self credentialsRevokedObserver]];
[self setCredentialsRevokedObserver:nil];
}

if (requestId != 0)
{
NSObject *observer = [[NSNotificationCenter defaultCenter] addObserverForName:ASAuthorizationAppleIDProviderCredentialRevokedNotification
object:nil
queue:nil
usingBlock:^(NSNotification * _Nonnull note) {
[self sendNativeMessageForString:@"Credentials Revoked" forRequestId:requestId];
}];
[self setCredentialsRevokedObserver:observer];
}
}
#endif
}

#pragma mark Private methods

- (void) sendNativeMessageForDictionary:(NSDictionary *)payloadDictionary forRequestId:(uint)requestId
{
NSError *error = nil;
NSData *payloadData = [NSJSONSerialization dataWithJSONObject:payloadDictionary options:0 error:&error];
NSString *payloadString = error ? [NSString stringWithFormat:@"Serialization error %@", [error localizedDescription]] : [[NSString alloc] initWithData:payloadData encoding:NSUTF8StringEncoding];
[self sendNativeMessageForString:payloadString forRequestId:requestId];
}

- (void) sendNativeMessageForString:(NSString *)payloadString forRequestId:(uint)requestId
{
if ([self mainCallback] == NULL)
return;

if ([self callingOperationQueue])
{
[[self callingOperationQueue] addOperationWithBlock:^{
[self mainCallback](requestId, [payloadString UTF8String]);
}];
}
else
{
[self mainCallback](requestId, [payloadString UTF8String]);
}
}

- (NSError *)internalErrorWithCode:(NSInteger)code andMessage:(NSString *)message
{
return [NSError errorWithDomain:@"com.unity.AppleAuth"
code:code
userInfo:@{NSLocalizedDescriptionKey : message}];
}

- (void) sendsCredentialStatusInternalErrorWithCode:(NSInteger)code andMessage:(NSString *)message forRequestWithId:(uint)requestId
{
NSError *customError = [self internalErrorWithCode:code andMessage:message];
NSDictionary *customErrorDictionary = [AppleAuthSerializer dictionaryForNSError:customError];
NSDictionary *responseDictionary = [AppleAuthSerializer credentialResponseDictionaryForCredentialState:nil
errorDictionary:customErrorDictionary];

[self sendNativeMessageForDictionary:responseDictionary forRequestId:requestId];
}

- (void) sendsLoginResponseInternalErrorWithCode:(NSInteger)code andMessage:(NSString *)message forRequestWithId:(uint)requestId
{
NSError *customError = [self internalErrorWithCode:code andMessage:message];
NSDictionary *customErrorDictionary = [AppleAuthSerializer dictionaryForNSError:customError];
NSDictionary *responseDictionary = [AppleAuthSerializer loginResponseDictionaryForAppleIdCredentialDictionary:nil
passwordCredentialDictionary:nil
errorDictionary:customErrorDictionary];

[self sendNativeMessageForDictionary:responseDictionary forRequestId:requestId];
}

#if AUTHENTICATION_SERVICES_AVAILABLE

- (void) performAuthorizationRequestsForController:(ASAuthorizationController *)authorizationController withRequestId:(uint)requestId
API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0), visionos(1.0))
{
NSValue *authControllerAsKey = [NSValue valueWithNonretainedObject:authorizationController];
[[self authorizationsInProgress] setObject:@(requestId) forKey:authControllerAsKey];

[authorizationController setDelegate:self];
[authorizationController setPresentationContextProvider:self];
[authorizationController performRequests];
}

#pragma mark ASAuthorizationControllerDelegate protocol implementation

- (void) authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization
API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0), visionos(1.0))
{
NSValue *authControllerAsKey = [NSValue valueWithNonretainedObject:controller];
NSNumber *requestIdNumber = [[self authorizationsInProgress] objectForKey:authControllerAsKey];
if (requestIdNumber)
{
NSDictionary *appleIdCredentialDictionary = nil;
NSDictionary *passwordCredentialDictionary = nil;
if ([[authorization credential] isKindOfClass:[ASAuthorizationAppleIDCredential class]])
{
appleIdCredentialDictionary = [AppleAuthSerializer dictionaryForASAuthorizationAppleIDCredential:(ASAuthorizationAppleIDCredential *)[authorization credential]];
}
else if ([[authorization credential] isKindOfClass:[ASPasswordCredential class]])
{
passwordCredentialDictionary = [AppleAuthSerializer dictionaryForASPasswordCredential:(ASPasswordCredential *)[authorization credential]];
}

NSDictionary *responseDictionary = [AppleAuthSerializer loginResponseDictionaryForAppleIdCredentialDictionary:appleIdCredentialDictionary
passwordCredentialDictionary:passwordCredentialDictionary
errorDictionary:nil];

[self sendNativeMessageForDictionary:responseDictionary forRequestId:[requestIdNumber unsignedIntValue]];

[[self authorizationsInProgress] removeObjectForKey:authControllerAsKey];
}
}

- (void) authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error
API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0), visionos(1.0))
{
NSValue *authControllerAsKey = [NSValue valueWithNonretainedObject:controller];
NSNumber *requestIdNumber = [[self authorizationsInProgress] objectForKey:authControllerAsKey];
if (requestIdNumber)
{
NSDictionary *errorDictionary = [AppleAuthSerializer dictionaryForNSError:error];
NSDictionary *responseDictionary = [AppleAuthSerializer loginResponseDictionaryForAppleIdCredentialDictionary:nil
passwordCredentialDictionary:nil
errorDictionary:errorDictionary];

[self sendNativeMessageForDictionary:responseDictionary forRequestId:[requestIdNumber unsignedIntValue]];

[[self authorizationsInProgress] removeObjectForKey:authControllerAsKey];
}
}

#pragma mark ASAuthorizationControllerPresentationContextProviding protocol implementation

- (ASPresentationAnchor) presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller
API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0), visionos(1.0))
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 || __TV_OS_VERSION_MAX_ALLOWED >= 130000 || __VISION_OS_VERSION_MAX_ALLOWED >= 10000
return [[[UIApplication sharedApplication] delegate] window];
#elif __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
return [[NSApplication sharedApplication] mainWindow];
#else
return nil;
#endif
}

#endif

@end

#pragma mark - Native C Calls

bool AppleAuth_IsCurrentPlatformSupported(void)
{
if (@available(iOS 13.0, tvOS 13.0, macOS 10.15, visionOS 1.0, *))
{
return true;
}
else
{
return false;
}
}

void AppleAuth_SetupNativeMessageHandlerCallback(NativeMessageHandlerDelegate callback)
{
[[AppleAuthManager sharedManager] setMainCallback:callback];
[[AppleAuthManager sharedManager] setCallingOperationQueue: [NSOperationQueue currentQueue]];
}

void AppleAuth_GetCredentialState(uint requestId, const char* userId)
{
[[AppleAuthManager sharedManager] getCredentialStateForUser:[NSString stringWithUTF8String:userId] withRequestId:requestId];
}

void AppleAuth_LoginWithAppleId(uint requestId, int options, const char* _Nullable nonceCStr, const char* _Nullable stateCStr)
{
NSString *nonce = nonceCStr != NULL ? [NSString stringWithUTF8String:nonceCStr] : nil;
NSString *state = stateCStr != NULL ? [NSString stringWithUTF8String:stateCStr] : nil;
[[AppleAuthManager sharedManager] loginWithAppleId:requestId withOptions:options nonce:nonce andState:state];
}

void AppleAuth_QuickLogin(uint requestId, const char* _Nullable nonceCStr, const char* _Nullable stateCStr)
{
NSString *nonce = nonceCStr != NULL ? [NSString stringWithUTF8String:nonceCStr] : nil;
NSString *state = stateCStr != NULL ? [NSString stringWithUTF8String:stateCStr] : nil;
[[AppleAuthManager sharedManager] quickLogin:requestId withNonce:nonce andState:state];
}

void AppleAuth_RegisterCredentialsRevokedCallbackId(uint requestId)
{
[[AppleAuthManager sharedManager] registerCredentialsRevokedCallbackForRequestId:requestId];
}

void AppleAuth_LogMessage(const char* _Nullable messageCStr)
{
NSString *message = messageCStr != NULL ? [NSString stringWithUTF8String:messageCStr] : nil;
NSLog(@"%@", message);
}

+ 105
- 0
Assets/AppleAuth/Runtime/Native/iOS/AppleAuthManager.m.meta View File

@@ -0,0 +1,105 @@
fileFormatVersion: 2
guid: 61f5e8cab65e74724a8d16c25b068fef
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude Linux: 1
Exclude Linux64: 1
Exclude LinuxUniversal: 1
Exclude OSXUniversal: 1
Exclude VisionOS: 0
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 0
Exclude tvOS: 0
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux
second:
enabled: 0
settings:
CPU: x86
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
VisionOS: VisionOS
second:
enabled: 1
settings: {}
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:

+ 62
- 0
Assets/AppleAuth/Runtime/Native/iOS/AppleAuthSerializer.h View File

@@ -0,0 +1,62 @@
//
// MIT License
//
// Copyright (c) 2019 Daniel Lupiañez Casares
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#import <Foundation/Foundation.h>

// IOS/TVOS 13.0 | MACOS 10.15 | VISIONOS 1.0
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 || __TV_OS_VERSION_MAX_ALLOWED >= 130000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500 || __VISION_OS_VERSION_MAX_ALLOWED >= 10000
#import <AuthenticationServices/AuthenticationServices.h>
#endif

@interface AppleAuthSerializer : NSObject

+ (NSDictionary * _Nullable) dictionaryForNSError:(NSError * _Nullable)error;

+ (NSDictionary * _Nullable) credentialResponseDictionaryForCredentialState:(NSNumber * _Nullable)credentialStateNumber
errorDictionary:(NSDictionary * _Nullable)errorDictionary;

+ (NSDictionary * _Nullable) loginResponseDictionaryForAppleIdCredentialDictionary:(NSDictionary * _Nullable)appleIdCredentialDictionary
passwordCredentialDictionary:(NSDictionary * _Nullable)passwordCredentialDictionary
errorDictionary:(NSDictionary * _Nullable)errorDictionary;

// IOS/TVOS 9.0 | MACOS 10.11 | VISIONOS 1.0
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 || __TV_OS_VERSION_MAX_ALLOWED >= 90000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 || __VISION_OS_VERSION_MAX_ALLOWED >= 10000

+ (NSDictionary * _Nullable) dictionaryForNSPersonNameComponents:(NSPersonNameComponents * _Nullable)nameComponents
API_AVAILABLE(ios(9.0), macos(10.11), tvos(9.0), watchos(2.0), visionos(1.0));

#endif

// IOS/TVOS 13.0 | MACOS 10.15 | VISIONOS 1.0
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 || __TV_OS_VERSION_MAX_ALLOWED >= 130000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500 || __VISION_OS_VERSION_MAX_ALLOWED >= 10000

+ (NSDictionary * _Nullable) dictionaryForASAuthorizationAppleIDCredential:(ASAuthorizationAppleIDCredential * _Nullable)appleIDCredential
API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0), visionos(1.0));

+ (NSDictionary * _Nullable) dictionaryForASPasswordCredential:(ASPasswordCredential * _Nullable)passwordCredential
API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0), visionos(1.0));

#endif

@end

+ 114
- 0
Assets/AppleAuth/Runtime/Native/iOS/AppleAuthSerializer.h.meta View File

@@ -0,0 +1,114 @@
fileFormatVersion: 2
guid: 7a96c2b731b5146bb9317c8ea15774ec
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude Linux: 1
Exclude Linux64: 1
Exclude LinuxUniversal: 1
Exclude OSXUniversal: 1
Exclude VisionOS: 0
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 0
Exclude tvOS: 0
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux
second:
enabled: 0
settings:
CPU: x86
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: LinuxUniversal
second:
enabled: 0
settings:
CPU: None
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
VisionOS: VisionOS
second:
enabled: 1
settings: {}
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
- first:
tvOS: tvOS
second:
enabled: 1
settings:
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

+ 151
- 0
Assets/AppleAuth/Runtime/Native/iOS/AppleAuthSerializer.m View File

@@ -0,0 +1,151 @@
//
// MIT License
//
// Copyright (c) 2019 Daniel Lupiañez Casares
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#import "AppleAuthSerializer.h"

@implementation AppleAuthSerializer

+ (NSDictionary *) dictionaryForNSError:(NSError *)error
{
if (!error)
return nil;
NSMutableDictionary *result = [NSMutableDictionary dictionary];
[result setValue:@([error code]) forKey:@"_code"];
[result setValue:[error domain] forKey:@"_domain"];
[result setValue:[error localizedDescription] forKey:@"_localizedDescription"];
[result setValue:[error localizedRecoveryOptions] forKey:@"_localizedRecoveryOptions"];
[result setValue:[error localizedRecoverySuggestion] forKey:@"_localizedRecoverySuggestion"];
[result setValue:[error localizedFailureReason] forKey:@"_localizedFailureReason"];
return [result copy];
}

+ (NSDictionary *) credentialResponseDictionaryForCredentialState:(NSNumber *)credentialStateNumber
errorDictionary:(NSDictionary *)errorDictionary
{
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
[result setValue:@(errorDictionary == nil) forKey:@"_success"];
[result setValue:@(credentialStateNumber != nil) forKey:@"_hasCredentialState"];
[result setValue:@(errorDictionary != nil) forKey:@"_hasError"];
[result setValue:credentialStateNumber forKey:@"_credentialState"];
[result setValue:errorDictionary forKey:@"_error"];
return [result copy];
}

+ (NSDictionary *) loginResponseDictionaryForAppleIdCredentialDictionary:(NSDictionary *)appleIdCredentialDictionary
passwordCredentialDictionary:(NSDictionary *)passwordCredentialDictionary
errorDictionary:(NSDictionary *)errorDictionary
{
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
[result setValue:@(errorDictionary == nil) forKey:@"_success"];
[result setValue:@(appleIdCredentialDictionary != nil) forKey:@"_hasAppleIdCredential"];
[result setValue:@(passwordCredentialDictionary != nil) forKey:@"_hasPasswordCredential"];
[result setValue:@(errorDictionary != nil) forKey:@"_hasError"];
[result setValue:appleIdCredentialDictionary forKey:@"_appleIdCredential"];
[result setValue:passwordCredentialDictionary forKey:@"_passwordCredential"];
[result setValue:errorDictionary forKey:@"_error"];
return [result copy];
}

// IOS/TVOS 9.0 | MACOS 10.11 | VISIONOS 1.0
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 || __TV_OS_VERSION_MAX_ALLOWED >= 90000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101100 || __VISION_OS_VERSION_MAX_ALLOWED >= 10000

+ (NSDictionary *) dictionaryForNSPersonNameComponents:(NSPersonNameComponents *)nameComponents
{
if (!nameComponents)
return nil;
// Sometimes, when not requesting a name in the ASAuthorizationAppleIDRequest scopes,
// Apple will just send an empty NSPersonNameComponents instance...
// This should be treated as a nil person name components
if ([nameComponents namePrefix] == nil &&
[nameComponents givenName] == nil &&
[nameComponents middleName] == nil &&
[nameComponents familyName] == nil &&
[nameComponents nameSuffix] == nil &&
[nameComponents nickname] == nil &&
[nameComponents phoneticRepresentation] == nil)
return nil;
NSMutableDictionary *result = [NSMutableDictionary dictionary];
[result setValue:[nameComponents namePrefix] forKey:@"_namePrefix"];
[result setValue:[nameComponents givenName] forKey:@"_givenName"];
[result setValue:[nameComponents middleName] forKey:@"_middleName"];
[result setValue:[nameComponents familyName] forKey:@"_familyName"];
[result setValue:[nameComponents nameSuffix] forKey:@"_nameSuffix"];
[result setValue:[nameComponents nickname] forKey:@"_nickname"];
NSDictionary *phoneticRepresentationDictionary = [AppleAuthSerializer dictionaryForNSPersonNameComponents:[nameComponents phoneticRepresentation]];
[result setValue:@(phoneticRepresentationDictionary != nil) forKey:@"_hasPhoneticRepresentation"];
[result setValue:phoneticRepresentationDictionary forKey:@"_phoneticRepresentation"];
return [result copy];
}

#endif

// IOS/TVOS 13.0 | MACOS 10.15 | VISIONOS 1.0
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 || __TV_OS_VERSION_MAX_ALLOWED >= 130000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500 || __VISION_OS_VERSION_MAX_ALLOWED >= 10000

+ (NSDictionary *) dictionaryForASAuthorizationAppleIDCredential:(ASAuthorizationAppleIDCredential *)appleIDCredential
{
if (!appleIDCredential)
return nil;
NSMutableDictionary *result = [NSMutableDictionary dictionary];
[result setValue:[[appleIDCredential identityToken] base64EncodedStringWithOptions:0] forKey:@"_base64IdentityToken"];
[result setValue:[[appleIDCredential authorizationCode] base64EncodedStringWithOptions:0] forKey:@"_base64AuthorizationCode"];
[result setValue:[appleIDCredential state] forKey:@"_state"];
[result setValue:[appleIDCredential user] forKey:@"_user"];
[result setValue:[appleIDCredential authorizedScopes] forKey:@"_authorizedScopes"];
[result setValue:[appleIDCredential email] forKey:@"_email"];
[result setValue:@([appleIDCredential realUserStatus]) forKey:@"_realUserStatus"];
NSDictionary *fullNameDictionary = [AppleAuthSerializer dictionaryForNSPersonNameComponents:[appleIDCredential fullName]];
[result setValue:@(fullNameDictionary != nil) forKey:@"_hasFullName"];
[result setValue:fullNameDictionary forKey:@"_fullName"];
return [result copy];
}

+ (NSDictionary *) dictionaryForASPasswordCredential:(ASPasswordCredential *)passwordCredential
{
if (!passwordCredential)
return nil;
NSMutableDictionary *result = [NSMutableDictionary dictionary];
[result setValue:[passwordCredential user] forKey:@"_user"];
[result setValue:[passwordCredential password] forKey:@"_password"];
return [result copy];
}

#endif

@end

+ 105
- 0
Assets/AppleAuth/Runtime/Native/iOS/AppleAuthSerializer.m.meta View File

@@ -0,0 +1,105 @@
fileFormatVersion: 2
guid: f4b051f98e4b74942bb617c674da4d8d
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude Linux: 1
Exclude Linux64: 1
Exclude LinuxUniversal: 1
Exclude OSXUniversal: 1
Exclude VisionOS: 0
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 0
Exclude tvOS: 0
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux
second:
enabled: 0
settings:
CPU: x86
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
VisionOS: VisionOS
second:
enabled: 1
settings: {}
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:

+ 78
- 0
Assets/AppleAuth/Runtime/Native/iOS/PersonNameComponentsFormatting.m View File

@@ -0,0 +1,78 @@
//
// MIT License
//
// Copyright (c) 2019 Daniel Lupiañez Casares
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#import <Foundation/Foundation.h>

const char* AppleAuth_CopyCString(const char* string)
{
if (string == NULL)
return NULL;
char* res = (char*)malloc(strlen(string) + 1);
strcpy(res, string);
return res;
}

const char* AppleAuth_GetPersonNameUsingFormatter(const char *payload, int style, bool usePhoneticRepresentation)
{
if (payload == NULL)
return NULL;
NSError *error = nil;
NSData *payloadData = [NSData dataWithBytes:payload length:strlen(payload)];
NSDictionary * nameComponentsDictionary = [NSJSONSerialization JSONObjectWithData:payloadData options:0 error:&error];
if (error)
return NULL;
if (@available(iOS 9.0, tvOS 9.0, macOS 10.11, visionOS 1.0, *)) {
NSPersonNameComponents *nameData = [[NSPersonNameComponents alloc] init];
[nameData setNamePrefix:[nameComponentsDictionary objectForKey:@"_namePrefix"]];
[nameData setGivenName:[nameComponentsDictionary objectForKey:@"_givenName"]];
[nameData setMiddleName:[nameComponentsDictionary objectForKey:@"_middleName"]];
[nameData setFamilyName:[nameComponentsDictionary objectForKey:@"_familyName"]];
[nameData setNameSuffix:[nameComponentsDictionary objectForKey:@"_nameSuffix"]];
[nameData setNickname:[nameComponentsDictionary objectForKey:@"_nickname"]];
NSDictionary *phoneticRepresentationDictionary = [nameComponentsDictionary objectForKey:@"_phoneticRepresentation"];
if (phoneticRepresentationDictionary)
{
NSPersonNameComponents *phoneticRepresentation = [[NSPersonNameComponents alloc] init];
[phoneticRepresentation setNamePrefix:[phoneticRepresentationDictionary objectForKey:@"_namePrefix"]];
[phoneticRepresentation setGivenName:[phoneticRepresentationDictionary objectForKey:@"_givenName"]];
[phoneticRepresentation setMiddleName:[phoneticRepresentationDictionary objectForKey:@"_middleName"]];
[phoneticRepresentation setFamilyName:[phoneticRepresentationDictionary objectForKey:@"_familyName"]];
[phoneticRepresentation setNameSuffix:[phoneticRepresentationDictionary objectForKey:@"_nameSuffix"]];
[phoneticRepresentation setNickname:[phoneticRepresentationDictionary objectForKey:@"_nickname"]];
[nameData setPhoneticRepresentation:phoneticRepresentation];
}
NSPersonNameComponentsFormatterOptions options = usePhoneticRepresentation ? NSPersonNameComponentsFormatterPhonetic : 0;
NSString *localizedName = [NSPersonNameComponentsFormatter localizedStringFromPersonNameComponents:nameData style:style options:options];
return AppleAuth_CopyCString([localizedName UTF8String]);
} else {
return NULL;
}
}

+ 105
- 0
Assets/AppleAuth/Runtime/Native/iOS/PersonNameComponentsFormatting.m.meta View File

@@ -0,0 +1,105 @@
fileFormatVersion: 2
guid: dcbee9f0ecbf4466b90ffadfe14a372a
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Editor: 1
Exclude Linux: 1
Exclude Linux64: 1
Exclude LinuxUniversal: 1
Exclude OSXUniversal: 1
Exclude VisionOS: 0
Exclude Win: 1
Exclude Win64: 1
Exclude iOS: 0
Exclude tvOS: 0
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux
second:
enabled: 0
settings:
CPU: x86
- first:
Standalone: Linux64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
VisionOS: VisionOS
second:
enabled: 1
settings: {}
- first:
iPhone: iOS
second:
enabled: 1
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:

+ 8
- 0
Assets/AppleAuth/Runtime/Native/macOS.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 749168713f07f492f92056b532fb27ef
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 101
- 0
Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle.meta View File

@@ -0,0 +1,101 @@
fileFormatVersion: 2
guid: 373cdd8a4c4d24881b488dd22e470a35
folderAsset: yes
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 1
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
: Any
second:
enabled: 0
settings:
Exclude Android: 1
Exclude Editor: 1
Exclude Linux: 1
Exclude Linux64: 0
Exclude LinuxUniversal: 1
Exclude OSXUniversal: 0
Exclude Win: 0
Exclude Win64: 0
Exclude iOS: 1
- first:
Android: Android
second:
enabled: 0
settings:
CPU: ARMv7
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
CPU: AnyCPU
DefaultValueInitialized: true
OS: AnyOS
- first:
Facebook: Win
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Facebook: Win64
second:
enabled: 0
settings:
CPU: AnyCPU
- first:
Standalone: Linux
second:
enabled: 0
settings:
CPU: x86
- first:
Standalone: Linux64
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings:
CPU: AnyCPU
- first:
Standalone: Win
second:
enabled: 1
settings:
CPU: None
- first:
Standalone: Win64
second:
enabled: 1
settings:
CPU: None
- first:
iPhone: iOS
second:
enabled: 0
settings:
AddToEmbeddedBinaries: false
CPU: AnyCPU
CompileFlags:
FrameworkDependencies:
userData:
assetBundleName:
assetBundleVariant:

+ 8
- 0
Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5eb5a53551730574e86ffadb88d66468
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/CodeResources View File


+ 2
- 0
Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/CodeResources.meta View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 169b7de0b3af44918b53bbc0a78d2fe6

+ 48
- 0
Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/Info.plist View File

@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BuildMachineOSBuild</key>
<string>24D81</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>MacOSAppleAuthManager</string>
<key>CFBundleIdentifier</key>
<string>com.lupidan.MacOSAppleAuthManager</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>MacOSAppleAuthManager</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.5.0</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>MacOSX</string>
</array>
<key>CFBundleVersion</key>
<string>1</string>
<key>DTCompiler</key>
<string>com.apple.compilers.llvm.clang.1_0</string>
<key>DTPlatformBuild</key>
<string>24C94</string>
<key>DTPlatformName</key>
<string>macosx</string>
<key>DTPlatformVersion</key>
<string>15.2</string>
<key>DTSDKBuild</key>
<string>24C94</string>
<key>DTSDKName</key>
<string>macosx15.2</string>
<key>DTXcode</key>
<string>1620</string>
<key>DTXcodeBuild</key>
<string>16C5032a</string>
<key>LSMinimumSystemVersion</key>
<string>10.13</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2020 Daniel Lupiañez Casares. All rights reserved.</string>
</dict>
</plist>

+ 2
- 0
Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/Info.plist.meta View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9b638816acd3a459aabcde43dcb8d767

+ 8
- 0
Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/MacOS.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ceabfa65c1a6fb744accaf7b4f143b4f
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

BIN
Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/MacOS/MacOSAppleAuthManager View File


+ 2
- 0
Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/MacOS/MacOSAppleAuthManager.meta View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2c61b42c59c7943f2ab3d31d65c452b7

+ 8
- 0
Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/_CodeSignature.meta View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f9fd4a8ff4ebfaf489fa3909f6390479
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

+ 115
- 0
Assets/AppleAuth/Runtime/Native/macOS/MacOSAppleAuthManager.bundle/Contents/_CodeSignature/CodeResources View File

@@ -0,0 +1,115 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>files</key>
<dict/>
<key>files2</key>
<dict/>
<key>rules</key>
<dict>
<key>^Resources/</key>
<true/>
<key>^Resources/.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Resources/Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^version.plist$</key>
<true/>
</dict>
<key>rules2</key>
<dict>
<key>.*\.dSYM($|/)</key>
<dict>
<key>weight</key>
<real>11</real>
</dict>
<key>^(.*/)?\.DS_Store$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>2000</real>
</dict>
<key>^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^.*</key>
<true/>
<key>^Info\.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^PkgInfo$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>20</real>
</dict>
<key>^Resources/</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^Resources/.*\.lproj/</key>
<dict>
<key>optional</key>
<true/>
<key>weight</key>
<real>1000</real>
</dict>
<key>^Resources/.*\.lproj/locversion.plist$</key>
<dict>
<key>omit</key>
<true/>
<key>weight</key>
<real>1100</real>
</dict>
<key>^Resources/Base\.lproj/</key>
<dict>
<key>weight</key>
<real>1010</real>
</dict>
<key>^[^/]+$</key>
<dict>
<key>nested</key>
<true/>
<key>weight</key>
<real>10</real>
</dict>
<key>^embedded\.provisionprofile$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
<key>^version\.plist$</key>
<dict>
<key>weight</key>
<real>20</real>
</dict>
</dict>
</dict>
</plist>

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save