Question from a developer:
I'm getting the session ticket from Steam using GetAuthSessionTicket, but LoginWithSteam in PlayFab expects a string for the ticket. If I just convert the digits to a string, that doesn't work, so what's the right way to do this?
Answer by Brendan · Nov 07, 2015 at 12:00 AM
For Steam authentication, you need to convert the ticket into a string of hexadecimal numbers. So for example, if sTicket[0] is 255, the first two characters of the string you pass in would be "FF". Here's a code snippet of how it's being converted in another game in our service:
std::stringstream s;
s << std::hex << std::setfill('0');
for (uint32_t i = 0; i < len; ++i)
s << std::setw(2) << int(ticket[i]);
Answer by Dylan Hunt · Apr 03, 2017 at 01:19 PM
For Unity C#, a bit more of use in a real situation. It's tricky because you need to wait for the callback. The callback returns the same value, but the reason to wait for the callback is to verify they own the game;
private byte[] ticketBlob; private uint ticketSize; private HAuthTicket hTicket; private string hexTicket; private Action<string> authTicketCallback; public void GetAuthSessionTicket(Action<string> callback) { // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // Validate if (!Initialized) return; if (callback != null) authTicketCallback = callback; else { Debug.LogError("[STEAM]**ERR @ GetAuthSessionTicket: callback is NULL!"); return; } // Remove old ticket (necessary here..?) try { Debug.Log("[STEAM] Cancelling old auth ticket.."); SteamUser.CancelAuthTicket(hTicket); } catch { Debug.Log("[STEAM] *Tried to cancel auth ticket, but already none (np)"); } // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> // Start ticketBlob = new byte[1024]; // Retrieve ticket; hTicket should be a field in the class so you can use it to cancel the ticket later // When you pass an object, the object can be modified by the callee. This function modifies the byte array you've passed to it. hTicket = SteamUser.GetAuthSessionTicket(ticketBlob, ticketBlob.Length, out ticketSize); // Resize the buffer to actual length Array.Resize(ref ticketBlob, (int)ticketSize); // Convert bytes to string StringBuilder sb = new StringBuilder(); foreach (byte b in ticketBlob) { sb.AppendFormat("{0:x2}", b); } hexTicket = sb.ToString(); // << This is it! But wait for callback to verify they own the game. // Wait for callback => }
// => Steam Callback private void OnGetAuthSessionTicketResponse(GetAuthSessionTicketResponse_t callback) { Debug.Log("[STEAM] Callback [" + GetAuthSessionTicketResponse_t.k_iCallback + " - GetAuthSessionTicketResponse] - " + callback.hTicket + " -- " + callback.eResult); if (callback.eResult.ToString().ToUpper() == "K_ERESULTOK") { // SUCCESS >> Debug.Log("[STEAM] @ OnGetAuthSessionTicketresponse == K_ERESULTOK"); // Callback now, saved from earlier => if (authTicketCallback != null) { authTicketCallback(hexTicket); authTicketCallback = null; // Reset } } else { Debug.LogError("[STEAM]**ERR @ OnGetauthSessionTicketResponse: Ticket was NOT OK and may not own the game: " + callback.eResult);
// Callback with null to indicate err. Probably better to use a separate callback with more err info.
if (authTicketCallback != null)
authTicketCallback(null);
}
}
That set up is one I have seen elsewhere, but does not appear to be applicable to the Facepunch.Steamworks library.
My current (and not working) approach looks like this:
public class SteamWrapper : MonoSingleton<SteamWrapper> { public const int appID = <REDACTED>; private Facepunch.Steamworks.Auth.Ticket _authTicket; public Facepunch.Steamworks.Client Client { get { return Facepunch.Steamworks.Client.Instance; } } void Start() { DontDestroyOnLoad(gameObject); Facepunch.Steamworks.Config.ForUnity(Application.platform.ToString()); //initializes the facepunch singleton instance var tmp = new Facepunch.Steamworks.Client(appID); if (Facepunch.Steamworks.Client.Instance != null) { _authTicket = Client.Auth.GetAuthSessionTicket(); } } public string GetSteamAuthTicket() { // Convert bytes to string StringBuilder sb = new StringBuilder(); foreach (byte b in _authTicket.Data) { sb.AppendFormat("{0:x2}", b); } return sb.ToString(); } }
Answer by Iengthean Sovann · Sep 28, 2020 at 02:39 AM
Hi Brendan, can you please give an example code in c++?