Client Authentication

The JSON Web Token (JWT) is signed with a private key on your server and verified with the public key on PSPDFKit Server.

PSPDFKit Server uses the JSON Web Token (JWT) format for authentication. Your backend signs a JWT asserting that the holder of the token is allowed access to a given document. Next, it passes the JWT to your client apps that use PSPDFKit for Android, iOS, and Web. Your app then passes its token to PSPDFKit Server to prove that it has access to the claimed document.

You can generate a token with one of the many open source libraries that are available and listed on jwt.io.

Things to keep in mind when generating a token:

  • It has to include the standard claim "exp", which sets the deadline for the validity of the token. This needs to be a non-negative number using the Unix “Seconds Since the Epoch” timestamp format.

  • It has to include the user-defined claims "document_id" and "permissions".

    • "document_id" is the identifier of a document that has been previously uploaded to the server. This field has to be a string value.

    • "permissions" is a list of permission names that define which features will be accessible to the holder of this token. See the Permissions section below for more details.

  • It may include the "user_id" claim, which will be stored on any annotation created, updated, or deleted by the user.

  • It may include the "layer" claim, which defines the Instant layer that all changes will be persisted to.

  • It may include the "password" claim, which defines the password to be used to open password-protected PDFs.

  • It has to be signed using an asymmetric cryptographic algorithm. PSPDFKit Server supports the algorithms RS256, RS512, ES256, and ES512. See RFC 7518 for details about specific algorithms.

Permissions

Available permissions:

  • "read-document" — required for viewing a document and its annotations. Without this permission, it won’t be possible for the user to load the document and perform any operations on it.

  • "write" — required for creating, updating, and deleting annotations in a document. If this permission is not present, PSPDFKit for Web will always be in read-only mode.

  • "download" — required for downloading and printing a document’s PDF file.

  • "cover-image" — required for accessing the /documents/cover endpoint.

Any combination of the above permissions can be included in the permissions list when generating a JWT. Apart from that, the permissions field of a JWT may have one of the following special values:

  • "all-2017.3" will enable all permissions available in the 2017.3 release, namely "read-document", "write", and "download".

  • "all-2017.9" will enable all permissions available in the 2017.9 release, namely "read-document", "write", "download", and "cover-image".

  • "all" will enable all permissions supported by the running version of the server.

Generating Tokens

The following example shows the creation of a JWT in a Node/Express app using the jsonwebtoken library. It assumes you chose the RS256 algorithm and have created a pair of private and public keys.

To create a key, you can use ssh-keygen:

Copy
1
2
3
4
5
ssh-keygen -t rsa -b 4096 -f jwtRS256.key
# Enter your passphrase.

# Get the public key in PEM format:
openssl rsa -in jwtRS256.key -pubout -outform PEM -out jwtRS256_pub.pem

Now use the private key to sign the tokens you hand out to the clients and add the public key to the server’s configuration so that the server will be able to validate the tokens’ signatures.

If you want to quickly test PSPDFKit for Web with your application, you can also use the key from our example apps (passphrase: secret). Make sure to change to a self-generated key before going into production:

Copy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// index.js

const express = require("express");
const router = express.Router();
const fs = require("fs");
const jwt = require("jsonwebtoken");
const key = fs.readFileSync("./jwt.pem");
const permissions = ["read-document", "write"];
const token = jwt.sign(
  { document_id: "abc", permissions: permissions },
  key,
  {
    algorithm: "RS256",
    expiresIn: 60 * 60 // 1hr, this will set the `exp` claim for us.
  }
);

/* GET home page. */
router.get("/", function(req, res, next) {
  res.render("index", { token: token });
});

module.exports = router;

Troubleshooting

If you are having trouble authenticating your clients, you can validate your JWT in the PSPDFKit Server Dashboard. This allows you to check if you are missing any claims and if your JWT is in the correct format.