The data browser is built for Chrome, Firefox, Safari, and IE9 and above. Please upgrade your browser, or download Google Chrome to get the best experience.

Data & Security

Data

Valid Data Types

We've designed the Parse SDKs so that you typically don't need to worry about how data is saved while using the iOS or Android SDKs. Simply add data to the PFObject or ParseObject, and it'll be saved correctly.

Nevertheless, there are some cases where it's useful to be aware of how data is stored on the Parse platform.

Internally, Parse stores data as JSON, so any datatype that can be converted to JSON can be stored on Parse. The framework can also handle Date, Bytes, and File types. Overall, the following types are allowed for each field in your object:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Bytes
  • File
  • Null

The type Object simply denotes that each value can be composed of nested objects that are JSON-encodable. Keys including the characters $ or ., along with the key __type key, are reserved for the framework to handle additional types, so don't use those yourself.

Our SDK handles translating native Objective-C and Java types to JSON. For example, if you save an NSString object, it will be translated into a String type in our system.

There are two ways to store binary data. The Bytes type allows you to associate NSData/bytes[] types directly on a PFObject. This is recommended only for small pieces of binary-encoded data. For actual files (images, documents, etc.), the File type can be used by instantiating a PFFile/ParseFile and setting it on a field.

Data Type Lock-in

When a class is initially created, it doesn't have an inherent schema defined. This means that for the first object, it could have any types of fields you want.

However, after a field has been set at least once, that field is locked into the particular type that was saved. For example, if a User object is saved with field name of type String, that field will be restricted to the String type only (our SDK will return an error if you try to save anything else).

One special case is that any field can be set to null, no matter what type it is.

The Data Browser

The Data Browser is the web UI where you can update and create objects in each of your apps. Here, you can see the raw JSON values that are saved that represents each object in your class.

When using the interface, keep in mind the following:

  • Entering "null" will set the value to the special null value, not the string "null".
  • The objectId, createdAt, updatedAt fields cannot be edited (these are set automatically).
  • The value "(empty)" denotes that the field has not been set for that particular object (this is different than null).

The Data Browser is also a great place to test the Cloud Code validations contained in your Cloud Code functions (such as beforeSave). These are run whenever a value is changed or object is deleted from the Data Browser, just as they would be if the value was changed or deleted from your client code.

Importing Data

You may import data into your Parse app by using CSV or JSON files. To create a new class with data from a CSV or JSON file, go to the Data Browser and click the "Import" button on the left hand column. To import data into an existing class, you can use our REST API.

The JSON format is an array of objects in our REST format or a JSON object with a results that contains an array of objects. A file containing regular objects could look like:

{ "results": [
  {
    "score": 1337,
    "playerName": "Sean Plott",
    "cheatMode": false,
    "createdAt": "2012-07-11T20:56:12.347Z",
    "updatedAt": "2012-07-11T20:56:12.347Z",
    "objectId": "fchpZwSuGG"
  }]
}

Normally, when objects are saved to Parse, they are automatically assigned a unique identifier through the objectId field, as well as a createdAt field and updatedAt field which represent the time that the object was created and last modified in the Parse Cloud. These fields can be manually set when data is imported from a JSON file. Please keep in mind the following:

  • Use a unique 10 character alphanumeric string as the value of your objectId fields.
  • Use a UTC timestamp in the ISO 8601 format when setting a value for the createdAt field or the updatedAt field.

In addition to the exposed fields, objects in the Parse User class can also have the bcryptPassword field set. The value of this field is a String that is the bcrypt hashed password + salt in the modular crypt format described in this StackOverflow answer. Most OpenSSL based bcrypt implementations should have built-in methods to produce these strings.

A file containing a User object could look like:

{ "results": [{
    "username": "cooldude",
    "createdAt": "2012-08-27T22:42:30.548Z",
    "updatedAt": "2012-09-05T23:23:40.636Z",
    "objectId": "ttttSEpfXm",
    "sessionToken": "dfwfq3dh0zwe5y2sqv514p4ib",
    "bcryptPassword": "$2a$10$ICV5UeEf3lICfnE9W9pN9.O9Ved/ozNo7G83Qbdk5rmyvY8l16MIK"
  }]
}

Security

Introduction

As your app development progresses, you will want to use Parse's security features in order to safeguard data. This document explains the ways in which you can secure your apps.

Connection Between Client and Server

An app connects to Parse and identifies itself with an application ID and a client key. The application ID and client key are not secret, and by themselves they do not secure an app.

All connections are made with HTTPS and SSL, and Parse will reject all non-HTTPS connections. As a result, you don't need to worry about man-in-the-middle attacks.

Class-Level Permissions

The second level of security is at the schema and data level. Enforcing security measures at this level will restrict how and when client applications can access and create data on Parse. When you first begin developing your Parse application, all of the defaults are set so that you can be a more productive developer. For example:

  • A client application can create new classes on Parse
  • A client application can add fields to classes
  • A client application can modify or query for objects on Parse

You can configure any of these permissions to apply to everyone, no one, or to specific users or roles in your app. Roles are groups that contain users or other roles, which you can assign to an object to restrict its use. Any permission granted to a role is also granted to any of its children, whether they are users or other roles, enabling you to create an access hierarchy for your apps. Each of the Parse guides includes a detailed description of employing Roles in your apps.

Once you are confident that you have the right classes and relationships between classes in your app, you should begin to lock it down by doing the following:

  • Restricting class creation from your app
  • Configuring class-level permissions on your schema
  • Creating restrictions on how your data is accessed by other users

Restrict class creation on Parse

As a start, you can configure your application so that clients cannot create new classes on Parse. This is done from the Settings tab on the Data Browser. Scroll down to the App Permissions section and turn off Allow client class creation. Once enabled, classes may only be created from the Data Browser. This will prevent attackers from filling your database with unlimited, arbitrary new classes.

Configuring class-level permissions

Parse lets you specify what operations are allowed per class. This lets you restrict the ways in which clients can access or modify your classes. To change these settings, go to the Data Browser, select a class, open the "More" dropdown, and click the "Set permissions" item.

You can configure the client's ability to perform each of the following operations for the selected class:

  • Get - fetching an object by its objectId
  • Find - issuing a query to fetch objects
  • Update - saving an object that already exists and has been modified
  • Create - saving an object that is new and hasn't been created yet
  • Delete - deleting an object
  • Add fields - adding fields to the class

For each of the above actions, you can grant permission to all users (which is the default), or lock permissions down to a list of roles and users. For example, a class that should be available to all users would be set to read-only by only enabling get and find. A logging class could be set to write-only by only allowing creates. You could enable moderation of user-generated content by providing update and delete access to a particular set of users or roles.

Object-Level Access Control

Once you've locked down your schema and class-level permissions, it's time to think about how data is accessed by your users. Object-level access control enables one user's data to be kept separate from another's. Parse also supports the notion of anonymous users for those apps that want to store and protect user-specific data without requiring explicit login.

When a user logs into an app, they initiate a session with Parse. Through this session they can add and modify their own data but are prevented from modifying other users' data.

Access Control Lists

The easiest way to control who can access data is through access control lists, commonly known as ACLs. The idea behind an ACL is that each object has a list of users and roles along with what permissions that user or role has. A user needs read permissions (or must belong to a role that has read permissions) in order to retrieve an object's data, and a user needs write permissions (or must belong to a role that has write permissions) in order to update or delete that object.

Applications can enforce their access patterns through ACLs and class-level permissions. For example:

  • For private data, read and write access can be restricted to the owner.
  • For a post on a message board, the author and members of the "Moderators" role can have "write" access, and the general public can have "read" access.
  • For logging data that will only be accessed by the developer through the REST API using the master key, the ACL can deny all permissions.
  • Data created by a privileged group of users or the developer, like a global message of the day, can have public read access but restrict write access to an "Administrators" role.
  • A message sent from one user to another can give "read" and "write" access just to those users.

As an example, here's the format for an ACL that restricts read and write permissions to the owner (whose objectId is identified by the X's) and enables other users to read the object:

{ "*":{"read":true}, "SaMpLeUsErId":{"write":true,"read":true} }

And, here's another example of the format of an ACL that uses a Role:

{ "role:RoleName":{"read":true}, "SaMpLeUsErId":{"write":true,"read":true} }

Using the Android and iOS SDKs, you can set a default ACL for all of the objects your application clients creates. See the Parse guides for more information about choosing secure defaults. You can do the same for other clients by setting ACLs in the beforeSave Cloud Code function.

Data Integrity in Cloud Code

The next level of security you may want to consider is restricting the values of data that are stored in Parse. In this scenario, you've already done what's required in class and object level security, and are now adding another layer where you are preventing invalid data from being stored.

Common scenarios that warrant validation include:

  • Making sure phone numbers have the right format
  • Sanitizing data so that its format is normalized
  • Making sure that an email address looks like a real email address
  • Requiring that every user specifies an age within a particular range
  • Not letting users directly change a calculated field
  • Not letting users delete specific objects unless certain conditions are met

To create validation functions, implement a beforeSave cloud function for your class. For example, if we wanted to ensure that the value for a review was within an acceptable range, we could implement a beforeSave function as described in the Cloud Code Guide. With beforeSave, you can either reject the save or modify the object so that it conforms to your parameters. In beforeDelete, you can evaluate certain conditions before permitting a delete to continue.

Validations can lock down your app so that only certain values are acceptable. You can also use validations to normalize your data, for example to format all phone numbers or currency identically. You get to retain most of the productivity benefits of accessing Parse data directly from your client applications, but you can also enforce the acceptable values for your data using Cloud Code functions.

Implementing Business Logic in Cloud Code

The final level of security you can implement with Parse is to move access and modification of data to Cloud Code functions. You can remove permissions from clients completely and instead funnel all data operations to Cloud Code functions. Since Cloud Code is code that you have written, it is guaranteed to be trusted more than code originating from untrusted clients.

When a Cloud Code function is called, it can invoke the useMasterKey function to gain the ability to modify user data. With the master key, your Cloud Code function can override any ACLs and write data. The master key should be used carefully. When invoked, the master key is in effect for the duration of the Cloud Code function in which it is called. A more prudent way to use the master key would be to pass it as a parameter on a per-function basis. For example, the find operation below uses the master key as a parameter to a function to override any permissions:

var query = new Parse.Query(Parse.User);
query.find({useMasterKey : true}).then(function(results) {
  // process the result of the query here
});

In this scenario, all of the instances where you directly access or modify data on Parse from the client are instead called via Cloud Code functions.

User Security

It is important to keep in mind that the Parse User object is readable by all other users by default. You will want to set the ACL on your User object accordingly if you wish to prevent data contained in the User object (for example, the user's email address) from being visible by other users.

There may be instances where you wish to provide selective read access to a Parse User object. For example, other users may wish to obtain a particular user's username, but you also want to prevent anyone from obtaining the user's email address. For situations like this, you will want to lock the object down by default and provide Cloud Code functions to access the parts of the Parse User object that you wish to expose to all users.

Parse Security Summary

Parse provides a number of ways for you to secure data in your app. As you build your app and evaluate the kinds of data you will be storing, you can make the decision about which implementation to choose.