Steamworks getAuthTicketForWebApi

Not favoritedFavorited Favorited 0 favourites
  • Heya!

    First off, thanks for the great work on the Steamworks plugin! Appreciate the latest update.

    I'm currently building a game that uses a custom backend server, and I've run into a security need. To safely validate that API requests are actually coming from an authenticated player, my server needs to verify an auth ticket from the client. The standard way to do this is by having the client generate a ticket using Steam's GetAuthTicketForWebApi function and sending it with each request.

    This function isn't currently exposed in the plugin's actions. It would be sweet if you could add a scripting function to get this ticket. An async function that fits the style of the current API would be perfect, something like:

    // Awaiting this promise would return the ticket string const ticket = await runtime.objects.Steamworks.getFirstInstance().getAuthTicketForWebApi();

  • It's not entirely clear to me how this all works - looking at GetTicketForWebApiResponse_t in the documentation, it looks like you get both a HAuthTicket (really a uint32) and m_rgubTicket which appears to be a block of binary data up to 2560 bytes long. Do you only need the HAuthTicket?

  • My server needs the m_rgubTicket data. I just send that ticket string to Steam's web API to verify the user.

    The HAuthTicket handle is just for the client to use, my server never sees it.

    So if the async function could just return the m_rgubTicket as a hex string, that'd be perfect.

  • I've implemented this for the next release of the Steamworks plugin. If you're feeling brave you can try the code already on the GitHub repo which supports Windows, but otherwise I will update the macOS/Linux builds next week and release the update.

  • Try Construct 3

    Develop games in your browser. Powerful, performant & highly capable.

    Try Now Construct 3 users don't see these ads
  • Oh wow, I checked out the commit and it looks great! This is why I recommend Construct 3 to everyone—support is top notch and consistent (across decades). Thanks Ashley!

  • I just published an update to the Steamworks addon (v1.4.1) which includes the authentication ticket features. Let me know if it's all working for you.

  • Heya! Following up, the getAuthTicketForWebApi feature seems to be working great, and my server is correctly validating the tickets. Fantastic!

    But there's a slight problem. I've run into an edge case with Steam Family Sharing that I wanted to bring to your attention. When someone plays my game via Family Sharing, I've found that the auth ticket generated by the plugin correctly belongs to the player's account. However, the Steam.StaticAccountKey expression returns the Steam ID of the owner's account.

    This creates a mismatch that my backend server flags as an invalid request (as it should). It sees a valid ticket for Player A, but the request claims to be from Player B. My AI took a peek at the GitHub repo to understand it better, and noticed the user ID is retrieved from the UserStatsReceived_t callback. A potential fix might be to use the standard SDK function SteamUser()->GetSteamID() instead. This synchronous call should always return the ID of the actual current player, which would resolve the issue in Family Sharing scenarios.

    I could just use the ID from the validated ticket as a source of truth.. However I think it should be addressed at the root, as I have other logic in my client that utilizes Steam.StaticAccountKey.

  • My AI took a peek at the GitHub repo to understand it better, and noticed the user ID is retrieved from the UserStatsReceived_t callback.

    That's incorrect - the plugin actually ignores that event (typical AI hallucination...) It currently just logs to the console in that event and does nothing about it.

    A potential fix might be to use the standard SDK function SteamUser()->GetSteamID() instead. This synchronous call should always return the ID of the actual current player, which would resolve the issue in Family Sharing scenarios.

    This is what the plugin already does: it ends up calling SteamUser()->GetSteamID().GetStaticAccountKey().

    So I'm not sure what the problem would be - perhaps there's some other ID we need to expose with the plugin, but I don't know what that would be - it probably depends on how all the server-side validation works. It might be a good idea to ask Valve for support.

  • True, alrighty I think this is more informative: The ticket’s steamid is the authoritative player identity; exposing both GetSteamID() and GetAppOwner() on the client will make Family Sharing behavior explicit.

    So it seems my initial comment was not the complete picture. Using a single “StaticAccountKey” (derived from SteamUser()->GetSteamID().GetStaticAccountKey()) is not great due to this concept of borrower vs owner.

    The Web API AuthenticateUserTicket returns both identities: the actual player steamid and the ownersteamid. This means identity can differ in Family Sharing and that the ticket’s steamid is the authoritative player identity for auth.

    So maybe we can expose two explicit accessors alongside any existing “static account key”?:

    Borrower ID (64-bit): SteamUser()->GetSteamID().ConvertToUint64()

    Owner ID (64-bit): ISteamApps()->GetAppOwner().ConvertToUint64()

    Then it aligns client API with what the server must already handle (two IDs).

  • OK, I'll look in to exposing the app owner account details via the plugin.

  • Appreciate it!

  • I just published an update to the Steamworks addon (v1.4.2) which includes the new expressions AppOwnerAccountID and AppOwnerStaticAccountKey (based on the Steam ID of GetAppOwner()). Hopefully that now covers everything you need.

  • Works great! Thanks for adding it!

  • Me again, I think I found a weird bug. I had submitted my game to Steam for review, and they noticed a discrepancy in the Cloud save feature—which led me down a rabbit hole, and I think the plugin's Steam.StaticAccountKey is not returning the actual 64-bit ID. This prevents Steam Cloud from working correctly with the file path tag {64BitSteamID}.

    At first I thought maybe something is borked with my Steam account, but then I tested this out on two separate accounts and encountered the same issue. For context, one account is like my 'developer' account and the other is just a regular Steam account that I gave a Steam key to—so it's completely fresh. Yet the issue persisted (just with different ID numbers). So we can safely rule out my account as being wonky.

    Anyhow, I wrote a debug function to display this:

    str(Steamworks.AccountID) & newline &
    str(Steamworks.StaticAccountKey) & newline &
    str(Steamworks.AppOwnerAccountID) & newline &
    str(Steamworks.AppOwnerStaticAccountKey)
    

    and this was the output

    // My actual Player ID is ***2851 (32-bit I believe would be: ***7123)
    // The unknown ID (seemingly the owner) is ***5555
    
    ***7123 // Probably my actual 32-bit ID
    ***5555 // Unsure - I guess the Owner's 64-bit ID?
    ***7123 // Same as AccountID
    ***5555 // Same as StaticAccountKey
    

    It looks like the two separate 64-bit IDs point to the same looking account when I search it up on: steamcommunity.com/profiles/***851/)

    I've confirmed this is NOT a Steam Cloud sysnc issue or anything like that by hard cording the ID to write in file path and such. The issue stems from StaticAccountKey not giving me the exact key that {64BitSteamID} (and my steam profile page) is giving me, and what I expect it to be.

    Your implementation (the WrapperExtension.cpp) looks fine to me, so I'm quite confused.

    Any ideas? I am able to consistently derive the correct ID via the GetAuthTicketForWebApi() feature you recently implemented (serverside only though). I just wanted to mention that.

  • I don't know what to say - the plugin returns SteamUser()->GetSteamID().GetStaticAccountKey() (as a string to ensure a 64-bit number is preserved). If that is not right, I'm not sure what else it should be accessing, and you'd need to ask Valve what it should be doing instead.

Jump to:
Active Users
There are 0 visitors browsing this topic (0 users and 0 guests)