Security Reference
This page covers both administrative security and application security.
FaunaDB Key System
Access to the FaunaDB API uses secrets that correspond to access keys, which authenticate connections as having particular permissions. The access key system applies both to administrator- and server-level connections, as well as to object- and user-level connections.
Keys are defined as instances of the keys class. Like databases, keys exist within the system-global root database context.
Keys are tied to a specific database and allow access to its contents. The level of access a key provides depends on its role.
You must copy the key’s secret
out of the key when it is first created
and store it securely. Only a BCrypt hash of the key is stored on disk.
It is impossible to recover the key’s secret if it is discarded.
Field Name | Value Type | Description |
---|---|---|
|
Database ref |
The database associated with this key. |
|
String |
The key’s role. Either |
|
String |
The key’s authentication secret. Only present on creation. |
|
String |
The key’s hashed authentication secret. |
|
Number |
A priority between 1 and 500, inclusive. Defaults to 1. |
|
Object |
A JSON object. Optional. |
Access Keys
Keys belong to one of four roles: either admin
, server
,
server-readonly
, or client
.
Admin Keys
Keys with the admin
role are used for managing databases and keys. An
admin key can be used to create and destroy databases and keys. They
should be very well protected.
Admin keys for Cloud accounts are created in the cloud keys interface. For Enterprise installments the configured root key is used.
Server Keys
Keys with the server
role bypass all permissions checks within the
database they’re assigned to. Because they provide unrestricted access,
they should be well protected and only used in trusted or server-side
environments.
Server Read-Only Keys
Keys with the server-readonly
role allow read-only access to all data
within the database they’re assigned to. Because they provide
unrestricted read access, they should be well protected and only used in
trusted or server-side environments.
Client Keys
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.
Token Access
Tokens allow direct access to FaunaDB by application users. Their use is optional. Each token has an associated instance. Requests made with a token apply resource-level permissions checks based on its instance.
Both server and client keys can generate tokens. Token generation with a client key requires a password. The password is optional when using a server key, but will be verified if provided.
Permissions
FaunaDB has a built-in permissions system that allows for fine-grained control over access to data.
Access is controlled by a resource’s permissions object. The identity of a request’s key is checked against the value of the permission field corresponding to the resource and action being taken.
Permission fields may be set to one of the following values:
Value | Access Allowed |
---|---|
empty |
Only server keys are allowed. |
"public" |
Any key is allowed. |
instance ref |
Only tokens belonging to the specified instance are allowed. |
class ref |
Only tokens belonging to instances in the specified class are allowed. |
Class Permissions
Creating, reading, and modifying an instance in a class is controlled by the class’s permissions. Applicable fields on a class are:
Permission Field | Action Allowed |
---|---|
|
Creating an instance in the class. |
|
Reading instances in the class. |
|
Writing to instances in the class. |
An instance also has permissions, which are applied in addition to permissions defined on its class. The permissions object on an instance may contain these fields:
Permission Field | Action Allowed |
---|---|
|
Reading this instance. |
|
Writing to this instance. |
User-Defined Function Permissions
Calling a function is controlled by its permissions. Applicable fields are:
Permission Field | Action Allowed |
---|---|
|
Calling the function. |
Index Permissions
Query access to an index is controlled by its permissions. Applicable fields are:
Permission Field | Action Allowed |
---|---|
|
Querying the index. |
Delegates
An instance may delegate access on its behalf to other instances by
adding the other instances' refs to its delegates
list. Any tokens
belonging to a member of delegates
will be granted access as though
they were tokens belonging to the delegating instance.
For example, if classes/users/1
has read access to classes/spells/1
but classes/users/2
does not, classes/users/1
may grant access to
classes/users/2
with the following query:
curl https://db.fauna.com/ \
-d '{
"update": { "ref": { "class": "users" }, "id": 1 },
"params": {
"object": {
"delegates": [ { "ref": { "class": "users" }, "id": 2 } ]
}
}
}'
client.Query(
Update(
Ref(Class("users"), 1),
Obj("delegates", Arr(Ref(Class("users"), 2)))));
client.query(
Update(
Ref(Class(Value("users")), Value(1)),
Obj("delegates", Arr(Ref(Class(Value("users")), Value(2))))));
result, _ := client.Query(
f.Update(
f.RefClass(f.Class("users"), "1"),
f.Obj{"delegates": f.Arr{f.RefClass(f.Class("users"), "2")}},
),
)
fmt.Println(result)
client.query(
Update(
Ref(Class("users"), 1),
Obj("delegates" -> Arr(Ref(Class("users"), 2)))))
client.query(
q.update(
Ref(q.class_expr("users"), 1),
{"delegates": [Ref(q.class_expr("users"), 2)]}
))
$client.query do
update ref(class_('users'), 1),
delegates: [ref(class_('users'), 2)]
end
client.query(
Update(
ref: Ref(class: Class("users"), id: 1),
to: Obj(
"delegates" => Arr(Ref(class: Class("users"), id: 2))
)
)
)
client.query(
q.Update(
q.Ref(q.Class("users"), 1),
{ delegates: [q.Ref(q.Class("users"), 2)] }))
.then((ret) => console.log(ret))
map[ref:{1 0xc420118d80 <nil>} ts:1527631398281881 delegates:[{2 0xc420119000 <nil>}]]
{ ref: Ref(id=1, class=Ref(id=users, class=Ref(id=classes))),
ts: 1527631398281881,
delegates: [ Ref(id=2, class=Ref(id=users, class=Ref(id=classes))) ] }
Now, when classes/users/2
attempts to read classes/spells/1
, they
will be granted the same level of access as classes/users/1
.
Delegates are not transitive — in the example above, classes/users/2
may not delegate classes/users/1
's permissions to another user.
Was this article helpful?
We're sorry to hear that.
Tell us how we can improve!
documentation@fauna.com
Thank you for your feedback!