question

brendan avatar image
brendan asked

How do I convert the Steam Session Ticket for sign-in with PlayFab?

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?

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

brendan avatar image
brendan answered

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]);
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Dylan Hunt avatar image
Dylan Hunt answered

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

}

1 comment
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

nicki avatar image nicki commented ·

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

0 Likes 0 ·
Iengthean Sovann avatar image
Iengthean Sovann answered

Hi Brendan, can you please give an example code in c++?

10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.