---
title: Secure your app
nav: Secure your app
group: Build your app
updated: 2026-11-13
description: Protect your SashiDo app's data. How keys work, class-level permissions, ACLs, roles, privileged logic in cloud code, the master key, App Checks, and access for scripts and AI assistants.
keywords: parse server security, parse class level permissions, parse acl, parse roles, parse protected fields, parse master key, sashido security, backend security checklist
---

Your app's client keys are inside your web and mobile apps, so anyone can find them and call your API as your app does. That's expected: Parse is built so the keys only identify the app, and **permissions** decide what each caller may do. This page is about setting them so that a stranger with your keys can do nothing they shouldn't.

## The model in one table

| Layer | Decides | Where |
|---|---|---|
| Class-level permissions (CLPs) | Who may find, get, create, update, delete in a class, and add fields | **Core › Browser › class › Security** |
| ACLs | Who may read and write one object | The object's `ACL` field, usually set in code |
| Roles | Groups of users, used in CLPs and ACLs | The `_Role` class |
| Cloud code | Anything that needs more than one user's rights | Your app's repository, `cloud/` |
| Master key | Bypasses all of the above | Server side only |

A request has to pass the CLP first, then each object's ACL. On Parse Server 6, a class's CLP can also hide fields from some users (`protectedFields`, set through the [schema API](/en/docs/developers/api#your-apps-data-the-parse-proxy)), e.g. other users' emails.

## Lock down the classes

New classes are open to everyone by default. For each class, decide who needs what:

- **Find** lists objects. Most classes don't need it public, and `_User` especially shouldn't have it.
- **Create**, **Update**, **Delete**: only for authenticated users or a role, not "Public".
- **Add field**: off for everyone. Add fields from the dashboard or your code with the master key.

Then turn off **Allow client class creation** (**App Settings › Security & Keys**), so clients can't create new classes by saving objects.

## Give objects an owner

An ACL says who may read and write one object. Set it when the object is created, in a `beforeSave` trigger, so clients can't forget or forge it:

```javascript
// cloud/main.js
Parse.Cloud.beforeSave('Note', (request) => {
  if (!request.original && request.user) {
    const acl = new Parse.ACL(request.user);   // the author reads and writes
    acl.setRoleReadAccess('moderators', true); // moderators read
    request.object.setACL(acl);
  }
});
```

## Keep privileged logic on the server

Anything that changes data the user doesn't own (payments, credits, counters, roles, other users' records) belongs in a cloud function that checks the caller and then acts with the master key:

```javascript
Parse.Cloud.define('grantCredits', async (request) => {
  const { user } = request;
  if (!user) throw new Parse.Error(Parse.Error.SESSION_MISSING, 'Log in first.');
  const isAdmin = await new Parse.Query(Parse.Role)
    .equalTo('name', 'admins').equalTo('users', user).first({ useMasterKey: true });
  if (!isAdmin) throw new Parse.Error(Parse.Error.OPERATION_FORBIDDEN, 'Admins only.');
  // ...the change, with { useMasterKey: true }
});
```

Never trust a field the client sends for decisions like `isAdmin` or `price`: read them from the database in the function.

## Keep keys and secrets where they belong

- **Master Key, REST API Key, Webhook Key, Database URL**: server side only. Never in an app, a repository, a support ticket or a prompt. If one leaks, reset it (**App Settings › Security & Keys › Reset master key**).
- **Third-party secrets** (Stripe, email services): in [environment variables](/en/docs/developers/api#environment-variables), read in cloud code from `process.env`, never in the code itself.
- **Scripts, CI and AI assistants**: a [personal access token](/en/docs/developers/authenticate) with only the scopes they need, not the master key. You can revoke it, limit it to apps, and see everything it did in **Account › Activity**.

## Check it

- **App Checks** in the dashboard (Parse Server 6.5.11 and newer) runs security, users and database checks against your app and says how to fix each finding.
- Through [MCP](/en/docs/developers/mcp), *"check my-app for security problems"* runs `get_app_advice`, including the class-level permission checks on older versions.
- Turn on two-factor authentication for your SashiDo account (**Account › Security**), and review **Account › Activity** for changes you didn't make.

## Checklist before launch

- [ ] Every class has CLPs for its purpose; nothing public that doesn't need to be
- [ ] `_User` **Find** is not public
- [ ] **Allow client class creation** is off
- [ ] Objects get ACLs in `beforeSave`
- [ ] Privileged changes are in cloud functions that check the caller
- [ ] No master key or secret in client code or repositories; secrets in environment variables
- [ ] App Checks (or `get_app_advice`) show no failures
- [ ] Two-factor authentication on for everyone with dashboard access
