4 minutes read

Xano security checklist

Xano Security Checklist

Xano is a great tool that allows to build secure and scalable applications. But to create secure applications, Xano won’t do everything for you. This post lists basic things that you should implement in order to make your app more secure.
In case you want to make sure your app is secure enough, we offer Xano audits (potentially combined with WeWeb audit).

Authentication

API authentication is what ensures that only users with authentication “token” have access to anything that hides behind the API.

It’s the most basic thing to do when developing an app in Xano and yet, we saw several client apps that didn’t have Authentication setup. (for APIs that were supposed to be private)

Please don’t be the “I’ll set it up later” type of developer.

How to setup authentication?
Go to API -> Settings -> Authentication

Xano Authentication

CORS settings

CORS (Cross-Origin Resource Sharing) is a browser feature that blocks requests made to a different website (origin) unless the server allows it. Servers can send special headers to let the browser know which sites are allowed to access their data. This helps protect against unauthorized access.

Probably the most “useful” part is to control “allow-origin” so that you can control which websites can call your API endpoints.

Please note that this does not affect when doing server-side XANO api requests. (CORS is browser-only feature)

How to setup CORS Settings?
Go to specific API Group-> More options -> CORS Management

Xano CORS management

UUID instead of integer ID

Why it’s better to use UUID instead of integer ID?
“Using UUIDs instead of integers in a database can improve security because UUIDs are hard to guess. Integers are sequential and can reveal patterns or expose the number of records. UUIDs, being random, make it harder for attackers to guess IDs or scrape data by iterating through predictable numbers.”
Are there any disadvantages?
For most of the apps, no. For some apps, yes.

  • UUID takes up 16 bytes while integer takes 4 bytes. In terms of storage, it’s not worth of discussion but the indexes may take up more space. Index size is using Xano’s “Database SSD Storage” so have that in mind
  • Query performance might be a bit slower. But this applies only for HUUUUUGE tables (talking about tens, hundreds of millions of records)

Referencing user ID in API

This may sound as too specific use-case but it is not. This is a general rule, that if you’re doing some user “self-operations” – e.g. user changing his/her profile information you should NOT use “user_id” as an API input parameter. (see example below)

Why?
Because when you reference user with API input instead of using “auth.id”, you’ll introduce a security vulnerability, because someone can just change the value of API input to another user and can potentially change other people’s data.

Enforce password strength on back-end

If you want to enforce password strength, you can easily do that on DB-level. No need to implement additional logic in signup flow.
Just go to user table -> right-click on password column and set up corresponding filters.

Consistent error messages in login/signup flow

OWASP recommendations:
OWASP advises not to disclose whether the username exists in login and password reset flows. Keeping error responses generic and timing responses uniformly are critical practices to mitigate user enumeration risks.
https://cheatsheetseries.owasp.org/cheatsheets/Authentication_Cheat_Sheet.html
What does it mean in terms of your login error messages?
They should be the same for any case of incorrect login (non-existing email, incorrect password)

Access to Swagger documentation

Xano automatically generates Swagger documentation for your APIs, providing information about the available endpoints.
You can configure access to API Group Swagger in API Group settings

Use token extras for role-based access controls

This one is kind of performance/security tip.
Suppose you have an app where users have roles and they belong to organizations. Access to data is stored primarily on organization-level.
There are 4 (worst to best, 3 & 4 are in my opinion equally good) how to check if user has access to corresponding data/features/operations

  1. Restrict access (only) on Front-end. This should never be the only way how to restrict access to data or user operations. Please make sure you implement the permission mechanism on backend as well
  2. Query user’s permissions for every API call. (e.g. query user’s role & and organization permissions) You always get accurate information on one hand, buy you’re making un-necessary queries, which can often lead to slower API responses.
  3. Write and read the information from token extras. Instead of requesting the data with the API call, you’ll encode this information into Authentication token instead. When making API calls, you can access this information without doing any other unnecessary DB queries.
  4. Create a cached function to get information about user’s roles.