GDay Creators,
Today we’re launching the Secrets Store. Announced at RDC 2023, this service lets you keep Secrets - for example, API Keys - separate from your code. Previously in beta, we’re now making it available to everyone.
What is the Secrets Store?
Roblox HttpService allows game servers to send HTTP requests to external services, usually requiring authentication. The most popular way is API Key authentication, when the secret is sent as a request header. Previously, creators had to store secrets as plain text in Luau scripts, or in Datastores.
Now you can leverage the Roblox Secrets Store to prevent API key leaks. We’re releasing a new method GetSecret, provided by the HttpService, which returns a secret that can be used in the HttpService:RequestAsync
function call. The secret content is not printable, by design. Secret(SecretId)
is printed instead of the actual content. Secrets are available in Production (game servers) or in the Team Create environment. For security reasons, experiences running locally cannot use Secrets.
Creating and updating Secrets
Navigate to your Experience in the Creator Hub and find the Secrets page under Configure.
Secret content cannot be retrieved through the Creator Hub. Secrets are encrypted using your Experience public key before they are sent to Roblox. Encryption is performed locally in your browser. When the game server starts, it retrieves all associated secrets from the Secrets Store and decrypts the content.
You can change the Secret content and domain restrictions:
Note: updated secrets are not pushed to currently running game servers. If you create a new secret, update or delete an existing one, you need to restart the game server for new values to take effect. This protects your experience from global outages, should the secret content happen to be invalid.
Using Secrets
Secrets Store provides a safer replacement for plain text secrets in the source code. For example, if you had a Yelp integration with the hardcoded API Key:
local yelpApiKey = "CZhtkLDpNYXgPH9Ml6shqh2OwykChw"
You can replace it with the following, provided that you uploaded your Yelp secret for the experience:
local yelpApiKey = HttpService:GetSecret("yelp")
It is possible to store the secret together with some extra text (e.g. Bearer CZhtkLDpNYXgPH9Ml6shqh2OwykChw
). However, storing just the key and applying a transformation in the Luau script source code may be more convenient.
Transformations
There are two basic transformations, addPrefix and addSuffix, that you can apply to the secret content. The former inserts a string at the beginning of the secret content, designed to prepend header names. For example, Bearer
string, as in the Yelp example below:
local yelpApiKey = HttpService:GetSecret("yelp_api_key")
local url = "https://api.yelp.com/v3/businesses/search?location="
.. location .. "&term=restaurants&categories=&price=2&sort_by=best_match&limit=5"
local response = HttpService:RequestAsync({
Url = url,
Method = "GET",
Headers = {
["accept"] = "application/json",
["Authorization"] = yelpApiKey:AddPrefix("Bearer ")
}
})
Use AddSuffix to append a string to the secret. Below is an example of creating a URL containing an API key. Be aware that secret content must be URL encoded for this to work.
local mySiteApiKey = HttpService:GetSecret("my_site")
local url = "https://apis.mysite.com/?apiKey="
local suffix = "&request=join&user=myname"
local urlWithKey = mySiteApiKey:addPrefix(url)
local resultingUrl = urlWithKey:AddSuffix(suffix)
Domain Restriction
Every secret is associated with a domain name. If the domain name is empty, the secret cannot be sent over the network (and therefore could not be used as an API key). Set the domain name to star (*) to allow sending the secret anywhere. You can limit the URL to a specific domain name (e.g. apis.myservice.com
), or subdomains of a domain (e.g. *.myservice.org
). Using the star anywhere except the first character is not supported.
Limitations
- Secrets cannot be used in the HTTP request body.
- Secret content cannot be larger than 1024 bytes.
- There is a limit of 500 secrets per experience.
- For group-owned experience, only the group owner is allowed to view and edit Secrets.
Next steps
- We’re working on expanding OpenCloud APIs support for Secret Store
- We are looking to implement advanced permissions for group-owned experiences to provide more flexibility than limiting access to group owners.
- Last, but not least, we’re considering upgrading HttpService with mutual TLS (mTLS, also known as “client certificates”), with Secrets Store used for private keys.
Thank you for your feedback so far! Please reply to this post with any questions or concerns.
Cheers,
The Roblox Creator Services Team