This reference guides covers Common Expression Language (CEL) syntax relevant to creating expressions for the @auth(expr:)
and @check(expr:)
directives.
Complete reference information for CEL is provided in the CEL specification.
Test variables passed in queries and mutations
@auth(expr)
syntax allows you access and test variables from queries and mutations.
For example, you can include an operation variable, such as $status
, using vars.status
.
mutationUpdate($id:UUID!,$status:Any)@auth(expr:"has(vars.status)")
Data available to expressions
Both @auth(expr:)
and @check(expr:)
CEL expressions can evaluate the following:
request.operationName
vars
(alias forrequest.variables
)auth
(alias forrequest.auth
)
Additionally, @check(expr:)
expressions can evaluate:
this
(the value of the current field)
The request.operationName object
The request.operarationName
object stores the type of operation, either query or mutation.
The vars
object
The vars
object allows your expressions to access all variables passed in your query or mutation.
You can use vars.<variablename>
in an expression as an alias for the fully-qualified request.variables.<variablename>
:
# The following are equivalentmutationStringType($v:String!)@auth(expr:"vars.v=='hello'")mutationStringType($v:String!)@auth(expr:"request.variables.v=='hello'")
The auth
object
Authentication identifies users requesting access to your data and provides that information as an object you can build on in your expressions.
In your filters and expressions, you can use auth
as an alias for request.auth
.
The auth object contains the following information:
uid
: A unique user ID, assigned to the requesting user.token
: A map of values collected by Authentication.
For more details on the contenst of auth.token
see Data in auth tokens
The this
binding
The binding this
evaluates to the field that the @check
directive is attached to. In a basic case, you might evaluate single-valued query results.
mutationUpdateMovieTitle($movieId:UUID!,$newTitle:String!)@auth(level:USER)@transaction{# Step 1: Query and checkquery@redact{moviePermission(# Look up a join table called MoviePermission with a compound key.key:{movieId:$movieId,userId_expr:"auth.uid"}){# Check if the user has the editor role for the movie. `this` is the string value of `role`.# If the parent moviePermission is null, the @check will also fail automatically.role@check(expr:"this == 'editor'",message:"You must be an editor of this movie to update title")}}# Step 2: Actmovie_update(id:$movieId,data:{title:$newTitle})}
If the returned field occurs multiple times because any ancestor is a list, each occurrence is tested with this
bound to each value.
For any given path, if an ancestor is null
or []
, the field won't be reached and the CEL evaluation will be skipped for that path. In other words, evaluation only takes place when this
is null
or non-null
, but never undefined
.
When the field itself is a list or object, this
follows the same structure (including all decendents selected in case of objects), as illustrated in the following example.
mutationUpdateMovieTitle2($movieId:UUID!,$newTitle:String!)@auth(level:USER)@transaction{# Step 1: Query and checkquery{moviePermissions(# Now we query for a list of all matching MoviePermissions.where:{movieId:{eq:$movieId},userId:{eq_expr:"auth.uid"}}# This time we execute the @check on the list, so `this` is the list of objects.# We can use the `.exists` macro to check if there is at least one matching entry.)@check(expr:"this.exists(p, p.role == 'editor')",message:"You must be an editor of this movie to update title"){role}}# Step 2: Actmovie_update(id:$movieId,data:{title:$newTitle})}
Complex expression syntax
You can write more complex expressions by combining with the &&
and ||
operators.
mutationUpsertUser($username:String!)@auth(expr:"(auth!=null) && (vars.username=='joe')")
The following section describes all available operators.
Operators and operator precedence
Use the following table as a reference for operators and their corresponding precedence.
Given arbitrary expressions a
and b
, a field f
, and an index i
.
Operator | Description | Associativity |
---|---|---|
a[i] a() a.f | Index, call, field access | left to right |
!a -a | Unary negation | right to left |
a/b a%b a*b | Multiplicative operators | left to right |
a+b a-b | Additive operators | left to right |
a>b a>=b a<b a<=b | Relational operators | left to right |
a in b | Existence in list or map | left to right |
type(a) == t | Type comparison, where t can be bool, int, float, number, string, list, map, timestamp, or duration | left to right |
a==b a!=b | Comparison operators | left to right |
a && b | Conditional AND | left to right |
a || b | Conditional OR | left to right |
a ? true_value : false_value | Ternary expression | left to right |
Data in auth tokens
The auth.token
object may contain the following values:
Field | Description |
---|---|
email | The email address associated with the account, if present. |
email_verified | true if the user has verified they have access to the email address. Some providers automatically verify email addresses they own. |
phone_number | The phone number associated with the account, if present. |
name | The user's display name, if set. |
sub | The user's Firebase UID. This is unique within a project. |
firebase.identities | Dictionary of all the identities that are associated with this user's account. The keys of the dictionary can be any of the following: email , phone , google.com , facebook.com , github.com , twitter.com . The values of the dictionary are arrays of unique identifiers for each identity provider associated with the account. For example, auth.token.firebase.identities["google.com"][0] contains the first Google user ID associated with the account. |
firebase.sign_in_provider | The sign-in provider used to obtain this token. Can be one of the following strings: custom , password , phone , anonymous , google.com , facebook.com , github.com , twitter.com . |
firebase.tenant | The tenantId associated with the account, if present. For example, tenant2-m6tyz |
Additional fields in JWT ID tokens
You can also access the following auth.token
fields:
Custom Token Claims | ||
---|---|---|
alg | Algorithm | "RS256" |
iss | Issuer | Your project's service account email address |
sub | Subject | Your project's service account email address |
aud | Audience | "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit" |
iat | Issued-at time | The current time, in seconds since the UNIX epoch |
exp | Expiration time | The time, in seconds since the UNIX epoch, at which the token expires. It can be a maximum of 3600 seconds later than the iat . Note: this only controls the time when the custom token itself expires. But once you sign a user in using signInWithCustomToken() , they will remain signed in into the device until their session is invalidated or the user signs out. |
<claims> (optional) | Optional custom claims to include in token, which can be accessed through auth.token (or request.auth.token ) in expressions. For example, if you create a custom claim adminClaim , you can access it with auth.token.adminClaim . |