HTTP request verification

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(opens in a new tab or window).

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.

For Node.js backends, the @canva/app-middleware(opens in a new tab or window) package simplifies the verification process by automatically handling token extraction, JWKS fetching, and JWT validation.

Some standard web APIs aren't available. To learn more, see Content Security Policy.

Step 1: Get a JWT from Canva

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.

Step 2: Send a request

  1. Use the Fetch API, or a library such as axios(opens in a new tab or window), 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.

Step 3: Verify the request

To verify the request, you can either use the @canva/app-middleware package (recommended), or manually implement your own verification.

For Node.js backends, use the @canva/app-middleware package to automatically verify requests:

Express.js middleware

import express from "express";
import { user } from "@canva/app-middleware/express";
const app = express();
// Apply middleware to verify all requests
app.use("/my/api", user.verifyToken({ appId: process.env.CANVA_APP_ID }));
app.post("/my/api/endpoint", (req, res) => {
// Access verified user information
const { userId, brandId } = req.canva.user;
// Your application logic here
res.sendStatus(200);
});
app.listen(process.env.PORT || 3000);
TYPESCRIPT

For more information, see user.verifyToken.

Framework-agnostic approach

For other Node.js environments:

import { initUserTokenVerifier } from "@canva/app-middleware";
// Initialize once at app startup
const userTokenVerifier = initUserTokenVerifier({
appId: process.env.CANVA_APP_ID,
});
// In your request handler
async function handleRequest(request) {
const authHeader = request.headers.authorization;
const token = authHeader?.replace("Bearer ", "");
if (!token) {
return { status: 401, body: "Unauthorized" };
}
try {
const { userId, brandId } = await userTokenVerifier.verify(token);
// Your application logic here
return { status: 200, body: "Success" };
} catch (error) {
return { status: 401, body: "Unauthorized" };
}
}
TYPESCRIPT

For more information, see initUserTokenVerifier.

Alternative: Manual verification

If you're using a non-Node.js backend, you can manually extract and verify JWTs. Here's an example using Python with Flask:

Step 3a: Extract the JWT

When the backend receives a request, extract the JWT from the Authorization header:

from flask import Flask, request, jsonify
from functools import wraps
app = Flask(__name__)
def extract_token(auth_header):
"""Extract JWT from Authorization header"""
if not auth_header:
return None
parts = auth_header.split()
if len(parts) != 2 or parts[0].lower() != 'bearer':
return None
return parts[1]
@app.route('/my/api/endpoint', methods=['POST'])
def api_endpoint():
auth_header = request.headers.get('Authorization')
token = extract_token(auth_header)
if not token:
return jsonify({'error': 'Unauthorized'}), 401
# Verify token (see next step)
# ...
return jsonify({'message': 'Success'}), 200
PYTHON

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

Step 3b: Verify the JWT

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 JSON Web Tokens.

Step 3c: Reject invalid requests

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 aren't available, reject the request with a 401 status code:

if not verified.aud or not verified.brandId or not verified.userId:
return jsonify({'error': 'Unauthorized'}), 401
PYTHON

API reference