diff --git a/Facepunch.Steamworks.Test/UserTest.cs b/Facepunch.Steamworks.Test/UserTest.cs index 2b5a4f3..25e28fd 100644 --- a/Facepunch.Steamworks.Test/UserTest.cs +++ b/Facepunch.Steamworks.Test/UserTest.cs @@ -74,6 +74,16 @@ namespace Steamworks SteamUser.EndAuthSession( SteamClient.SteamId ); } + [TestMethod] + public async Task AuthSessionAsync() + { + var ticket = await SteamUser.GetAuthSessionTicketAsync( 5.0 ); + + Assert.AreNotEqual( 0, ticket.Handle ); + Assert.AreNotEqual( 0, ticket.Data.Length ); + Console.WriteLine( $"ticket.Handle: {ticket.Handle}" ); + Console.WriteLine( $"ticket.Data: { string.Join( "", ticket.Data.Select( x => x.ToString( "x" ) ) ) }" ); + } [TestMethod] public void SteamLevel() diff --git a/Facepunch.Steamworks/SteamUser.cs b/Facepunch.Steamworks/SteamUser.cs index 7b5a342..3d3e4fa 100644 --- a/Facepunch.Steamworks/SteamUser.cs +++ b/Facepunch.Steamworks/SteamUser.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; using System.Text; @@ -49,6 +50,7 @@ namespace Steamworks ValidateAuthTicketResponse_t.Install( x => OnValidateAuthTicketResponse?.Invoke( x.SteamID, x.OwnerSteamID, x.AuthSessionResponse ) ); MicroTxnAuthorizationResponse_t.Install( x => OnMicroTxnAuthorizationResponse?.Invoke( x.AppID, x.OrderID, x.Authorized != 0 ) ); GameWebCallback_t.Install( x => OnGameWebCallback?.Invoke( x.URL ) ); + GetAuthSessionTicketResponse_t.Install( x => OnGetAuthSessionTicketResponse?.Invoke( x ) ); } /// @@ -88,10 +90,16 @@ namespace Steamworks /// /// Called when an auth ticket has been validated. /// The first parameter is the steamid of this user - /// The second is the Steam ID that owns the game, this will be different from the first if the game is being borrowed via Steam Family Sharing + /// The second is the Steam ID that owns the game, this will be different from the first + /// if the game is being borrowed via Steam Family Sharing /// public static event Action OnValidateAuthTicketResponse; + /// + /// Used internally for GetAuthSessionTicketAsync + /// + internal static event Action OnGetAuthSessionTicketResponse; + /// /// Called when a user has responded to a microtransaction authorization request. /// ( appid, orderid, user authorized ) @@ -302,6 +310,55 @@ namespace Steamworks } } + /// + /// Retrieve a authentication ticket to be sent to the entity who wishes to authenticate you. + /// This waits for a positive response from the backend before returning the ticket. This means + /// the ticket is definitely ready to go as soon as it returns. Will return null if the callback + /// times out or returns negatively. + /// + public static async Task GetAuthSessionTicketAsync( double timeoutSeconds = 10.0f ) + { + var result = Result.Pending; + AuthTicket ticket = null; + var stopwatch = Stopwatch.StartNew(); + + Action f = ( t ) => + { + if ( t.AuthTicket != ticket.Handle ) return; + result = t.Result; + }; + + OnGetAuthSessionTicketResponse += f; + + try + { + ticket = GetAuthSessionTicket(); + if ( ticket == null ) + return null; + + while ( result == Result.Pending ) + { + await Task.Delay( 10 ); + + if ( stopwatch.Elapsed.TotalSeconds > timeoutSeconds ) + { + ticket.Cancel(); + return null; + } + } + + if ( result == Result.OK ) + return ticket; + + ticket.Cancel(); + return null; + } + finally + { + OnGetAuthSessionTicketResponse -= f; + } + } + public static unsafe BeginAuthResult BeginAuthSession( byte[] ticketData, SteamId steamid ) { fixed ( byte* ptr = ticketData )