Security

Every request to an app backend on Kinvey, made by one of our mobile SDKs or another client, is associated with a security context. Kinvey uses this context to determine whether the user making the request is:

  • Who they say they are -- The user is authenticated using their credentials
  • Allowed to do what they're trying to do -- The user is authorized to act on the resource in the manner specified

An app will naturally include logic to filter the data displayed to each user. However, this logic resides on the client side, and can be circumvented by a malicious user or ignored by a programming error. This is true whether you build your own backend or not. To give you control and flexibility enforced on the server side, we offer a number of easy options for both authentication and authorization.

Authentication

An app can use one of two forms of authentication - Basic Auth and Session Auth. All credentials used to access any of the Kinvey REST APIs can be used with either style of authentication.

Basic Authentication

The first form of authentication - Basic Auth - authenticates each individual request using a username and password pair.

The Basic Auth token is reversible, however when all communication is over HTTPS the security context is completely protected. Basic Auth is trivial to use from HTTP client libraries. Tools such as cURL provide corresponding command line options.

To use Basic Auth, an app must send an HTTP Authorization header containing the username and password with every request. You will find more details on Basic Auth in IETF RFC 2617. In short, a Basic Auth authorization string is composed of the word Basic followed by a base64-encoded string containing the username and password separated by a colon.

Simple example:

Auth string (before encoding in base64): Basic myUsername:myPassword

Auth string (after base64 encoding): Basic bXlVc2VybmFtZTpteVBhc3N3b3Jk

Complete authorization header: Authorization: Basic bXlVc2VybmFtZTpteVBhc3N3b3Jk

When using the App or Master secret with Basic Auth, use your App Key as the username, and the secret as the password.

Session Authentication

The second form of authentication - Session Auth - authenticates each individual request using a Kinvey generated auth token.

By using Session Auth, an app eliminates exposure of passwords on every individual request. Only the initial request for setting up the session needs to be sent with the username and password. Session Auth provides an app fine grained access control whereby the Kinvey backend can grant, reject, expire, and invalidate access on a per session basis. Security can be managed without requiring user intervention (e.g.: change of password or disabling the account).

To use Session Auth, an app must first make a login request to collect an auth token from the Kinvey backend. The auth token is returned under the _kmd property in the JSON returned in the response. This auth token can then be used for authentication in subsequent requests across all Kinvey REST APIs.

The auth token is cleared from a device when a user is logged out, but only on the client device. It is important to note that logging out does not invalidate session tokens in Mobile Identity Connect (MIC).

Mobile Identity Connect (MIC) provides an OAuth2 authentication interface for integrating with a number of types of identity providers, including SAML-Redirect, OpenID Connect, Active Directory, and LDAP. MIC maintains a session token for users who are logged in. When a user is logged out on the client device, the session token in MIC remains valid in the event of a logout and invalidation of the auth token on the client device.

Session Auth Dataflow

To send the auth token with a request, use the HTTP Authorization header with the Kinvey scheme. It’s trivial to add an Authorization header from any HTTP client library or tools such as cURL which provide easy options for customizing standard HTTP headers. Session Auth is only available when accessed for API version 1 or higher.

Authorization: Kinvey 0a8368d7-cbb8-473d-8fec-a1f7f50b764b.X0KQYoRCFEdyBW9WIP/RpzYBrmyraGA5u9cEHprUGk8=

The auth token is cryptographically secured and cannot be reversed. Hence, it’s impervious to forgery. Kinvey auth tokens are long lived, which greatly reduces the security burden on app users. A future release will provide you the ability to configure token inactivity and expiration policies for sessions.

To terminate a session, an app should invoke the logout request. A logout will destroy the auth token presented for authenticating the logout request. Any subsequent attempts to re-use that auth token will be rejected with a 401 invalid error response. We recommend apps provide logout functionality to users as a standard security practice for terminating sessions. The Kinvey backend also provides additional security measures by implementing controls for invalidating auth tokens (e.g.: when the password for a user is changed).

Credentials

There are three types of credentials used in our service. User credentials can be used with both Basic Auth and Session Auth, while Master and App credentials can only be used with Basic Auth.

  • Master credentials represent the 'admin account' which has complete access over all data. These credentials must never be part of the released mobile app, as the app may be reverse engineered to extract the credentials. The master secret is typically for administrative tasks. Your management console account uses the master credentials to access data from interfaces such as the data browser. You can use the master credentials to create your own custom admin console or scripts, or to access Kinvey data from business logic running in a trusted environment.
  • User credentials are what authenticate all communication between the mobile app and Kinvey.
  • App credentials are used to bootstrap an app by authenticating the request that creates the user. Since they have very limited grants, there is no expectation that they must remain uncompromised.

Authorization

Kinvey allows an app to control access authorization via settings at the collection and entity level. These permission settings establish a hierarchy whereby lower level (entity) permissions take priority over higher ones (collection). For example, if a user has read access to an entity, they have that access regardless of the collection level setting. This hierarchy offers useful high-level controls, and robust lower level tuning options.

Collection Permissions

Below is the full list of collection-level permission settings. They can be modified by visiting the Settings page of the collection.

  • Shared (read-all, write-yours)
    End users of an app can only create and modify their own data, but read all data in this collection. This is the default permission level for any new collection. Previously referred to as 'append-read' permission level.

  • Private (read-yours, write-yours)
    End users of an app can only read, create, and modify their own data. They cannot read any other data in this collection. Previously referred to as 'append-only' permission level.

  • Read Only (read-all, write-none)
    End users of an app can read all data in this collection but cannot create and modify data. Previously referred to as 'read' permission level.

  • Full (read-all, write-all)
    End users of an app can read, create, and modify all data in this collection. Previously referred to as 'write' permission level.

The Full permission level allows anyone with access to your app to modify any data in that collection. Use with caution!

Common settings

Most developers will not need to do anything, since by default, all data within an app is readable by its users, but writable only by the user which created the entity. This is suitable for many apps as it automatically protects against unauthorized modifications, while keeping the data open.

If the use case requires more privacy, an app can set the permission level to Private, which limits the read access to entity creators. When an app requests an entire Private collection, Kinvey will respond with only the entities that user has access to - the user’s own data.

Entity and User permissions

An individual entity can override the collection level setting by turning on or off the global read or global write property. This will set read or write access to all app users, respectively.

To grant access only to specific users rather than globally, add the user id to the readers or writers property. With these methods an app can enable users to share their data with a set of named users, and collaborate by jointly modifying it.

To grant access by user groups, add the group id to the groups.r or groups.w property. By using groups, an app can manage access for a set of users even as users join or leave the group over time. A group with its all property set to true will allow access to all users of the app.

These grants are stored server side by using specific properties nested under _acl in the JSON representation. To ensure correct execution, the exact property names must be passed.

    # Regular entity with a detailed ACL structure included
    {
        "_id" : "4ff99979c0c014af6ee2773b",
        "field1" : "value1",
        "field2" : "value2",
        "field3" : "value3",
        "_acl":
            {
                "creator": "user_id_1",
                "gr": true,
                "gw": false,
                "r": ["user_id_2", "user_id_3"],
                "w": ["user_id_4", "user_id_5"],
                "groups": {
                    "r": ["group_id_1", "group_id_5"],
                    "w": ["group_id_3", "group_id_4"]
                }
            }
    }
NameTypeDescription
creatorstringthe _id of the user that originally created the entity
grbooleanabbr from 'global read', specifies whether the entity is globally readable
gwbooleanabbr from 'global write', specifies whether the entity is globally writable
rarrayabbr from 'readers', specifies the list of user _ids that are explicitly allowed to read the entity
warrayabbr from 'writers', specifies the list of user _ids that are explicitly allowed to modify the entity
groups.rarrayabbr from 'group readers', specifies the list of user groups that are explicitly allowed to read the entity
groups.warrayabbr from 'group writers', specifies the list of user groups that are explicit allowed to modify the entity

Passing _acl as part of the HTTP body is optional - if missing, the server copy is used. When the entity is being first created (via POST or PUT), the creator field is automatically set to the authenticated user id for that request. It is then stored and can never be changed (except by the master secret, as usual). Creators always have read and write access, and are the only user that is allowed to change the _acl structure.

Gotchas

Write implies delete

If a user has write access to an object, they can delete it. They cannot, however, set permissions themselves. Only the creator can give and take permissions for the respective entity

Write does not imply read

Having write access does not imply read access. To grant both kinds of access, simply call the two methods.

Master secret is "root"

The master secret has read and write access to all data, and can modify any permissions setting at any level. Entity creators have no mechanism to take that access away. (A reminder, never embed the master secret in the app). To import data from a legacy data source, use the master secret and set the ACL such that it preserves data ownership and access level.

Use cases

If you have collections that only hold entities that the app developer or administrator can create or modify, such as a daily deal, or a blog post, you would want to set the access level to Read Only. This allows read access to user credentials, and write access only to the app developer using the master secret.

If you have some kind of watch list functionality, where app users express interest in certain items by adding them to their watch list, and you store those in a separate collection, you might want to set it to Private. This means that any app user can append (create their new watch list and modify it) to the collection, but not read another user's watch list. If you want the watch list to be visible to other app users, you could set the collection to Shared.

The Full collection permission level allows any app user to create and modify any object. By itself it may seem too open, but combined with the right entity level settings it can be an effective approach for some apps.

To enable a social app, you can make use of the fine grained permissions described above. For example, set the collection holding user profiles to Private and let users make their profiles public via 'global read' or open them only to their friends, via 'readers'. Note, the lookup method will always allow an app user to discover other users.

Got a question?