diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication.meta new file mode 100644 index 000000000..cd8906d0e --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 60adf4f9040d189499c6dbb852840cf4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication/AuthenticationDataProviderProfile.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication/AuthenticationDataProviderProfile.cs new file mode 100644 index 000000000..6e820ab5b --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication/AuthenticationDataProviderProfile.cs @@ -0,0 +1,63 @@ +// Copyright (c) XRTK. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using UnityEngine; +using XRTK.Attributes; +using XRTK.Definitions.Utilities; +using XRTK.Interfaces.Authentication; + +namespace XRTK.Definitions.Authentication +{ + /// + /// The configuration profile for . + /// + [CreateAssetMenu(menuName = "Mixed Reality Toolkit/Authentication System/Generic Authentication Data Provider", fileName = "AuthenticationDataProviderProfile", order = (int)CreateProfileMenuItemIndices.AuthenticationSystem)] + public class AuthenticationDataProviderProfile : BaseMixedRealityProfile + { + [SerializeField] + [Tooltip("The client ID is the unique application (client) ID assigned to your app by registering your application with the identity provider.")] + private string clientId = ""; + + /// + /// The client ID is the unique application (client) ID assigned to your app by registering your application with the identity provider. + /// + public string ClientId => clientId; + + [SerializeField] + [Tooltip("The identity provider url to request OAuth tokens from.")] + private string identityProviderUrl = ""; + + /// + /// The identity provider url to request OAuth tokens from. + /// + public string IdentityProviderUrl => identityProviderUrl; + + [SerializeField] + [Tooltip("Scopes or Permissions to request access to.")] + private string[] scopes = new string[0]; + + /// + /// The Scopes or Permissions to request access to. + /// + public string[] Scopes => scopes; + + [SerializeField] + [Tooltip("The redirect url is the endpoint the identity provider will send the security tokens back to.")] + private string redirectUrl = ""; + + /// + /// The redirect url is the endpoint the identity provider will send the security tokens back to. + /// + public string RedirectUrl => redirectUrl; + + [SerializeField] + [Prefab(typeof(IAuthenticationHandler))] + [Tooltip("The login prefab to display when the user is logging in.")] + private GameObject loginPrefab = null; + + /// + /// The login prefab to display when the user is logging in. + /// + public GameObject LoginPrefab => loginPrefab; + } +} diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication/AuthenticationDataProviderProfile.cs.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication/AuthenticationDataProviderProfile.cs.meta new file mode 100644 index 000000000..984d7dfcb --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication/AuthenticationDataProviderProfile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: c042ff0dbb5def24f99759820314b067 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 8ac5213854cf4dbabd140decf8df1946, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication/AuthenticationSystemProfile.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication/AuthenticationSystemProfile.cs new file mode 100644 index 000000000..a453258ec --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication/AuthenticationSystemProfile.cs @@ -0,0 +1,19 @@ +// Copyright (c) XRTK. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using UnityEngine; +using XRTK.Interfaces.Authentication; + +namespace XRTK.Definitions.Authentication +{ + public class AuthenticationSystemProfile : BaseMixedRealityServiceProfile + { + [SerializeField] + private bool cacheUserTokens = true; + + /// + /// Remember previously obtained user tokens. + /// + public bool CacheUserTokens => cacheUserTokens; + } +} diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication/AuthenticationSystemProfile.cs.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication/AuthenticationSystemProfile.cs.meta new file mode 100644 index 000000000..bd9598f8e --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Authentication/AuthenticationSystemProfile.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cd7a1e631fa20d9459694f09e2f93fb0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 8ac5213854cf4dbabd140decf8df1946, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Utilities/ProfileMenuItemIndices.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Utilities/ProfileMenuItemIndices.cs index ea0378ffc..98e969b65 100644 --- a/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Utilities/ProfileMenuItemIndices.cs +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Definitions/Utilities/ProfileMenuItemIndices.cs @@ -24,6 +24,7 @@ public enum CreateProfileMenuItemIndices Networking, NetworkingDataProviders, Diagnostics, + AuthenticationSystem, RegisteredServiceProviders, Settings } diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication.meta new file mode 100644 index 000000000..b47281849 --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8da3efad4e4f335459023717118039f2 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IAuthenticatedAccount.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IAuthenticatedAccount.cs new file mode 100644 index 000000000..c0290682a --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IAuthenticatedAccount.cs @@ -0,0 +1,26 @@ +// Copyright (c) XRTK. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +namespace XRTK.Interfaces.Authentication +{ + /// + /// Represents an authenticated user account + /// + public interface IAuthenticatedAccount + { + /// + /// The username of the authenticated account + /// + string Username { get; } + + /// + /// The access token required for secure access to an online service + /// + string AccessToken { get; } + + /// + /// Gets the that this account identity is associated with. + /// + IMixedRealityAuthenticationDataProvider Provider { get; } + } +} diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IAuthenticatedAccount.cs.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IAuthenticatedAccount.cs.meta new file mode 100644 index 000000000..b618db907 --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IAuthenticatedAccount.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: ea1cb58906310af4c879624cc34e78f4 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 8ac5213854cf4dbabd140decf8df1946, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IAuthenticationHandler.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IAuthenticationHandler.cs new file mode 100644 index 000000000..9048a9e88 --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IAuthenticationHandler.cs @@ -0,0 +1,14 @@ +// Copyright (c) XRTK. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +namespace XRTK.Interfaces.Authentication +{ + public interface IAuthenticationHandler : UnityEngine.EventSystems.IEventSystemHandler + { + /// + /// Display code flow message. + /// + /// + void DisplayCodeFlowMessage(string message); + } +} diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IAuthenticationHandler.cs.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IAuthenticationHandler.cs.meta new file mode 100644 index 000000000..430120d3f --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IAuthenticationHandler.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 4baea7e2107271548a960fdf4e5e976b +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 8ac5213854cf4dbabd140decf8df1946, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IMixedRealityAuthenticationDataProvider.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IMixedRealityAuthenticationDataProvider.cs new file mode 100644 index 000000000..ffeee54f5 --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IMixedRealityAuthenticationDataProvider.cs @@ -0,0 +1,55 @@ +// Copyright (c) XRTK. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Threading.Tasks; +using XRTK.Definitions.Authentication; + +namespace XRTK.Interfaces.Authentication +{ + /// + /// Interface contract for specific identity provider implementations for use in the . + /// + public interface IMixedRealityAuthenticationDataProvider : IMixedRealityDataProvider + { + /// + /// Event called when a user has successfully logged in. + /// + event Action OnLoggedIn; + + /// + /// Event called when a user has logged out. + /// + event Action OnLoggedOut; + + /// + /// The . Null if no user is logged in. + /// + IAuthenticatedAccount AuthenticatedAccount { get; } + + /// + /// Is there currently a valid user logged in with a valid token? + /// + bool IsUserLoggedIn { get; } + + /// + /// Start Login task. + /// + /// + /// This may prompt the user to authenticate with the + /// + /// Completed . + Task LoginAsync(); + + /// + /// Log the user out. + /// + /// + void Logout(bool reAuthenticate = true); + + /// + /// Removes all account tokens from the cache. + /// + void ClearTokenCache(); + } +} diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IMixedRealityAuthenticationDataProvider.cs.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IMixedRealityAuthenticationDataProvider.cs.meta new file mode 100644 index 000000000..f552789fa --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IMixedRealityAuthenticationDataProvider.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 3c0fd10ffac6fb04bab0551b44ca1c1e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 8ac5213854cf4dbabd140decf8df1946, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IMixedRealityAuthenticationSystem.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IMixedRealityAuthenticationSystem.cs new file mode 100644 index 000000000..aefb86251 --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IMixedRealityAuthenticationSystem.cs @@ -0,0 +1,65 @@ +// Copyright (c) XRTK. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using XRTK.Definitions.Authentication; + +namespace XRTK.Interfaces.Authentication +{ + /// + /// Provider agnostic Interface contract for user authentication with public client applications. + /// + public interface IMixedRealityAuthenticationSystem : IMixedRealitySystem + { + /// + /// Signals when the user has been logged in + /// + event Action OnLoggedIn; + + /// + /// Signals when the user has been logged out. + /// + event Action OnLoggedOut; + + /// + /// Should the login tokens be cached? + /// + bool CacheUserTokens { get; set; } + + /// + /// Gets the currently logged in s. + /// + IReadOnlyCollection ActiveAccounts { get; } + + /// + /// All of the currently active s. + /// + IReadOnlyCollection ActiveAuthenticationProviders { get; } + + /// + /// Register a with the system. + /// + /// The to register. + /// True, if the was successfully registered, otherwise false. + bool RegisterAuthenticationDataProvider(IMixedRealityAuthenticationDataProvider provider); + + /// + /// Unregister a with the system. + /// + /// The to unregister. + /// True, if the was successfully unregistered, otherwise false. + bool UnregisterAuthenticationDataProvider(IMixedRealityAuthenticationDataProvider provider); + + /// + /// Logs out of all active sessions in all active s. + /// + void LogOutAllSessions(); + + /// + /// Clears out all of the token caches for all active s. + /// + void ClearAllTokenCaches(); + } +} diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IMixedRealityAuthenticationSystem.cs.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IMixedRealityAuthenticationSystem.cs.meta new file mode 100644 index 000000000..a44cf4c32 --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Interfaces/Authentication/IMixedRealityAuthenticationSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: cf9563889fed24c49862ab8550ca9414 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 8ac5213854cf4dbabd140decf8df1946, type: 3} + userData: + assetBundleName: + assetBundleVariant: diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/Authentication.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/Authentication.meta new file mode 100644 index 000000000..1bf0c5eab --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/Authentication.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8ba5a13650181cc4ab96ae8c9543e682 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/Authentication/AuthenticationSystem.cs b/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/Authentication/AuthenticationSystem.cs new file mode 100644 index 000000000..308d51a3b --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/Authentication/AuthenticationSystem.cs @@ -0,0 +1,134 @@ +// Copyright (c) XRTK. All rights reserved. +// Licensed under the MIT License. See LICENSE in the project root for license information. + +using System; +using System.Collections.Generic; +using UnityEngine; +using XRTK.Definitions.Authentication; +using XRTK.Interfaces.Authentication; + +namespace XRTK.Services.Authentication +{ + /// + /// Concrete implementation of the + /// + [System.Runtime.InteropServices.Guid("B9AA44EA-23C9-4B4A-8DE6-D598E6F638FB")] + public class AuthenticationSystem : BaseSystem, IMixedRealityAuthenticationSystem + { + /// + public AuthenticationSystem(AuthenticationSystemProfile profile) : base(profile) + { + CacheUserTokens = profile.CacheUserTokens; + } + + #region IMixedRealityAuthenticationSystem Implementation + + /// + public event Action OnLoggedIn; + + /// + public event Action OnLoggedOut; + + /// + public bool CacheUserTokens { get; set; } + + private readonly HashSet activeAccounts = new HashSet(); + + /// + public IReadOnlyCollection ActiveAccounts => activeAccounts; + + private readonly HashSet activeDataProviders = new HashSet(); + + /// + public IReadOnlyCollection ActiveAuthenticationProviders => activeDataProviders; + + /// + public bool RegisterAuthenticationDataProvider(IMixedRealityAuthenticationDataProvider provider) + { + if (activeDataProviders.Contains(provider)) + { + return false; + } + + activeDataProviders.Add(provider); + LoginEvents(provider, true); + return true; + } + + /// + public bool UnregisterAuthenticationDataProvider(IMixedRealityAuthenticationDataProvider provider) + { + if (!activeDataProviders.Contains(provider)) + { + return false; + } + + LoginEvents(provider, false); + activeDataProviders.Remove(provider); + return true; + } + + /// + public void LogOutAllSessions() + { + foreach (var provider in activeDataProviders) + { + provider.Logout(false); + } + } + + /// + public void ClearAllTokenCaches() + { + foreach (var provider in activeDataProviders) + { + provider.ClearTokenCache(); + } + } + + #endregion IMixedRealityAuthenticationSystem Implementation + + private void LoginEvents(IMixedRealityAuthenticationDataProvider provider, bool isRegistered) + { + if (activeDataProviders.Contains(provider)) + { + if (isRegistered) + { + provider.OnLoggedIn += OnProviderLoggedIn; + provider.OnLoggedOut += OnProviderLogout; + } + else + { + provider.OnLoggedIn -= OnProviderLoggedIn; + provider.OnLoggedOut -= OnProviderLogout; + } + } + + void OnProviderLoggedIn(IAuthenticatedAccount account) + { + if (!activeAccounts.Contains(account)) + { + activeAccounts.Add(account); + OnLoggedIn?.Invoke(provider, account); + } + else + { + Debug.LogError($"{Name}:{nameof(OnLoggedOut)}: Account already logged in!"); + } + } + + void OnProviderLogout(IAuthenticatedAccount account) + { + if (activeAccounts.Contains(account)) + { + activeAccounts.Remove(account); + OnLoggedOut?.Invoke(provider, account); + } + else + { + Debug.LogError($"{Name}:{nameof(OnLoggedOut)}: Account already logged out!"); + } + } + } + } +} diff --git a/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/Authentication/AuthenticationSystem.cs.meta b/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/Authentication/AuthenticationSystem.cs.meta new file mode 100644 index 000000000..afda790ec --- /dev/null +++ b/XRTK-Core/Packages/com.xrtk.core/Runtime/Services/Authentication/AuthenticationSystem.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 17991b69050bcce4a8c0a8e5eb8041ab +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {fileID: 2800000, guid: 8ac5213854cf4dbabd140decf8df1946, type: 3} + userData: + assetBundleName: + assetBundleVariant: