Login and logout
A token requires an identity document
field. This document can represent a
person, service, system, or process that needs access to database resources.
Typically, though, an identity document represents a person who is a user
accessing a Fauna database from a client application.
In this tutorial, you learn about creating tokens associated with people.
Associate a credential with a document
In other databases, you might have stored a hashed password with user data.
Fauna supports this with features that are easier to use and more secure.
The way to tell Fauna that an identity, such as People
, document
has a password is by associating it with a Credential
document.
A document can only have one associated credential. Attempts to create a second
credential return a constraint_failure
error.
Your CoffeeStore
database should have a populated People
collection. If it
doesn’t, you can create one as
instructed in the previous section.
-
Open the Fauna Shell in the CoffeeStore database.
A
Token
document can only access one database. Access to a parent database in a hierarchy does not grant access to its children. -
In the run menu, set Admin or an equivalent key secret.
-
Find the first
People
document where there is an email.{ id: "370723013175279650", coll: People, ts: Time("2023-07-20T15:21:59.220Z"), name: "Janine Labrune", email: "jlabrune@gmail.com", address: { street: "67, rue des Cinquante Otages", city: "Nantes", country: "France", zip: "44000" }, status: "active" }
-
Make note of the
id
field on this person. -
Create a
Credential
for thisid
providing a requiredpassword
field.{ id: "371153420791316514", coll: Credential, ts: Time("2023-07-24T17:05:34.890Z"), document: People.byId("370723013175279650") }
The
People
document serves as the required identity document for the credential. The credential securely encrypts but never displays thepassword
. This design ensures a caller cannot expose hashed credentials by mistake.Fauna cannot recover a password that is discarded or lost. Copy and save it to a password manager or other safe location. You can call
Credential.update()
to set a new password. -
Using the credential
id
and the userpassword
, make theCredential.login()
query.{ id: "371153519651061794", coll: Token, ts: Time("2023-07-24T17:07:09.170Z"), secret: "fnEFJpoo3_AAIgUiXlNNgAAi7f_DzBJ_4i_Y3fJHlD_KYwtEGfc", document: People.byId("370723013175279650") }
At creation is the only time Fauna displays the
secret
field. The value in this field is equivalent to a password. Fauna cannot recover a secret that is discarded or lost. Copy and save the secret to a password manager or other safe location. Delete and replace keys or tokens for which you have lost the secret. If you no longer need a key or token, you should delete it.The token has no
ttl
, time-to-live, field so it remains until it is deleted or expired. You can set this value. -
Update the token adding a
ttl
value that expires the token after a day.{ id: "371153519651061794", coll: Token, ts: Time("2023-07-24T21:23:47.260Z"), ttl: Time("2023-07-25T21:23:44.631Z"), document: People.byId("370723013175279650") }
Sign in and Log in
In this procedure, you use the basic queries you learned to log in users to
create functions. Commonly, an application uses the email and password
combination for signing up new users. Each user is identified by their unique
email address so it is important to constrain the People.email
field so that
it is unique.
In the Shell go to the run menu and set Admin or an equivalent key secret, then do the following.
-
Add a unique constraint to the
email
field inPeople
.{ name: "People", coll: Collection, ts: Time("2023-07-25T22:03:50.820Z"), constraints: [ { unique: [ "email" ], status: "active" } ] }
-
Create a user-defined function to sign up users.
The FQL function body is written like a standard JavaScript arrow function. When called from the Shell or an application the caller provides
username
,email
andpassword
as parameters. The function creates aPeople
document that becomes the identity provided in theCredential
document that the function returns.{ name: "Signup", coll: Function, ts: Time("2023-07-25T15:59:03.950Z"), role: "server", body: <<-END (username, email, password) => { let user = People.create({ name: username, email: email }) Credentials.create({ document: user, password: password }) } END }
-
Call the
Signup
function to test it is correct.{ id: "371240301830864930", coll: Credential, ts: Time("2023-07-25T16:06:31.110Z"), document: People.byId("371240301825622050") }
-
Test the
email
constraint by supplying the same parameters again to theSignup()
function.Your second call should fail the unique constraint. Typically, applications must support users who log into an application after signing up. Now that
email
is constrained, it makes sense to create an index on that field. -
Create an index on the
People
collection.{ name: "People", coll: Collection, ts: Time("2023-07-24T15:50:31.105Z"), indexes: { byEmail: { terms: [ { field: "email" } ], queryable: true, status: "complete" } }, constraints: [ { unique: [ "email" ], status: "active" } ] }
-
Create a new
loginUser
UDF that takes makes use of this new index.{ name: "Login", coll: Function, ts: Time("2023-07-25T22:19:52.930Z"), body: <<-END (email, password) => { let user = People.byEmail(email).first() Credentials.byDocument(user)!.login(password) } END, role: "server" }
This function uses the email index to find a user document. Then, it supplies the document together with the
password
provided by the caller to theCredential.login()
function. -
Use the
loginUser
function to login the user.{ id: "371264487134593058", coll: Token, ts: Time("2023-07-25T22:30:56.010Z"), document: People.byId("371264255805095970"), secret: "fnEFJv8VgWAAIgUiXlNNgAAivHz8zbJGD2srnxB55AmR16fv-o4" }
-
Make note of the
secret
value for this token as you need it in the next section.At creation is the only time Fauna displays the
secret
field. The value in this field is equivalent to a password. Fauna cannot recover a secret that is discarded or lost. Copy and save the secret to a password manager or other safe location. Delete and replace keys or tokens for which you have lost the secret. If you no longer need a key or token, you should delete it. -
Experiment with the
loginUser()
function by giving it the wrongemail
orpassword
.
Your experiment should find that Fauna inherently provides proper security and error messaging for your new login function.
Log out
To log out, you can destroy the token created when logging in. The Fauna
Query
namespace has methods that you can use to get the token in the current
session. You can use these methods to log out a user by destroying their access
token.
-
In the run menu, set Secret and enter the token
secret
created by theloginUser()
function.Subsequent queries you enter use this secret.
-
Verify that you are in the session with the correct token.
{ id: "371287435110252578", coll: Token, ts: Time("2023-07-26T04:35:40.910Z"), document: People.byId("371264255805095970") }
As you are running with the token secret, Fauna knows your identity. It allows you to do queries related to your own identity data.
-
List all the
People
documents.{ data: [ { id: "371264255805095970", coll: People, ts: Time("2023-07-25T22:27:15.410Z"), name: "Alice Jones", email: "ajones@gmail.com" } ] }
Even though the
People
collection has several documents, the Fauna returns only the document whoseid
matches the current identity. -
To logout of this session, delete the token.
Token.byId("371287435110252578") /* permission denied */
-
Subsequent queries fail as your secret is no longer valid.
Invalid secret
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!