diff --git a/.gitignore b/.gitignore index b400c0478..e9147ea1e 100644 --- a/.gitignore +++ b/.gitignore @@ -60,4 +60,4 @@ docs/.sass-cache .Trashes ehthumbs.db Thumbs.db -/VisRepo.txt +*.txt diff --git a/Assets/Mirror/Runtime/NetworkAuthenticator.cs b/Assets/Mirror/Runtime/NetworkAuthenticator.cs index 2c673ff3c..65570de8b 100644 --- a/Assets/Mirror/Runtime/NetworkAuthenticator.cs +++ b/Assets/Mirror/Runtime/NetworkAuthenticator.cs @@ -1,4 +1,5 @@ using System; +using System.Collections; using UnityEngine; using UnityEngine.Events; @@ -15,6 +16,11 @@ namespace Mirror [HelpURL("https://mirror-networking.com/docs/Guides/Authentication.html")] public abstract class NetworkAuthenticator : MonoBehaviour { + [Header("Configuration")] + + [Range(0, 255), Tooltip("Timeout to auto-disconnect in seconds. Set to 0 for no timeout.")] + public byte timeout; + [Header("Event Listeners (optional)")] /// @@ -40,6 +46,9 @@ public virtual void OnStartServer() {} // This will get more code in the near future internal void OnServerAuthenticateInternal(NetworkConnection conn) { + // Start the countdown for Authentication + if (timeout > 0) StartCoroutine(AuthenticationTimer(conn, true)); + OnServerAuthenticate(conn); } @@ -49,6 +58,16 @@ internal void OnServerAuthenticateInternal(NetworkConnection conn) /// Connection to client. public abstract void OnServerAuthenticate(NetworkConnection conn); + /// + /// Called on server when the timeout expires without being authenticated + /// + /// Connection to client. + public virtual void OnServerAuthenticationTimeout(NetworkConnection conn) + { + Debug.LogErrorFormat("OnServerAuthenticationTimeout: {0}", conn); + conn.Disconnect(); + } + #endregion #region client @@ -62,6 +81,9 @@ public virtual void OnStartClient() {} // This will get more code in the near future internal void OnClientAuthenticateInternal(NetworkConnection conn) { + // Start the countdown for Authentication + if (timeout > 0) StartCoroutine(AuthenticationTimer(conn, false)); + OnClientAuthenticate(conn); } @@ -71,8 +93,39 @@ internal void OnClientAuthenticateInternal(NetworkConnection conn) /// Connection of the client. public abstract void OnClientAuthenticate(NetworkConnection conn); + /// + /// Called on client when the timeout expires without being authenticated + /// + /// Connection of the client. + public virtual void OnClientAuthenticationTimeout(NetworkConnection conn) + { + Debug.LogErrorFormat("OnClientAuthenticationTimeout: {0}", conn); + conn.Disconnect(); + } + #endregion + /// + /// This is called on both client and server if timeout > 0 + /// + /// Connection of the client. + public IEnumerator AuthenticationTimer(NetworkConnection conn, bool isServer) + { + if (LogFilter.Debug) Debug.LogFormat("Authentication countdown started {0} {1}", conn.connectionId, timeout); + + yield return new WaitForSecondsRealtime(timeout); + + if (conn != null && !conn.isAuthenticated) + { + if (LogFilter.Debug) Debug.LogFormat("Authentication Timeout {0}", conn.connectionId); + + if (isServer) + OnServerAuthenticationTimeout(conn); + else + OnClientAuthenticationTimeout(conn); + } + } + void OnValidate() { #if UNITY_EDITOR diff --git a/doc/Components/Authenticators/Basic.png b/doc/Components/Authenticators/Basic.png index 735912cdc..7bbbe58e4 100644 Binary files a/doc/Components/Authenticators/Basic.png and b/doc/Components/Authenticators/Basic.png differ diff --git a/doc/Guides/Authentication.md b/doc/Guides/Authentication.md index d69d4ede4..924bafff6 100644 --- a/doc/Guides/Authentication.md +++ b/doc/Guides/Authentication.md @@ -49,6 +49,7 @@ To make your own custom Authenticator, you can just create a new script in your Here are some tips for custom Authenticators: - `OnStartServer` and `OnStartClient` are the appropriate methods to register server and client messages and their handlers. They're called from StartServer/StartHost, and StartClient, respectively. +- The base Authenticator includes a timeout feature so you can prevent rogue clients from locking up your connections. - Send a message to the client if authentication fails, especially if there's some issue they can resolve. - Call the `Disconnect()` method of the `NetworkConnection` on the server and client when authentication fails. If you want to give the user a few tries to get their credentials right, you certainly can, but Mirror will not do the disconnect for you. - Remember to put a small delay on the Disconnect call on the server if you send a failure message so that it has a chance to be delivered before the connection is dropped.