diff --git a/README.md b/README.md
index bca0877..8d583fa 100644
--- a/README.md
+++ b/README.md
@@ -106,6 +106,8 @@ There's also a list of all endpoints examples at [docs/api-examples.md](docs/api
For websocket examples, check [docs/ws-examples.md](docs/ws-examples.md)
+For detailed information on how authentication works in Soul, please refer to the [docs/auth.md](docs/auth.md)
+
## Extending Soul
Soul is able to be extended (e.g. Adding custom APIs) via extensions, you can find a list of extensions at [docs/extensions-examples.md](docs/extensions-examples.md)
diff --git a/docs/auth-db-diagram.png b/docs/auth-db-diagram.png
new file mode 100644
index 0000000..c243407
Binary files /dev/null and b/docs/auth-db-diagram.png differ
diff --git a/docs/auth.md b/docs/auth.md
new file mode 100644
index 0000000..29ddfa0
--- /dev/null
+++ b/docs/auth.md
@@ -0,0 +1,135 @@
+## User Authentication in Soul
+
+Soul incorporates a robust user authentication system that handles user accounts, groups, permissions, and cookie-based user sessions. This section provides an overview of how the default implementation works.
+
+Authentication is switched off by default in Soul, but is enabled when either of the `-a` or `--auth` flags are provided at the command line.
+
+### Overview
+
+The Soul authentication system handles both authentication and authorization. Briefly, authentication verifies a user is who they claim to be, and authorization determines what an authenticated user is allowed to do. Here, the term "authentication" is used to refer to both tasks.
+
+The auth system consists of:
+
+- Users
+- Roles and Permissions: A generic way of applying labels and permissions to more than one user.
+- A password hashing system
+- APIs for logging in users or restricting content
+- JWT based access tokens
+
+The authentication system in Soul aims to be very generic and doesn't provide some features commonly found in web authentication systems, such as:
+
+- Password strength checking
+- Throttling of login attempts
+- Authentication against third-parties (OAuth, for example)
+- Object-level permissions
+
+
+
+
Figure 1: Soul Authentication Database Diagram
+
+#### Users
+
+The `_users` table serves as the central component of the authentication system. Each row in the `_users` table represents an individual who interacts with your Soul instance. This table is crucial for enabling various functionalities, such as access restriction, and user registration.
+
+**_Superusers_**, distinguished by the `is_superuser` attribute set to true, are a special type of user in Soul. They can bypass any permissions and restrictions, effectively granting them "God-mode" within the system, including being able to access the `/api/tables` and `/api` end-points. Authorization limitations do not apply to superusers.
+
+The attributes of the `_users` table are:
+
+- id int
+- username varchar
+- \_hashed_password varchar
+- \_salt varchar
+- is_superuser boolean
+- created_at datetime
+- updated_at datetime
+
+Note that when Soul boots up, it looks for a table called `_users` (Otherwise Soul creates `_users` table) which holds the Users mentioned above.
+
+##### Modifying Superusers
+
+Due to the sensitive nature of the superuser status, it is not possible to change the `is_superuser` attribute of a user through the API.
+
+Instead, you can update superusers using the command line.
+
+```
+$ node src/server.js updateuser --id=1 --password=newstrongstring // To update password of a superuser with id 1
+$ node src/server.js updateuser --id=1 --is_superuser=true // To promote a user with id 1 to superuser
+```
+
+#### Roles
+
+Roles are a generic way of categorizing users so you can assign permissions to those users. A user can belong to any number of roles.
+
+If we have an `editor` role, and a `_roles_permissions` entry for the `posts` table that allows `update`, then any user with that role will be able to update `posts`.
+
+The attributes of the `_roles` table are:
+
+- id int
+- name varchar
+- created_at datetime
+- updated_at datetime
+
+##### Roles Permissions
+
+Using a table called `_roles_permissions` we can assign permissions to roles.
+
+The attributes of this table are:
+
+- id int
+- role_id int
+- table_name varchar
+- create boolean
+- read boolean
+- update boolean
+- delete boolean
+
+There is unique constraint on the combination of `role_id` and `table_name` attributes,
+to prevent duplication of permissions for the same role and table.
+
+###### Default Role
+
+Once a new table is created, Soul will automatically create a new `_roles_permissions` row for the `default` role and the new table, with the following permissions:
+
+- create: false
+- read: true
+- update: false
+- delete: false
+
+Which basically means that any user can read the table data, but can't create, update or delete data.
+
+Soul uses the `default` role to assign permissions to new users.
+
+The same happens when Soul boots up, but for all existing tables, making sure that all tables have the `default` role assigned to them.
+
+##### Users Roles
+
+To assign roles to users we have a join table called `_users_roles` with the following attributes:
+
+- id int
+- user_id int
+- role_id int
+
+#### Authentication
+
+Soul uses cookies and middleware to hook the authentication system into request objects.
+
+These provide a `req.user` attribute on every request, which represents the current user. If the current user has not logged in, it is set to null.
+
+#### Obtain Access Token
+
+To be able to use private APIs, users need to obtain an access token, which is a JWT token consisting of this payload:
+
+- username
+- is_superuser
+- roles
+
+For security reasons, Access tokens have a very short lifetime, and once expired, they can be refreshed using another API called Refresh Access token. Refresh tokens have a much longer lifetime, and both access and refresh tokens are provided to the user upon logging in.
+
+#### Register New Users
+
+To register new users, you need to create a new user using the `/api/tables/_users/rows/` endpoint, and then assign roles to that user using the `/api/tables/_users_roles/rows/` endpoint.
+Note that you need to be logged in using a user with a role that has creating users permission.
+
+Additionally, it's important to note that the `/api/tables/_users/rows/` endpoint functions slightly differently compared to other `/api/tables//rows/` endpoints. When creating or updating user data through this endpoint, we need to provide the raw passwords, which are then automatically hashed before being stored in the `_hashed_password` field. This extra step enhances the security of the stored passwords.
+
+Furthermore, when retrieving user data, the endpoint automatically filters out sensitive information such as the `_hashed_password` and `_salt` fields. This precautionary measure is in place to address security concerns and ensure that only necessary and non-sensitive information is included in the returned results.