Provide a native way to verify a HTTP request is from Roblox

I have worked on multiple different methods of verifying the legitimacy of Roblox HTTP requests, and as a developer on the platform, it’s pretty tricky (and very hacky) to do.

Roblox adding a native method for verifying an HTTP request would not only drastically improve my, and others workflow, but it would also improve the reliability, speed and security of any existing methods out there.

One could argue that you can “have a private API key.” However, in some environments, this doesn’t always work. What if your games API key gets leaked without you knowing? By the time you find out the damage could have already been done.

I am working on my project, Devable, and it is critical that unauthorised requests that aren’t from Roblox don’t get made. For example, we whitelist games based on the game ID or account ID. This is because someone can leak their API key and allow others to use the products they have purchased (refer to https://devable.org for context). If we know for sure a request is from Roblox then we know that the place id that came with it is also legitimate and can, therefore, use it for authentication.


Roblox could provide an rbx-sig header which contains an HMAC. There could then be an API that would take this HMAC and return whether or not it is valid. The API should also return metadata like the place it came from, the job id, the place owner, etc.

Another option could be a one-time JWT token. Once again it could come in an rbx-sig header. Roblox should, again, provide an API that verifies the integrity of the JWT token and then returns the decoded version (or errors if it’s not legitimate). The JWT token could then contain the claims (and potentially custom claims defined within the Roblox game).

Defining custom claims could work like so:

local httpService = game:GetService('HttpService')

httpService:SetCustomClaims({
	foo = bar
})

-- Send the request with the custom claims
-- Once decoded the server can access the custom claims
httpService:PostAsync(...)
Another method by @berezaa

I’m pretty new to the cryptography world, so please correct me if the authentication methods above wouldn’t work for this scenario and provide possible alternatives!

Thanks!

Edit: For clarification, verifying could work like this (from your end):

  1. Request to your server
  2. Server takes signature
  3. The server sends the signature to Roblox API for verification
  4. Roblox API either errors or returns claims
25 Likes

+1. I’m currently working on a web app for my game and it sends chills down my spine to have to use an authorization key in my requests that has to be stored in plaintext in a script. Storing the key in a datastore is only marginally better. I imagine this method completely falls apart when making a web app that is intended for multiple games with different developers. Would love to see the potential of Roblox web apps expanded with a feature like this.

From my understanding of cryptology, Roblox wouldn’t even need to provide API to verify that a signature is correct. The HTTP request would send information like you mentioned, the jobId, gameId, placeId, etc. of the Roblox web server that sent the HTTP request. That information would be sent with an accompanying PGP signature. Roblox could publish their PGP public key, and anyone with that key could use it along with the message and the signature to verify that the contents of the information are legitimate and came from Roblox.

PGP Example

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA512

Anyone can copy someone else’s GPG public key, but only the true
owner can make a digital signature that validates for that key,
or decrypt messages encrypted to that key.

GPG is what establishes identity in the way you’re describing.

You can import my public key from
https://np.reddit.com/r/publickeyexchange/comments/2cmfob/sapiophiles_public_key/
and validate the signature on this comment (or send me an encrypted
message) using GPG if you’d like to see it in action.
-----BEGIN PGP SIGNATURE-----

iQIcBAEBCgAGBQJVjixxAAoJEJdH3pe6/Nu5EJUP/iXdLbAAIrjmXYlfeTrQNA1w
nSOBT36O95sdZs4GD5lMdDNqjOcY8QkPGQHiU47EoIezcdaqVS5lg2E782ADC2is
dK2Nfga05QsCjMKWp3azeX9g0JWUGHi0mlSUDDMckLVklq4bCqHTIgrYFMBvhPkO
QUedjRzCoR/fArRw+QEtoTsDoTJJVzUJkBOykpRsS+d6M3MlrNjUpvxZB4Rw+6wx
6M09Dg8xFaa7On021uXmcXx5UcWr5iKUmN1d9H/5WX3IJMRpDeOJGrU8ZYVwfvpG
9wBKnIJ5C1+1ix2U4rI+WoWMUO+8WfDyw+DHZs0ZD+ADnCTTRrDQwNPex4uqbd/t
lJKQJICTim9pgFOcPEvX25FaXJY6sak6MTVtPbZNjesE9C6zwg0KI62ZYyhQ1Xhm
xqegmrBUiS0S9UeA80G7jOxRm4tHYqAsLth0RO7RBll1urwai2oCd3Pnq1C2BYC5
V9i745tY4PhBkI5zxegiTR/KN5X8RPhE8IIxs804G7blPQBCOMYDWxPd8RLRCbZr
5dKaUAYvBWdJnE2/137Jq7qgGHvj+yBgL/PqGsejyz0s5fe0borKGVNHDmGrnQJj
BUB+mz7+7wkrrUxkQRc2tR/e1vZETAR8SkZwY5Sr8gl3m5jhC4GYR1baKowxtcSc
ArH9ynW15UsCIr2/A2jM
=fa8+
-----END PGP SIGNATURE-----

15 Likes

Couldn’t requests just use a consistent HTTPS certificate that web servers can verify as belonging to Roblox?

2 Likes

That’s a good idea. However (as far as I’m aware), you can’t put an SSL cert on an IP.

1 Like

What I mean is to have Roblox force their HTTP client to use a specific cert owned by Roblox. On the game server side, all developers have to do is use https:// when they use HttpService.

1 Like

Could you elaborate more?

As far as I can tell what you’re saying is that I can access the SSL certificate of the requester? If that’s what you’re saying then that’s not the case.

  1. Roblox owns the certificate “ROBLOX_CERT”.
  2. A script calls HttpService with a https:// URL.
  3. The game server (sender) makes the request using ROBLOX_CERT for the SSL handshake.
  4. The web server (receiver) inspects the certificate of the incoming request to make sure it is known to be owned by Roblox.

The web server would have to have low-level functions for inspecting the certificates of requests, which I guess may not be a thing on every framework.

1 Like

Yeah I see what you’re saying now. While it would probably work in some cases, a lot of the time people run web apps on cloud providers (things like kubernetes too) which wouldn’t allow for this because they handle all that stuff on their own.

Roblox should introduce a better solution.

3 Likes