Keys are stored as hashes
When you create a key, you get it back once and we keep only a hash. A copy of our database wouldn’t give anyone a working key, and we can’t show a key again. So show the key when it’s created and let users roll it over. Don’t promise to show it later. See Key storage.Recovery is opt-in and separately permissioned
If your product must show a key more than once, we can turn on encrypted storage for a keyspace. Keys created withrecoverable: true are then also stored encrypted with keys unique to your workspace. It’s off by default. Creating a recoverable key needs the encrypt_key permission, and reading one back needs decrypt_key, so you can grant recovery narrowly. See Recovering keys for the trade-offs and Recoverable keys for the steps.
Verification doesn’t leak
keys.verifyKey returns NOT_FOUND for several failures, including a root key without permission for the keyspace, so nobody can use it to find out which keys exist. Every verification is recorded in analytics, and verifications made with a root key are also in the audit log.
IP allow lists
A keyspace can have a list of IP addresses its keys can be verified from. Verification from anywhere else fails withFORBIDDEN. Use it for keys that should only be used from your own servers. See Keyspace settings.
Delete protection
With delete protection on, you can’t delete a keyspace until you turn protection off, so one wrong call can’t wipe out a production keyspace and all its keys. See Delete protection.Root keys are scoped
A root key has only the permissions you give it, down to one keyspace. For example,api.<api_id>.verify_key lets a service verify keys in one keyspace and nothing else. Give each service its own root key with as few permissions as it needs, so a leaked key does little damage and is easy to replace. See Root key permissions.
Leaked credentials
GitHub’s secret scanning recognizes root keys by theirunkey_ prefix. If one is pushed to a public repository, every member of your workspace gets an email. The keys you issue to your users use your own prefixes, and GitHub doesn’t scan for them, so delete or reroll a user’s key yourself when you learn it leaked. Details are on GitHub secret scanning.