애플 관련 에러 수정

This commit is contained in:
Ino 2024-12-18 15:23:47 +09:00
parent aeb934fda5
commit 3fbc327afa
94 changed files with 2712 additions and 11 deletions

8
Assets/ThirdParty/AppleAuth.meta vendored Normal file
View File

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

View File

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

View File

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

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;
}
}
}

View File

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

View File

@ -0,0 +1,338 @@
#if ((UNITY_IOS || UNITY_TVOS || 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 - v1.4.3";
#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
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
}
}

View File

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

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;
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,47 @@
using System;
using System.IO;
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)
{
Debug.LogError("AppleAuthMacosPostprocessorHelper: FixManagerBundleIdentifier should only be called when building for macOS");
return;
}
const string bundleIdentifierPattern = @"(\<key\>CFBundleIdentifier\<\/key\>\s*\<string\>)(com\.lupidan)(\.MacOSAppleAuthManager\<\/string\>)";
const string macOSAppleAuthManagerInfoPlistRelativePath = "/Contents/Plugins/MacOSAppleAuthManager.bundle/Contents/Info.plist";
try
{
var macosAppleAuthManagerInfoPlistPath = path + macOSAppleAuthManagerInfoPlistRelativePath;
var macosAppleAuthManagerInfoPlist = File.ReadAllText(macosAppleAuthManagerInfoPlistPath);
var modifiedMacosAppleAuthManagerInfoPlist = Regex.Replace(
macosAppleAuthManagerInfoPlist,
bundleIdentifierPattern,
"$1" + PlayerSettings.applicationIdentifier + "$3");
File.WriteAllText(macosAppleAuthManagerInfoPlistPath, modifiedMacosAppleAuthManagerInfoPlist);
Debug.Log("AppleAuthMacosPostprocessorHelper: Renamed MacOSAppleAuthManager.bundle bundle identifier from \"com.lupidan.MacOSAppleAuthManager\" -> \"" + PlayerSettings.applicationIdentifier + ".MacOSAppleAuthManager\"");
}
catch (Exception exception)
{
Debug.LogError("AppleAuthMacosPostprocessorHelper: Error while fixing MacOSAppleAuthManager.bundle bundle identifier :: " + exception.Message);
}
}
}
}

View File

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

View File

@ -0,0 +1,78 @@
#if UNITY_IOS || UNITY_TVOS
using System;
using System.Reflection;
using UnityEditor.iOS.Xcode;
namespace AppleAuth.Editor
{
public static class ProjectCapabilityManagerExtension
{
private const string EntitlementsArrayKey = "com.apple.developer.applesignin";
private const string DefaultAccessLevel = "Default";
private const string AuthenticationServicesFramework = "AuthenticationServices.framework";
private const BindingFlags NonPublicInstanceBinding = BindingFlags.NonPublic | BindingFlags.Instance;
private const BindingFlags PublicInstanceBinding = BindingFlags.Public | BindingFlags.Instance;
/// <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>
/// <param name="unityFrameworkTargetGuid">The GUID for the UnityFramework target. If null, it will use the main target GUID.</param>
public static void AddSignInWithAppleWithCompatibility(this ProjectCapabilityManager manager, string unityFrameworkTargetGuid = null)
{
var managerType = typeof(ProjectCapabilityManager);
var projectField = managerType.GetField("project", NonPublicInstanceBinding);
var targetGuidField = managerType.GetField("m_TargetGuid", NonPublicInstanceBinding);
var entitlementFilePathField = managerType.GetField("m_EntitlementFilePath", NonPublicInstanceBinding);
var getOrCreateEntitlementDocMethod = managerType.GetMethod("GetOrCreateEntitlementDoc", NonPublicInstanceBinding);
// in old unity versions PBXCapabilityType had internal ctor; that was changed to public afterwards - try both
var constructorInfo = GetPBXCapabilityTypeConstructor(PublicInstanceBinding) ??
GetPBXCapabilityTypeConstructor(NonPublicInstanceBinding);
if (projectField == null || targetGuidField == null || entitlementFilePathField == null ||
getOrCreateEntitlementDocMethod == null || constructorInfo == 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 = getOrCreateEntitlementDocMethod.Invoke(manager, new object[] { }) as PlistDocument;
if (entitlementDoc != null)
{
var plistArray = new PlistElementArray();
plistArray.AddString(DefaultAccessLevel);
entitlementDoc.root[EntitlementsArrayKey] = plistArray;
}
var project = projectField.GetValue(manager) as PBXProject;
if (project != null)
{
var mainTargetGuid = targetGuidField.GetValue(manager) as string;
var capabilityType = constructorInfo.Invoke(new object[] { "com.apple.developer.applesignin.custom", true, string.Empty, true }) as PBXCapabilityType;
var targetGuidToAddFramework = unityFrameworkTargetGuid;
if (targetGuidToAddFramework == null)
{
targetGuidToAddFramework = mainTargetGuid;
}
project.AddFrameworkToProject(targetGuidToAddFramework, AuthenticationServicesFramework, true);
project.AddCapability(mainTargetGuid, capabilityType, entitlementFilePath, false);
}
}
private static ConstructorInfo GetPBXCapabilityTypeConstructor(BindingFlags flags)
{
return typeof(PBXCapabilityType).GetConstructor(
flags,
null,
new[] {typeof(string), typeof(bool), typeof(string), typeof(bool)},
null);
}
}
}
#endif

View File

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

View File

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

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,
}
}

View File

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

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,
}
}

View File

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

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 users full name.
/// </summary>
IncludeFullName = 1 << 0,
/// <summary>
/// A scope that includes the users email address
/// </summary>
IncludeEmail = 1 << 1,
}
}

View File

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

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,
}
}

View File

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

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,
}
}

View File

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

View File

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

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;
}
}
}

View File

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

View File

@ -0,0 +1,91 @@
#if ((UNITY_IOS || UNITY_TVOS || 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
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
}
}

View File

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

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();
}
}

View File

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

View File

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

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; }
}
}

View File

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

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 apps 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 users name
/// </summary>
IPersonName FullName { get; }
/// <summary>
/// The users email address
/// </summary>
string Email { get; }
/// <summary>
/// A value that indicates whether the user appears to be a real person.
/// </summary>
RealUserStatus RealUserStatus { get; }
}
}

View File

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

View File

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

View File

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

View File

@ -0,0 +1,11 @@
using AppleAuth.Enums;
namespace AppleAuth.Interfaces
{
public interface ICredentialStateResponse
{
bool Success { get; }
CredentialState CredentialState { get; }
IAppleError Error { get; }
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,43 @@
namespace AppleAuth.Interfaces
{
/// <summary>
/// PersonNameComponents
/// </summary>
public interface IPersonName
{
/// <summary>
/// The portion of a names 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 names 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; }
}
}

View File

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

View File

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

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}";
}
}
}

View File

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

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");
}
}
}

View File

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

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);
}
}
}

View File

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

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);
}
}
}

View File

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

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);
}
}
}

View File

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

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);
}
}
}

View File

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

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);
}
}
}

View File

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

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);
}
}
}

View File

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

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;
}
}
}

View File

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

View File

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

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

View File

@ -0,0 +1,27 @@
fileFormatVersion: 2
guid: f705402ad262540e1bc3643761542ce8
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,392 @@
//
// 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
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 || __TV_OS_VERSION_MAX_ALLOWED >= 130000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
#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))
@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, *))
{
_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, *))
{
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, *))
{
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, *))
{
[[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, *))
{
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))
{
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))
{
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))
{
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))
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 || __TV_OS_VERSION_MAX_ALLOWED >= 130000
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()
{
if (@available(iOS 13.0, tvOS 13.0, macOS 10.15, *))
{
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);
}

View File

@ -0,0 +1,37 @@
fileFormatVersion: 2
guid: 1588cf41e8b514372ad7cc2f8e8f4b3a
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings: {}
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:

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
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 || __TV_OS_VERSION_MAX_ALLOWED >= 130000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
#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
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 || __TV_OS_VERSION_MAX_ALLOWED >= 90000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
+ (NSDictionary * _Nullable) dictionaryForNSPersonNameComponents:(NSPersonNameComponents * _Nullable)nameComponents
API_AVAILABLE(ios(9.0), macos(10.11), tvos(9.0), watchos(2.0));
#endif
// IOS/TVOS 13.0 | MACOS 10.15
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 || __TV_OS_VERSION_MAX_ALLOWED >= 130000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
+ (NSDictionary * _Nullable) dictionaryForASAuthorizationAppleIDCredential:(ASAuthorizationAppleIDCredential * _Nullable)appleIDCredential
API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0));
+ (NSDictionary * _Nullable) dictionaryForASPasswordCredential:(ASPasswordCredential * _Nullable)passwordCredential
API_AVAILABLE(ios(13.0), macos(10.15), tvos(13.0), watchos(6.0));
#endif
@end

View File

@ -0,0 +1,27 @@
fileFormatVersion: 2
guid: 503b805cc1e9b4684bd3ffee99ff984e
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 1
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
userData:
assetBundleName:
assetBundleVariant:

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
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 90000 || __TV_OS_VERSION_MAX_ALLOWED >= 90000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101100
+ (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
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 || __TV_OS_VERSION_MAX_ALLOWED >= 130000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101500
+ (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

View File

@ -0,0 +1,37 @@
fileFormatVersion: 2
guid: 95521bb09876d4fb3a043afcb7a808d7
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings: {}
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:

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, *)) {
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;
}
}

View File

@ -0,0 +1,37 @@
fileFormatVersion: 2
guid: 1b9b9a8e9fccb4db0bcdd7b6e4639fde
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 0
settings:
DefaultValueInitialized: true
- first:
iPhone: iOS
second:
enabled: 1
settings: {}
- first:
tvOS: tvOS
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

View File

@ -0,0 +1,33 @@
fileFormatVersion: 2
guid: e999e31db70c344009ad7b13f1519e14
folderAsset: yes
PluginImporter:
externalObjects: {}
serializedVersion: 2
iconMap: {}
executionOrder: {}
defineConstraints: []
isPreloaded: 0
isOverridable: 0
isExplicitlyReferenced: 0
validateReferences: 1
platformData:
- first:
Any:
second:
enabled: 0
settings: {}
- first:
Editor: Editor
second:
enabled: 1
settings:
DefaultValueInitialized: true
- first:
Standalone: OSXUniversal
second:
enabled: 1
settings: {}
userData:
assetBundleName:
assetBundleVariant:

View File

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

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>22G120</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.4.3</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></string>
<key>DTPlatformName</key>
<string>macosx</string>
<key>DTPlatformVersion</key>
<string>14.0</string>
<key>DTSDKBuild</key>
<string>23A334</string>
<key>DTSDKName</key>
<string>macosx14.0</string>
<key>DTXcode</key>
<string>1500</string>
<key>DTXcodeBuild</key>
<string>15A240d</string>
<key>LSMinimumSystemVersion</key>
<string>10.13</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2020 Daniel Lupiañez Casares. All rights reserved.</string>
</dict>
</plist>

View File

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

BIN
Assets/ThirdParty/AppleAuth/README.pdf vendored Normal file

Binary file not shown.

View File

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

View File

@ -0,0 +1,26 @@
{
"name": "com.lupidan.apple-signin-unity-src",
"displayName": "Sign in with Apple [Local Source]",
"version": "1.4.3",
"unity": "2018.3",
"description": "[Local Source]\nProvides a Unity bridge to use the native Sign In With Apple method on iOS/iPadOS/tvOS/macOS devices",
"author": {
"name": "Daniel Lupiañez Casares",
"email": "daniel.lupianez.casares@gmail.com",
"url": "https://github.com/lupidan"
},
"keywords": [
"apple",
"iphone",
"ios",
"ipad",
"ipados",
"tvos",
"macOS",
"signin",
"oauth",
"native",
"unity"
],
"category": "Unity"
}

View File

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

View File

@ -1,16 +1,15 @@
{
"dependencies": {
"com.lupidan.apple-signin-unity": "https://github.com/lupidan/apple-signin-unity.git#v1.4.2",
"com.unity.2d.sprite": "1.0.0",
"com.unity.addressables": "1.22.3",
"com.unity.ai.navigation": "1.1.5",
"com.unity.mobile.notifications": "2.4.0",
"com.unity.purchasing": "4.12.2",
"com.unity.recorder": "4.0.3",
"com.unity.collab-proxy": "2.6.0",
"com.unity.ide.rider": "3.0.34",
"com.unity.ide.visualstudio": "2.0.22",
"com.unity.ide.vscode": "1.2.5",
"com.unity.mobile.notifications": "2.4.0",
"com.unity.purchasing": "4.12.2",
"com.unity.recorder": "4.0.3",
"com.unity.render-pipelines.universal": "14.0.11",
"com.unity.services.ccd.management": "2.2.2",
"com.unity.test-framework": "1.1.33",

View File

@ -1,12 +1,5 @@
{
"dependencies": {
"com.lupidan.apple-signin-unity": {
"version": "https://github.com/lupidan/apple-signin-unity.git#v1.4.2",
"depth": 0,
"source": "git",
"dependencies": {},
"hash": "e39981bca07f08f068231f651e1e8d0f69397222"
},
"com.unity.2d.sprite": {
"version": "1.0.0",
"depth": 0,

View File

@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<projectSettings>
<projectSetting name="com.google.external-dependency-managerAnalyticsCookie" value="f3be45d57d874f619c90b91cf65ba1ce" />
<projectSetting name="com.google.external-dependency-managerAnalyticsEnabled" value="True" />
<projectSetting name="Google.IOSResolver.VerboseLoggingEnabled" value="False" />
<projectSetting name="Google.PackageManagerResolver.VerboseLoggingEnabled" value="False" />
<projectSetting name="Google.VersionHandler.VerboseLoggingEnabled" value="False" />