Untrusted client

Follow sections sequentially to complete demonstration of an access from an untrusted client.

Create application

Login to Jazer’s dashboard. Create a new application by clicking on the create new app button. A dialog will be shown asking for an application name. Give it a name like Untrusted client test and click on the create button. An application will then be created and shown in the application list. Click on the newly created application in the application list to open application page.

Create API key

Open API keys using left sidebar menu item api-key-menu-item-icon. Create a new API key using toolbar item create-icon. A dialog will be shown asking for an API key name. Give it a name like Untrusted API key and click on the create button. API key will be created with no permissions. To add a permission use permissions toolbar item add-icon. Use /resources/todo for the path and enable methods GET and POST. Turn ACL on. Add two more permissions for users one with path /users/core\.user and other with path /users/core\.user\.token. On both enable POST method and leave ACL turned off. Add another two permissions for inspecting ACL. One with the path /resources/todo\.acl/[0-9a-fA-F]{24} and the other with the path /resources/todo\.acl\.acl/[0-9a-fA-F]{24}. On both enable GET method and turn ACL on. Save API key changes using toolbar item save-changes-icon.

../_images/api-key-untrusted-api-key-created.png

To protect data ACL should be turned on for untrusted client API key permissions. There are cases when it is safe to turn it off like for fetching public data. When permission undergoes ACL each document ACL record is checked against users credentials. The client, therefore, needs to authenticate a user.

Find application ID

Open the metadata page using left sidebar menu item metadata-menu-item-icon. Application ID is presented alongside other application metadata. The client must supply application ID in the application-id header in each API request.

Create user

To create a user make API request:

curl -H 'Content-Type: application/vnd.api+json' \
-H 'Accept: application/vnd.api+json' \
-H 'api-key: <YOUR_API_KEY_SECURE_ID>' \
-H 'application-id: <YOUR_APPLICATION_ID>' \
-d '
{
  "data": {
    "type": "core.user",
    "attributes": {
      "username": "john.smith",
      "password": "aDayInTheLife"
    }
  }
}' \
-X POST https://api.jazer.com/users/core.user

The response will contain created user:

{
  "data": {
    "type": "core.user",
    "id": "59bee9ffac610577a9bae5b1",
    "attributes": {
      "username": "john.smith",
      "password": "$2a$11$vD7Ky82IX5cD6tYWeIpQ8e9jH1NHbYbAzdUrhJcJFVAlCdOxHVBD6"
    },
    "links": {
      "self": "https://api.jazer.io/users/core.user/59bee9ffac610577a9bae5b1"
    }
  }
}

Note

System types usually have prefix core.

Create token

To create an authentication token for a user make API request with Authorization header where value starts with Basic followed by base64 encoded <USERNAME>:<PASSWORD>. Created user would encode john.smith:aDayInTheLife where the result would be am9obi5zbWl0aDphRGF5SW5UaGVMaWZl. Online service can be used to base64 encode while testing.

curl -H 'Accept: application/vnd.api+json' \
-H 'api-key: <YOUR_API_KEY_SECURE_ID>' \
-H 'application-id: <YOUR_APPLICATION_ID>' \
-H 'Authorization: Basic am9obi5zbWl0aDphRGF5SW5UaGVMaWZl' \
-X POST https://api.jazer.io/users/core.user.token

The response will contain created token:

{
  "data": {
    "type": "core.user.token",
    "id": "59bef133ac610577a9bae5b7",
    "attributes": {
      "token": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJ0b2tlbiI6eyJ0eXBlIjoiY29yZS51c2VyLnRva2VuIiwiaWQiOiI1OWJlZjEzM2FjNjEwNTc3YTliYWU1YjcifSwidXNlciI6eyJ0eXBlIjoiY29yZS51c2VyIiwiaWQiOiI1OWJlZTlmZmFjNjEwNTc3YTliYWU1YjEifSwiaXNzIjoiamF6ZXIiLCJpYXQiOjE1MDU2ODU4MTEsImV4cCI6MTUwODI3NzgxMX0.MEUCIQC3xyKTm8BONMA2D7-TEQHQRvwkHtB7LCcb_RSt-snZ_wIgEuoeGQrFFHlKGTK9rLyVq2lH25CjJ7IcMyUtLVWqedI",
      "created": "2017-09-17T22:03:31.060Z"
    },
    "relationships": {
      "user": {
        "data": {
          "type": "core.user",
          "id": "59bee9ffac610577a9bae5b1"
        }
      }
    },
    "links": {
      "self": "https://api.jazer.io/users/core.user.token/59bef133ac610577a9bae5b7"
    }
  }
}

Create resource

Create a todo resource. A user token must be supplied in Authorization header since API key permission for todo resource is protected with ACL.

curl -H 'Content-Type: application/vnd.api+json' \
-H 'Accept: application/vnd.api+json' \
-H 'api-key: <YOUR_API_KEY_SECURE_ID>' \
-H 'application-id: <YOUR_APPLICATION_ID>' \
-H 'Authorization: Token <JOHN_SMITH_USER_TOKEN>' \
-d '
{
  "data": {
    "type": "todo",
    "attributes": {
      "title": "Buy flowers"
    }
  }
}' \
-X POST https://api.jazer.io/resources/todo

The response will contain createded todo resource:

{
  "data": {
    "type": "todo",
    "id": "59bef4cdac610577a9bae5bb",
    "attributes": {
      "title": "Buy flowers"
    },
    "links": {
      "self": "https://api.jazer.io/resources/todo/59bef4cdac610577a9bae5bb"
    }
  }
}

Fetch resources

Make an API request to fetch all todo resources:

curl -H 'Accept: application/vnd.api+json' \
-H 'api-key: <YOUR_API_KEY_SECURE_ID>' \
-H 'application-id: <YOUR_APPLICATION_ID>' \
-H 'Authorization: Token <JOHN_SMITH_USER_TOKEN>' \
-X GET https://api.jazer.io/resources/todo

The response will contain previously created todo resource:

{
  "meta": {
    "count": 1
  },
  "data": [
    {
      "type": "todo",
      "id": "59bef4cdac610577a9bae5bb",
      "attributes": {
        "title": "Buy flowers"
      },
      "links": {
        "self": "https://api.jazer.io/resources/todo/59bef4cdac610577a9bae5bb"
      }
    }
  ],
  "links": {
    "first": "https://api.jazer.io/resources/todo?page[offset]=0&page[limit]=20",
    "last": "https://api.jazer.io/resources/todo?page[offset]=0&page[limit]=20",
    "prev": null,
    "next": null
  }
}

Create another user and a token for that user. Fetch all todo resources using the new token. The response will contain zero todo resources. When the user John Smith created Buy flowers todo resource, all ACL rights were automatically assigned to him. Any other user who uses API key which undergoes ACL for todo resources will not see Buy flowers todo resource. Since API key has permission to read ACL record, ACL of a created todo can be inspected using API request:

curl -H 'Accept: application/vnd.api+json' \
-H 'api-key: <YOUR_API_KEY_SECURE_ID>' \
-H 'application-id: <YOUR_APPLICATION_ID>' \
-H 'Authorization: Token <JOHN_SMITHS_USER_TOKEN>' \
-X GET https://api.jazer.io/resources/todo.acl/<TODO_ID>

The response will contain ACL record for a given todo resource:

{
  "data": {
    "type": "todo.acl",
    "id": "59bef4cdac610577a9bae5bb",
    "attributes": {
      "read": [
        {
          "id": "59bee9ffac610577a9bae5b1",
          "type": "core.user"
        }
      ],
      "update": [
        {
          "id": "59bee9ffac610577a9bae5b1",
          "type": "core.user"
        }
      ],
      "delete": [
        {
          "id": "59bee9ffac610577a9bae5b1",
          "type": "core.user"
        }
      ]
    },
    "links": {
      "self": "https://api.jazer.io/resources/todo.acl/59bef4cdac610577a9bae5bb"
    }
  }
}

ACL record of a resource shows who is allowed to perform a specific operation on a resource. The user John Smith could update ACL record appending other users to read array. When other user makes API request to fetch todo resources then the result would contain one John Smith created. The user John Smith can update ACL record appending other users to update array allowing them to update todo resource. This does not imply that other users have right to change ACL record of that resource. They have only right to change the resource. To be able to change ACL record they need to have an update right in a super ACL record. Super ACL record is basically ACL record for ACL record of a resource. API request to inspect super ACL:

curl -H 'Accept: application/vnd.api+json' \
-H 'api-key: <YOUR_API_KEY_SECURE_ID>' \
-H 'application-id: <YOUR_APPLICATION_ID>' \
-H 'Authorization: Token <JOHN_SMITHS_USER_TOKEN>' \
-X GET https://api.jazer.io/resources/todo.acl.acl/<TODO_ID>

The response will contain super ACL record of a given todo resource:

{
  "data": {
    "type": "todo.acl.acl",
    "id": "59bef4cdac610577a9bae5bb",
    "attributes": {
      "read": [
        {
          "id": "59bee9ffac610577a9bae5b1",
          "type": "core.user"
        }
      ],
      "update": [
        {
          "id": "59bee9ffac610577a9bae5b1",
          "type": "core.user"
        }
      ]
    },
    "links": {
      "self": "https://api.jazer.io/resources/todo.acl.acl/59bef4cdac610577a9bae5bb"
    }
  }
}

Super ACL record shows who can read and update ACL record of a resource. There is no delete operation since ACL records are system types which are automatically created with the resource and cannot be deleted.

More info

API keys and Users explain in detail how is security enforced. Visit Resources to see which other operations are supported for resources. Further enhance security by validating resource data using Schemas.