Hey,
I’m pretty sure a new Studio version has just rolled out. Secrets still don’t save and persist between sessions. I haven’t yet tested whether they actually work locally.
Can you confirm the fix for both of these issues has been released?
Hey,
I’m pretty sure a new Studio version has just rolled out. Secrets still don’t save and persist between sessions. I haven’t yet tested whether they actually work locally.
Can you confirm the fix for both of these issues has been released?
Release notes for version 630 haven’t been released yet, so I’m guessing we are still in version 629 even tho it’s around the time for an update. However, you should note that many updates for version 629 are still pending and not live, so even if the update has been pushed it could still be pending approval.
Might not even appear on the release notes. Some bug fixes don’t. But we’ll see
Locally-saved secrets still do not save across sessions or work at all in playtesting. It seems nothing has been fixed here. Have confirmed on version 630.
Could be the case that it hasn’t went LIVE yet.
Indeed, this is not supported. It sounds like a useful feature, allow AddPrefix/AddSuffix concatenate another secret, but here I agree with Sammy, passing multiple secrets via URL feels unnatural.
Yes, this is our usual practice, to employ “slow rollout”. We must ensure that changes do not break anything else in the system, hence the need for such practice. It is at 100% now, and should be working for everyone.
Thanks for the info. Secrets now save between Studio sessions but I still can’t seem to access them via scripts.
It likely means there is some mismatch in the JSON or script. For example, secret name, or JSON format, or secret content not being base64-encoded. If you could paste the JSON and a script, that might be helpful. We don’t validate JSON when saving it (even invalid input will be saved, but it won’t be loaded in the game server, causing “Secret not found”).
I do agree that passing the secrets as parameters is definitely unsecure. But it’s just how the Trello API (developed by Atlassian) works. Feature support for this would be very nice but I guess for now I will have to use the solution @Mmm_Wafflez came up with.
Hey again,
Not sure what happened but it seems to be working now! Thanks a lot for your continued assistance.
I’ll be sure to let you know if I experience any further issues.
I’d recommend adding a regex check to validate JSON when saving as this could be a somewhat annoying thing to debug with a pretty easy fix. Low priority ticket item tho.
Heres some examples of how to do this:
Perl and JS:
Regex strings are pretty much the same across different languages so I hope you can implement this whenever you have spare time.
How do i add a secret to this window?
I am unsure of the format and is unable to find documentation
come on man, I can’t even use it
You want to write Secrets in JSON format wrapped with curly brackets where the key is the Secret name and the value is an array with the first value as the Token and the second value as the whitelisted URL. Note that you should prepend URLs with a * (wildcard) to make sure that all subdomains associated with a domain are whitelisted aswell.
Roblox has been down just before and it caused the method GetSecret to fail (telling the secret was not found), which my game was not designed to handle at all and broke everything because I didn’t even know the method could error in this case. It would be nice to either document that this function may error in case roblox gets down (so advise to wrap in a pcall ), or either return a secret but with empty value or whatever.
edit 2: When i run local Test, i’m able to retrieve the secret, but when i try to use it in a request such as:
local response = HttpService:PostAsync(
apiUrl,
HttpService:JSONEncode(self.payload),
Enum.HttpContentType.ApplicationJson,
false,
{["api-key"] = apiKey} -- secret
)
I get the error:
Header "api-key" has unallowed character - Server
However, team test is working with the api-key i have put the web portal. therefore im assuming there is some issue with the formatting in Game Settings > Security > Secrets. how can we verify that it is being parsed correctly?
edit 1: i’m guessing it doesn’t work in command bar, it seems to work locally - however new issue: there is no documentation on how to use Secrets with PostAsync header variant or RequestAsync headers. when i try to use it i get “header must be a dictionary”. this feature is borderline useless.
command bar doesn’t appear to be working. maybe i am doing something wrong.
Sorry, I missed this message. The locally defined secret should be base64 encoded. So, the Secrets box should be: `{“test”: [“Zm9vYmFy”, “*”]}
I am making changes to documentation to provide a useful example.
ok thanks! ill test it out and see. im hoping at some point maybe we could just get like a local env file that we can import and the local secrets engine will handle it. right now i have been having it fail gracefully on local and testing normally in team test which has not been a bad experience.
Secrets can be managed programmatically, via an OpenCloud API. You need Secrets Store API System enabled for your API Key. Alternatively, you may create an OAuth App with universe.secret:read
and universe.secret:write permissions
. Since secrets are associated with Experiences, you need to know the universeID
.
Lists all secrets defined for this experience. Secret content is not returned. Requires read
permission.
Example:
curl -H 'Content-Type: application/json'\
'https://apis.roblox.com/cloud/v2/universes/<universeID>/secrets'\
-H 'x-api-key: <API Key>'
Sample Response:
{"secrets":
[{
"id":"gcp",
"domain":"*.google.com",
"created":"2023-11-07T18:15:01.809Z",
"updated":"2023-11-07T18:15:01.809Z"
}],
"nextPageCursor":"n2o2djcA",
"previousPageCursor":"p2o2djcA"
}
Retrieves the public key for your experience. You need it to encrypt the secret content before sending it to Roblox. The API requires read
permission.
Example:
curl -H 'Content-Type: application/json'\
'https://apis.roblox.com/cloud/v2/universes/<universeID>/secrets/public-key'\
-H 'x-api-key: <API Key>'
Sample Response:
{
"id":"public-key",
"secret":"Zgj4+V7vSaEZ06rXazKJUIcUnVa95tUNiwXAif/vdHo=",
"key_id":"1200590785272263122"
}
Creates a new Secret (fails if a secret with this name already exists), which requires write permission. The secret must be encrypted before sending it to Roblox. Encrypt your secret using LibSodium sealed box. The example below uses Python and PyNaCl to create a sealed box (run pip install pynacl
to install it locally).
Create Python script with this content (use your own public key and secret content there):
from base64 import b64encode
from nacl import encoding, public
public_key = "Zgj4+V7vSaEZ06rXazKJUIcUnVa95tUNiwXAif/vdHo="
secret_content = "my_api_key_content"
public_key = public.PublicKey(public_key.encode("utf-8"), encoding.Base64Encoder())
sealed_box = public.SealedBox(public_key)
encrypted = sealed_box.encrypt(secret_content.encode("utf-8"))
print(b64encode(encrypted).decode("utf-8"))
Run the script python3 seal_box.py
. Script output is your encrypted secret, e.g. Bgy1ky7Se3xSquRc1b/T1C1FIxXbEDppMRA2trpJy1luT7NY6UQDT+rk6qnnGq09lQl9EQQU5xKsWCk=
Example creating a new secret and sending encrypted content:
curl -H 'Content-Type: application/json'\ 'https://apis.roblox.com/cloud/v2/universes/<universeID>/secrets'\
-d '{"id":"gcp","domain":"*.google.com",
"secret":"Bgy1ky7Se3xSquRc1b/T1C1FIxXbEDppMRA2trpJy1luT7NY6UQDT+rk6qnnGq09lQl9EQQU5xKsWCk=", "key_id":"1200590785272263122"}'\
-H 'x-api-key: <API Key>'
Sample Response:
{
"id":"gcp",
"created":"2023-11-07T18:15:01.809Z",
"updated":"2023-11-07T18:15:01.809Z"
}
Use the same encryption script to get the sealed box. Requires write
permission.
Example:
curl -X PATCH -H 'Content-Type: application/json'\
'https://apis.roblox.com/cloud/v2/universes/<universeID>/secrets/gcp'\
-d '{"secret":"rlkpVPeg+Fyh+eSTGLTySlQBV8MszuOcvq56SGWHLU39avqLw24bDmkhQHms+6NOlnJ6kiPbCG1KE70=", "key_id":"1200590785272263122"}'\
-H 'x-api-key: <API Key>'
Sample Response:
{"updated":"2023-11-07T18:23:53.334Z"}
Requires write
permission.
Example:
curl -X DELETE -H 'Content-Type: application/json'\
'https://apis.roblox.com/cloud/v2/universes/<universeID>/secrets/gcp'\
-H 'x-api-key: <API Key>'
Response:
HTTP status code 200 when successful.