FQL v4 will be decommissioned on June 30, 2025. Ensure that you complete your migration from FQL v4 to FQL v10 by that date. For more details, review the migration guide. Contact support@fauna.com with any questions. |
Keys
Fauna keys provide anonymous-based access to a database.
Anyone who possesses the secret for a Fauna key can access the database associated with the key and perform any operations that are permitted by the key’s role (see Access roles). Keys are typically used by database owners or administrators to manage database structure and contents with few restrictions, and by background tasks that automate various database procedures at regular intervals.
When a key is created, you must copy the key’s secret out of the query result when it is first created, and store it securely. It is impossible to recover the key’s secret if it is discarded or lost, because the key only stores the BCrypt hash of the secret.
A key’s secret is then included as a bearer token in Fauna queries:
Anonymous-based authentication and access control with Fauna keys
-
The client send a query to Fauna, and the request includes the secret for a Key as an HTTP bearer token header.
-
If the secret exists, Fauna looks up the associated Key document. If not, the response is
Unauthorized
. -
If the Key exists and has not expired (due to
ttl
), Fauna evaluates the Key’srole
field within the database associated with the Key. The active role could be a built-in role or an ABAC role, and determines whether the query should be permitted to execute. If not, the response isUnauthorized
. -
If the Key provides permission, the query is executed and the response is returned.
A key’s secret can be used in multiple queries until its key becomes invalid or is deleted.
Keys are defined as documents within the system keys collection. Like databases, keys exist within the system-global root database context. Keys are tied to a specific database and allow access to its contents. If no database is specified, the key grants access to the database in which it was created. The level of access that a key provides depends on its role.
A key’s secret is a password equivalent. Guard secrets with the same care and attention that you use for passwords. |
Beginning with Fauna 2.11.0, the Fauna access control logic has been changed to use attribute-based access control (ABAC) roles, or the key-based permission system, but never both. If a resource is a member of an ABAC role, the ABAC role specifies all privileges for that resource. Otherwise, the key-based permission system determines whether read/write/execute privileges are enabled. For example, when an ABAC role includes a user-defined function as a
member, that function cannot be called unless the ABAC privileges permit
the |
Access roles
Keys belong to one of four built-in roles, either admin
, server
,
server-readonly
, or client
, or to one or more used-defined roles.
Admin role
Keys with the admin
role are used for managing their associated
database, including the database’s access providers, child databases,
documents, functions, indexes, keys, tokens, and user-defined roles.
Since a key with the admin
role can be used, in its associated
database, to create and destroy child databases, and to modify any
document content or access controls, they should be very well
protected.
Admin keys for Fauna accounts are managed in the Fauna Dashboard.
Server role
Keys with the server
role are used for managing their associated
database, including the database’s documents, functions, and indexes.
Unlike the admin
role, user-defined roles and child databases
(including child database documents, of any kind) cannot be directly
managed with a server
role.
Otherwise, the server
role is equivalent in all other respects to the
admin
role. They should be very well protected.
The |
Server read-only role
Keys with the server-readonly
role allow read-only access to all data
within the database that they are assigned to. Because they provide
unrestricted read access, they should be well protected and only used in
trusted or server-side environments.
User-defined role
Keys can specify one or more user-defined roles. The privileges for such a key are specified by the associated role(s).
Keys having user-defined roles are, essentially, equivalent to tokens, in that there are no specific privileges provided by default, but there is no associated identity.
Client role
Keys with the client
role are restricted to actions and resources that
are specifically marked with the public
permission. Because their
access is controlled, they are suitable for embedding in untrusted
environments, such as mobile clients.
Typically they are used as part of an application’s user authentication flow, or to access public data, such as an application’s logged-out view.
Client keys and roles, and See Deprecations for more details. |
Scoped keys
There are several situations where you might want to impersonate access to a database, because regular access is more difficult or you are lacking information. For example:
-
You have a reporting tool that needs to gather information from all of your child databases. To access a child database, you would typically need to use a secret associated with each child database. With hundreds or thousands of child databases, managing those secrets is challenging.
-
Your application performs queries on behalf of users, and you need to test that functionality and/or access controls are working correctly. However, you don’t have access to any user’s password in order to call
Login
. -
Similarly, your applications provides different functionality for users with differing roles, and you need to test the functionality and access controls.
To facilitate these use cases, Fauna accepts a scoped key. A scoped key allows you to use a secret that you already possess to impersonate access to Fauna in several ways. However, it is not possible to use a scoped key to gain additional privileges.
A scoped key is formed from the secret of a key that you already possess, plus some additional information that provides three impersonation alternatives:
-
secret[:child_database]:role
Where:
-
secret
is the key’s secret. An admin key is required to access a child database. -
child_database
is the name of a child database (optional). When specified, thesecret
for an admin key must be used. When not specified, thesecret
from an admin or server key can be used. -
role
is the name of a system role to use, one ofadmin
,server
,server-readonly
, orclient
.
This kind of scoped key would typically be used to impersonate access to a child database.
For example:
fnACysRJGIACAHiL_5f0UxHlPFIZgq876ptMNJ72:posts:admin
Provided that the secret belong to an
admin
key, this scoped key provides full access to the child database calledposts
. -
-
secret[:child_database]:@doc/collection/id
Where:
-
secret
is the key’s secret. An admin key is required to access a child database. -
child_database
is the name of a child database (optional). When specified, thesecret
for an admin key must be used. When not specified, thesecret
from an admin or server key can be used. -
collection
is the name of a collection in the current database, or ifchild_database
is specified, in the child database. -
id
is the document ID for the document to authorize as. Document IDs are string-encoded 64-bit integers.
This kind of scoped key would be used to impersonate a specific user.
For example:
fnACysRJGIACAHiL_5f0UxHlPFIZgq876ptMNJ72:@doc/users/1234
This scoped key would have the same privileges as the authenticated
Ref(Collection("users"), 1234)
document. -
-
secret[:child_database]:@role/name
Where:
-
secret
is the key’s secret. An admin key is required to access a child database. -
child_database
is the name of a child database (optional). When specified, thesecret
for an admin key must be used. When not specified, thesecret
from an admin or server key can be used. -
name
is the name of an ABAC role to authorize as.
This kind of scoped key would be used to impersonate any user having the privileges of the specified role.
For example:
fnACysRJGIACAHiL_5f0UxHlPFIZgq876ptMNJ72:@role/developers
This scoped key would have the same privileges as any member document with the
developers
role. -
In each case [:child_database]
refers to an optional child database
name. The name can use slashes to refer to grandchild and
great-grandchild databases (with unlimited nesting). For example:
-
secret:test:admin
is a scoped key with theadmin
role for the current database’s child database calledtest
. -
secret:test/performance:server
is a scoped key with theserver
role for a database calledperformance
in the current database’s child database calledtest
.
The Dashboard Shell’s "Run As" feature uses scoped keys.
"Run As" allows you to run a query using different roles, which simplifies evaluating your user-defined roles:
Once specified, queries that you execute in the Dashboard Shell run using the selected role or identity document. |
Definition
{
ref: Ref(Keys(), "265969362433737234"),
ts: 1589906999970000,
name: 'A server key for my_app',
role: 'server',
hashed_secret: '$2a$05$o6GjiF54FaZ6IBy4Qaxiz.NybQ0BcFGaze4WZ178VaTMUT.voXw5G'
}
Field name | Value type | Description | ||
---|---|---|---|---|
|
Reference |
The reference for this key. |
||
|
Long |
The timestamp, with microsecond resolution, associated with the creation of the key. |
||
|
String |
Optional - The key’s user-defined name. |
||
|
String |
The key’s role. Either
|
||
|
String |
The key’s authentication secret. Only present on creation of a key, not recoverable if lost or discarded. |
||
|
String |
The key’s hashed authentication secret. |
||
|
Number |
A priority between 1 and 500, inclusive. Defaults to 1.
|
||
|
Reference |
Optional - A reference for the database associated with this key. When not provided, the key is associated with the database in which it was created (the current database). |
||
|
Object |
Optional - User-defined metadata for the key. |
Key management
Reading or writing key documents requires an admin key or equivalent Attribute-based access control (ABAC) permissions.
Create a key
This example creates a key with a custom document ID, to make it easy to refer to in subsequent examples.
{
ref: Ref(Keys(), "10"),
ts: 1622570210270000,
database: Database("prydain"),
role: 'server',
secret: 'fnAAAAAAAAAACoN0A5ubTm47tR91JxqPlwT_-CbI',
hashed_secret: '$2a$05$QdVl/iiY6zuLarg4UkuWsujjtfj246d4lyglOLBmcsunpTm6M.d8i'
}
{'ref': Ref(id=10, collection=Ref(id=keys)), 'ts': 1622570214350000, 'database': Ref(id=prydain, collection=Ref(id=databases)), 'role': 'server', 'secret': 'fnAAAAAAAAAACgkusOundYlMZWkrN6FfB0aIiHM3', 'hashed_secret': '$2a$05$sZ3WNGNUKBGcJZ5TYJ26YuFD197LT8JWvWZFf582rX1yh3x7xb7xa'}
map[database:{prydain 0xc000109c20 0xc000109c20 <nil>} hashed_secret:$2a$05$XivqEwum/aF0kBXjp6vDJe7KTX0od5snoq6.nWDlXnG1X9CGLuPim ref:{10 0xc000109b30 0xc000109b30 <nil>} role:server secret:fnAAAAAAAAAACuZGZ4F3v-q357JhKVPbCxhcyLUt ts:1622570158160000]
ObjectV(ref: RefV(id = "10", collection = RefV(id = "keys")),ts: LongV(1622570134070000),database: RefV(id = "prydain", collection = RefV(id = "databases")),role: StringV(server),secret: StringV(fnAAAAAAAAAACn0kUwkshUUXzZTKE7YAmU0_oCm5),hashed_secret: StringV($2a$05$qm2Em6pmKksAwXEEGwyE5eSEorjy9DtvjXzPtm2Dj3y79CDZv42Ne))
{
ref: Ref(Keys(), "10"),
ts: 1624310590670000,
database: Database("prydain"),
role: 'server',
secret: 'fnAAAAAAAAAACuHWsfY88SXrHkVM95Fnjiseenyf',
hashed_secret: '$2a$05$PLRDauz7KMnS95.y6Z36Ou5/wcsI8ZOYFlrCrIaUrr9LUp/oL2fyO'
}
Normally, keys would be created like this:
{
ref: Ref(Keys(), "300219221209514496"),
ts: 1622570210570000,
database: Database("prydain"),
role: 'server',
secret: 'fnAEKpfKgvACAO2iHElhrfX4kI-1tqzFsF1vnp7G',
hashed_secret: '$2a$05$4q2pVlw6K73s5/HJXXEF9uqFlvOXAL6DDxhSgaG7fs69Iao9JS0t.'
}
{'ref': Ref(id=300219225491898880, collection=Ref(id=keys)), 'ts': 1622570214660000, 'database': Ref(id=prydain, collection=Ref(id=databases)), 'role': 'server', 'secret': 'fnAEKpfLgjACAOa4PY2rIlz0tKY3FcM1gUcPjUGE', 'hashed_secret': '$2a$05$0oluC2QmIN3Ym6cgEoAtAOgpPinlqSwjDSHj5f3LVS5OSI13B1i3O'}
map[database:{prydain 0xc000113a40 0xc000113a40 <nil>} hashed_secret:$2a$05$QtOi9l/TNkdRutE/8HkyNeposuQlZUoIpQhtJaSQ2Gu4AvdfSJ5nO ref:{300219167344165376 0xc000113950 0xc000113950 <nil>} role:server secret:fnAEKpe9-FACAE92aUsl_o8MDMdoSaI0ATcVJG8S ts:1622570159200000]
ObjectV(ref: RefV(id = "300219145590407680", collection = RefV(id = "keys")),ts: LongV(1622570138450000),database: RefV(id = "prydain", collection = RefV(id = "databases")),role: StringV(server),secret: StringV(fnAEKpe457ACAOO8a26wJI31icC-IYtiTlCEECtN),hashed_secret: StringV($2a$05$.8vgPhuXh3ZIAP3Mpt7wwunbNTA97he0hWI2gvOqtGVVxDRMmZmwe))
{
ref: Ref(Keys(), "302044142673854976"),
ts: 1624310591300000,
database: Database("prydain"),
role: 'server',
secret: 'fnAEMROMJpACAHm8GoTLAbGbGvlBnU1hPPSg1JB5',
hashed_secret: '$2a$05$N6mjK9dPfpJW.KXzDekpKOXclTcwBff/GfX1ZlP0Wp/r5eIBS6ZsC'
}
You cannot create a key with greater privileges than the key you are already using. |
Paginate all keys
{
data: [
Ref(Keys(), "1"),
Ref(Keys(), "2"),
Ref(Keys(), "10"),
Ref(Keys(), "300219221209514496")
]
}
{'data': [Ref(id=1, collection=Ref(id=keys)), Ref(id=2, collection=Ref(id=keys)), Ref(id=10, collection=Ref(id=keys)), Ref(id=300219225491898880, collection=Ref(id=keys))]}
map[data:[{1 0xc0000924b0 0xc0000924b0 <nil>} {2 0xc0000925a0 0xc0000925a0 <nil>} {10 0xc000092690 0xc000092690 <nil>} {300219167344165376 0xc000092780 0xc000092780 <nil>}]]
ObjectV(data: Arr(RefV(id = "1", collection = RefV(id = "keys")), RefV(id = "2", collection = RefV(id = "keys")), RefV(id = "10", collection = RefV(id = "keys")), RefV(id = "300219145590407680", collection = RefV(id = "keys"))))
{
data: [
Ref(Keys(), "1"),
Ref(Keys(), "2"),
Ref(Keys(), "10"),
Ref(Keys(), "302044142673854976")
]
}
Get a key
{
ref: Ref(Keys(), "10"),
ts: 1622570210270000,
database: Database("prydain"),
role: 'server',
hashed_secret: '$2a$05$QdVl/iiY6zuLarg4UkuWsujjtfj246d4lyglOLBmcsunpTm6M.d8i'
}
{'ref': Ref(id=10, collection=Ref(id=keys)), 'ts': 1622570214350000, 'database': Ref(id=prydain, collection=Ref(id=databases)), 'role': 'server', 'hashed_secret': '$2a$05$sZ3WNGNUKBGcJZ5TYJ26YuFD197LT8JWvWZFf582rX1yh3x7xb7xa'}
map[database:{prydain 0xc00009b9b0 0xc00009b9b0 <nil>} hashed_secret:$2a$05$XivqEwum/aF0kBXjp6vDJe7KTX0od5snoq6.nWDlXnG1X9CGLuPim ref:{10 0xc00009b8c0 0xc00009b8c0 <nil>} role:server ts:1622570158160000]
ObjectV(ref: RefV(id = "10", collection = RefV(id = "keys")),ts: LongV(1622570134070000),database: RefV(id = "prydain", collection = RefV(id = "databases")),role: StringV(server),hashed_secret: StringV($2a$05$qm2Em6pmKksAwXEEGwyE5eSEorjy9DtvjXzPtm2Dj3y79CDZv42Ne))
{
ref: Ref(Keys(), "10"),
ts: 1624310590670000,
database: Database("prydain"),
role: 'server',
hashed_secret: '$2a$05$PLRDauz7KMnS95.y6Z36Ou5/wcsI8ZOYFlrCrIaUrr9LUp/oL2fyO'
}
Update a key
Rename a key, or modify its optional user-defined metadata (the data
field) by using the Update
function.
Delete a key
{
ref: Ref(Keys(), "10"),
ts: 1622570210270000,
database: Database("prydain"),
role: 'server',
hashed_secret: '$2a$05$QdVl/iiY6zuLarg4UkuWsujjtfj246d4lyglOLBmcsunpTm6M.d8i'
}
{'ref': Ref(id=10, collection=Ref(id=keys)), 'ts': 1622570214350000, 'database': Ref(id=prydain, collection=Ref(id=databases)), 'role': 'server', 'hashed_secret': '$2a$05$sZ3WNGNUKBGcJZ5TYJ26YuFD197LT8JWvWZFf582rX1yh3x7xb7xa'}
map[database:{prydain 0xc0000a5950 0xc0000a5950 <nil>} hashed_secret:$2a$05$XivqEwum/aF0kBXjp6vDJe7KTX0od5snoq6.nWDlXnG1X9CGLuPim ref:{10 0xc0000a5860 0xc0000a5860 <nil>} role:server ts:1622570158160000]
ObjectV(ref: RefV(id = "10", collection = RefV(id = "keys")),ts: LongV(1622570134070000),database: RefV(id = "prydain", collection = RefV(id = "databases")),role: StringV(server),hashed_secret: StringV($2a$05$qm2Em6pmKksAwXEEGwyE5eSEorjy9DtvjXzPtm2Dj3y79CDZv42Ne))
{
ref: Ref(Keys(), "10"),
ts: 1624310590670000,
database: Database("prydain"),
role: 'server',
hashed_secret: '$2a$05$PLRDauz7KMnS95.y6Z36Ou5/wcsI8ZOYFlrCrIaUrr9LUp/oL2fyO'
}
Deleting a key immediately makes its associated secrets invalid. |
Is this article helpful?
Tell Fauna how the article can be improved:
Visit Fauna's forums
or email docs@fauna.com
Thank you for your feedback!