SurrealDB
SurrealDB Docs Logo

Enter a search query

Handle authentication

Since SurrealDB is a database that is designed to be used in a distributed environment, it is important to secure the database and the data that is stored in it. SurrealDB provides a number of methods for authenticating users and securing the database.

In your SurrealDB database, you can create authentication login using the DEFINE ACCESS statement which supports JWT and Record Access methods.

The access method used will inform the input for access in the .SignUp() and .SignIn() methods.

Important

If you are not on Version v2.3.7 of SurrealDB, you will use the scope property instead of access.

MethodDescription
db.SignUp()Connects to a local or remote database endpoint
db.SignIn()Signs in to a root, namespace, database or scope user
db.Invalidate()Invalidates the current session
db.Authenticate()Authenticates a user with a token

Defining access in your application

The Golang SDK has a .Query() method which allows you to write secure SurrealQL statements from within your application. Using this method, you can define access for your users and securely manage authentication. See the code example below:

package main import ( "context" "fmt" surrealdb "github.com/surrealdb/surrealdb.go" "github.com/surrealdb/surrealdb.go/contrib/testenv" ) //nolint:funlen func ExampleDB_record_user_auth_struct() { ns := "surrealdbexamples" db := testenv.MustNew(ns, "record_auth_demo", "user") setupQuery := ` -- Define the user table with schema DEFINE TABLE user SCHEMAFULL PERMISSIONS FOR select, update, delete WHERE id = $auth.id; -- Define fields DEFINE FIELD name ON user TYPE string; DEFINE FIELD password ON user TYPE string; -- Define unique index on email REMOVE INDEX IF EXISTS name ON user; DEFINE INDEX name ON user FIELDS name UNIQUE; -- Define access method for record authentication REMOVE ACCESS IF EXISTS user ON DATABASE; DEFINE ACCESS user ON DATABASE TYPE RECORD SIGNIN ( SELECT * FROM user WHERE name = $user AND crypto::argon2::compare(password, $pass) ) SIGNUP ( CREATE user CONTENT { name: $user, password: crypto::argon2::generate($pass) } ); ` if _, err := surrealdb.Query[any](context.Background(), db, setupQuery, nil); err != nil { panic(err) } fmt.Println("Database schema setup complete") // Refer to the next example, `ExampleDB_record_user_custom_struct`, // when you need to use fields other than `user` and `pass` in the query specified for SIGNUP. _, err := db.SignUp(context.Background(), &surrealdb.Auth{ Namespace: ns, Database: "record_auth_demo", Access: "user", Username: "yusuke", Password: "VerySecurePassword123!", }) if err != nil { panic(err) } fmt.Println("User signed up successfully") // Refer to the next example, `ExampleDB_record_user_custom_struct`, // when you need to use fields other than `user` and `pass` in the query specified for SIGNIN. // // For example, you might want to use `email` and `password` instead of `user` and `pass`. // In that case, you need to something that encodes to a cbor map containing those keys. _, err = db.SignIn(context.Background(), &surrealdb.Auth{ Namespace: ns, Database: "record_auth_demo", Access: "user", Username: "yusuke", Password: "VerySecurePassword123!", }) if err != nil { panic(err) } fmt.Println("User signed in successfully") info, err := db.Info(context.Background()) if err != nil { panic(err) } fmt.Printf("Authenticated user name: %v\n", info["name"]) // Output: // Database schema setup complete // User signed up successfully // User signed in successfully // Authenticated user name: yusuke } func ExampleDB_record_user_custom_struct() { ns := "surrealdbexamples" db := testenv.MustNew(ns, "record_user_custom", "user") setupQuery := ` -- Define the user table with schema DEFINE TABLE user SCHEMAFULL PERMISSIONS FOR select, update, delete WHERE id = $auth.id; -- Define fields DEFINE FIELD name ON user TYPE string; DEFINE FIELD email ON user TYPE string; DEFINE FIELD password ON user TYPE string; -- Define unique index on email REMOVE INDEX IF EXISTS email ON user; DEFINE INDEX email ON user FIELDS email UNIQUE; -- Define access method for record authentication REMOVE ACCESS IF EXISTS user ON DATABASE; DEFINE ACCESS user ON DATABASE TYPE RECORD SIGNIN ( SELECT * FROM user WHERE email = $email AND crypto::argon2::compare(password, $password) ) SIGNUP ( CREATE user CONTENT { name: $name, email: $email, password: crypto::argon2::generate($password) } ); ` if _, err := surrealdb.Query[any](context.Background(), db, setupQuery, nil); err != nil { panic(err) } fmt.Println("Database schema setup complete") type User struct { Namespace string `json:"NS"` Database string `json:"DB"` Access string `json:"AC"` Name string `json:"name"` Password string `json:"password"` Email string `json:"email"` } type LoginRequest struct { Namespace string `json:"NS"` Database string `json:"DB"` Access string `json:"AC"` Email string `json:"email"` Password string `json:"password"` } _, err := db.SignUp(context.Background(), &User{ // Corresponds to the SurrealDB namespace Namespace: ns, // Corresponds to the SurrealDB database Database: "record_user_custom", // Corresponds to `user` in `DEFINE ACCESS USER ON ...` Access: "user", // Corresponds to the $name in the SIGNUP query and `name` in `DEFINE FIELD name ON user` Name: "yusuke", // Corresponds to the $password in the SIGNUP query and `password` in `DEFINE FIELD password ON user` Password: "VerySecurePassword123!", // Corresponds to the $email in the SIGNUP query and `email` in `DEFINE FIELD email ON user` Email: "yusuke@example.com", }) if err != nil { panic(err) } fmt.Println("User signed up successfully") _, err = db.SignIn(context.Background(), &LoginRequest{ Namespace: ns, Database: "record_user_custom", Access: "user", // Corresponds to the $email in the SIGNIN query and `email` in `DEFINE FIELD email ON user` Email: "yusuke@example.com", // Corresponds to the $password in the SIGNIN query and `password` in `DEFINE FIELD password ON user` Password: "VerySecurePassword123!", }) if err != nil { panic(err) } fmt.Println("User signed in successfully") info, err := db.Info(context.Background()) if err != nil { panic(err) } fmt.Printf("Authenticated user name: %v\n", info["name"]) // Output: // Database schema setup complete // User signed up successfully // User signed in successfully // Authenticated user name: yusuke }

Learn more

Learn more about authentication in SurrealDB in our security best practices documentation and in the security section of the SurrealDB documentation.

Edit this page on GitHub