Grant DataSync access
This guide shows you how to issue Access Manager tokens that authorize DataSync operations and optionally scope field-level access with projection grants. Token issuance is a server-side operation. Your client application then uses the token to make DataSync requests.
The examples issue one token for each of three roles in a marketplace:
- A catalog service that creates and deletes the objects.
- A shopper, Alice, who reads products through the
publicprojection. - A support agent who reads Alice's
admin-only fields.
They use the classes from Define an entity class and the objects from Create entities and relationships.
Before you start
- Access Manager must be enabled on your keyset. Refer to Enable DataSync.
- You need server-side signing credentials. Do not issue tokens from a client.
- Refer to Access control and permissions management for the general Access Manager model.
DataSync resource types
DataSync adds three resource types: datasync:entities, datasync:relationships, and datasync:memberships. User and channel entities reuse the existing users and channels resource types.
Use users, not uuids, for DataSync user entities
DataSync checks the users resource type for user entities. A token that only grants uuids permissions does not authorize DataSync operations on the corresponding user entity. Refer to DataSync access control.
Grant a service write access
The catalog service creates, reads, and deletes each object by exact ID.
- JavaScript
- C#
1const catalogToken = await pubnub.grantToken({
2 ttl: 15,
3 authorizedUserId: 'catalog-service',
4 resources: {
5 dataSync: {
6 entities: { 'product-sneaker-42': { create: true, get: true, delete: true } },
7 relationships: { 'wishlist-alice-sneaker': { create: true, get: true, delete: true } },
8 memberships: { 'membership-alice-summer-sale': { create: true, get: true, delete: true } },
9 },
10 users: { 'user-alice': { create: true, get: true, delete: true } },
11 channels: { 'channel-summer-sale': { create: true, get: true, delete: true } },
12 },
13})
1PNResult<PNAccessManagerTokenResult> catalogGrant = await pubnub.GrantToken()
2 .TTL(15)
3 .AuthorizedUserId("catalog-service")
4 .Resources(new PNTokenResources
5 {
6 DataSync = new PNDataSyncTokenScopes
7 {
8 Entities = new Dictionary<string, PNTokenAuthValues> { { "product-sneaker-42", new PNTokenAuthValues { Create = true, Get = true, Delete = true } } },
9 Relationships = new Dictionary<string, PNTokenAuthValues> { { "wishlist-alice-sneaker", new PNTokenAuthValues { Create = true, Get = true, Delete = true } } },
10 Memberships = new Dictionary<string, PNTokenAuthValues> { { "membership-alice-summer-sale", new PNTokenAuthValues { Create = true, Get = true, Delete = true } } },
11 },
12 Users = new Dictionary<string, PNTokenAuthValues> { { "user-alice", new PNTokenAuthValues { Create = true, Get = true, Delete = true } } },
13 Channels = new Dictionary<string, PNTokenAuthValues> { { "channel-summer-sale", new PNTokenAuthValues { Create = true, Get = true, Delete = true } } },
14 })
15 .ExecuteAsync();
A token without a projection grant reads and writes the __default__ view. The catalog service can't create a user with email, because email belongs only to the admin projection. The request fails with a 403 and error code DS-0202. Set admin-only fields from your server.
Grant a shopper read access
Alice reads her own user, her memberships, and every product, and subscribes to product updates. Pattern grants cover every ID that matches the regular expression, so product-.* covers product-sneaker-42 and any product added later. The projection grant makes every product read return the public view.
- JavaScript
- C#
1const aliceToken = await pubnub.grantToken({
2 ttl: 15,
3 authorizedUserId: 'user-alice',
4 resources: {
5 users: { 'user-alice': { get: true, update: true } },
6 channels: {
7 'channel-summer-sale': { get: true, read: true },
8 '__public__product-sneaker-42': { read: true },
9 },
10 },
11 patterns: {
12 dataSync: {
13 entities: { 'product-.*': { get: true } },
14 memberships: { 'membership-alice-.*': { get: true } },
15 },
show all 20 lines1PNResult<PNAccessManagerTokenResult> aliceGrant = await pubnub.GrantToken()
2 .TTL(15)
3 .AuthorizedUserId("user-alice")
4 .Resources(new PNTokenResources
5 {
6 Users = new Dictionary<string, PNTokenAuthValues> { { "user-alice", new PNTokenAuthValues { Get = true, Update = true } } },
7 Channels = new Dictionary<string, PNTokenAuthValues>
8 {
9 { "channel-summer-sale", new PNTokenAuthValues { Get = true, Read = true } },
10 { "__public__product-sneaker-42", new PNTokenAuthValues { Read = true } },
11 },
12 })
13 .Patterns(new PNTokenPatterns
14 {
15 DataSync = new PNDataSyncTokenScopes
show all 28 linesUser entities use the users resource type and channels use channels. Reading a user or channel entity uses get. read on a channel gates subscribe access.
Alice can read products but can't create them. A create with this token fails with a 403.
ID channels carry the default view
An object's ID channel, such as product-sneaker-42, carries the __default__ view in every event, whatever projection the subscriber's token has. It also carries events about the entities linked to that object. That's why Alice gets read on __public__product-sneaker-42 rather than on product-sneaker-42: the ID channel would send her stock. Grant read on an ID channel only to clients that may see the __default__ view of the object and of everything linked to it. Refer to Events.
Grant a support agent the admin projection
The support agent reads Alice's email, which only the admin projection includes. The token assigns admin to user-alice and grants read on the projection channel __admin__user-alice, so the agent also receives email changes in real time.
- JavaScript
- C#
1const supportToken = await pubnub.grantToken({
2 ttl: 15,
3 authorizedUserId: 'support-agent',
4 resources: {
5 users: { 'user-alice': { get: true } },
6 channels: { '__admin__user-alice': { read: true } },
7 },
8 dataSyncProjections: {
9 resources: { users: { 'user-alice': 'admin' } },
10 },
11})
1PNResult<PNAccessManagerTokenResult> supportGrant = await pubnub.GrantToken()
2 .TTL(15)
3 .AuthorizedUserId("support-agent")
4 .Resources(new PNTokenResources
5 {
6 Users = new Dictionary<string, PNTokenAuthValues> { { "user-alice", new PNTokenAuthValues { Get = true } } },
7 Channels = new Dictionary<string, PNTokenAuthValues> { { "__admin__user-alice", new PNTokenAuthValues { Read = true } } },
8 })
9 .DataSyncProjections(new PNDataSyncProjections
10 {
11 Resources = new PNDataSyncProjectionScope
12 {
13 Users = new Dictionary<string, string> { { "user-alice", "admin" } },
14 },
15 })
show all 16 linesA read with this token returns only the fields in the admin projection, so getUser for user-alice returns email without name or display_name. Permission on user-alice doesn't cover the projection channel. Grant read on __admin__user-alice separately.
Refer to Grant token (JavaScript) and Grant token (C#) for the full parameter reference.
Choose permissions per operation
| Operation | Resource type | Permission |
|---|---|---|
| Read a DataSync object | datasync:entities, datasync:relationships, datasync:memberships, users, channels | get |
| Create a DataSync object | Same | create |
| Replace or patch a DataSync object | Same | update |
| Delete a DataSync object | Same | delete |
| Subscribe to an entity's ID channel or projection channel for events | channels | read |