Verifying HTTP requests

How to verify the authenticity of HTTP requests.

At their most basic, apps are web pages embedded in an iframe. As a result, they have access to many standard web APIs, including the Fetch API.

Using the Fetch API in an app is the same as using it anywhere else, but before you can release your app publicly, we require that your app's backend verifies the authenticity of incoming requests. This ensures that requests are arriving from the app and not from some other, potentially malicious source.

Before an app sends an HTTP request to its backend, it must request a JSON Web Token (JWT) from Canva. The app's backend can use this JWT to verify that the request is legitimate.

To get a JWT:

  1. Import the auth namespace from the @canva/user package:

    import { auth } from "@canva/user";
    ts
  2. Call the getCanvaUserToken method:

    const token = await auth.getCanvaUserToken();
    ts

    This method returns a JWT as a string.

  1. Use the Fetch API, or a library such as axios, to send an HTTP request:

    const response = await fetch("http://localhost:3001/my/api/endpoint");
    ts
  2. In the headers of the request, include an Authorization header:

    const response = await fetch("http://localhost:3001/my/api/endpoint", {
    headers: {
    Authorization: `Bearer ${token}`,
    },
    });
    ts

    The header should contain the word Bearer and the JWT, separated by a space.

When the backend receives a request, extract the JWT from the Authorization header. The following code samples how to extract a JWT from an Express.js Request object:

import express from "express";
const app = express();
app.post("/my/api/endpoint", async (request, response) => {
const token = getTokenFromHeader(request);
if (!token) {
return response.sendStatus(401);
}
return response.sendStatus(200);
});
app.listen(process.env.PORT || 3000);
function getTokenFromHeader(request: express.Request) {
const header = request.headers["authorization"];
if (!header) {
return;
}
const parts = header.split(" ");
if (parts.length !== 2 || parts[0].toLowerCase() !== "bearer") {
return;
}
const [, token] = parts;
return token;
}
ts

If the Authorization header doesn't contain a token, reject the request with a 401 status code.

By itself, the JWT is an indecipherable string. To get useful information out of the JWT, it needs to be decoded and verified. To learn how to do this, see Verifying JWTs.

The verified JWT is an object that should contain the following properties:

  • aud - The ID of the app.
  • brandId - The ID of the user's team.
  • userId - The ID of the user.

If any of these properties are not available, reject the request with a 401 status code:

if (!verified.aud || !verified.brandId || !verified.userId) {
return response.sendStatus(401);
}
ts