Skip to content

Commit

Permalink
Added support for TIFF in upload, Update examples, fix preview instru…
Browse files Browse the repository at this point in the history
…ctions (#24)

2024-04-02
  • Loading branch information
mikk-o authored Apr 2, 2024
1 parent 6e22e89 commit 6a83079
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 20 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Changelog

## 2024-04-02

### 🧰 Added
- `@canva/asset`
- Added support for TIFF in `upload`

### 🔧 Changed
- Minor fix in [README.md](./README.md) Step 2: Preview the app to reflect the latest instructions.
- `examples`
- Updated the [/examples/design_token](/examples/design_token) example to include more checks against important JWT claims.
- Downgraded ExpressJS module used in [/examples/design_token](/examples/design_token) from v5 to v4 to be consistent with other examples.

## 2024-03-21

### 🧰 Added
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ The local development server only exposes a JavaScript bundle, so you can't prev

To preview an app:

1. Create an app via the [Developer Portal](https://www.canva.com/developers).
1. Create an app via the [Developer Portal](https://www.canva.com/developers/apps).
2. Select **App source > Development URL**.
3. In the **Development URL** field, enter the URL of the development server.
4. Click **Preview**. This opens the Canva editor (and the app) in a new tab.
5. Click **Use**. (This screen only appears when when using an app for the first time.)
5. Click **Open**. (This screen only appears when using an app for the first time.)

The app will appear in the side panel.

Expand Down
62 changes: 58 additions & 4 deletions examples/design_token/backend/decode_jwt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,24 @@ const CACHE_EXPIRY_MS = 60 * 60 * 1_000; // 60 minutes
const TIMEOUT_MS = 30 * 1_000; // 30 seconds
const CANVA_BASE_URI = "https://api.canva.com";

/**
* The JWT payload we'll decode contains:
* designId - The ID of the Canva Design where this token was issued.
* aud (audience) - We use the App ID to identify the targeted audience for this payload.
* exp (expiry) - The expiry timestamp for this JWT, in seconds.
* iat (issuedAt) - The timestamp at which this JWT was issued, in seconds.
* nbf (notBefore) - The JWT should only be valid after this timestamp, in seconds.
*
* See the JWT specification for more details on each claim and what it represents.
* https://datatracker.ietf.org/doc/html/rfc7519#section-4.1
*/
type DesignToken = Omit<jwt.Jwt, "payload"> & {
payload: {
designId: string;
appId: string;
userId: string;
aud: string;
exp: number;
iat: number;
nbf: number;
};
};

Expand Down Expand Up @@ -42,9 +55,50 @@ export const decodeAndVerifyDesignToken = async (
});
const key = await jwksClient.getSigningKey(unverifiedDecodedToken.header.kid);
const publicKey = key.getPublicKey();
const verifiedToken = jwt.verify(designToken, publicKey, {
const { payload } = jwt.verify(designToken, publicKey, {
audience: appId,
complete: true,
}) as DesignToken;
return verifiedToken.payload;

if (payload.designId == null || payload.aud == null) {
throw new jwt.JsonWebTokenError("Invalid JWT payload");
}

/**
* Convert current timestamp to seconds, as determined by the NumericDate object in the JWT specifications
* See https://datatracker.ietf.org/doc/html/rfc7519#section-2
*/
const now = convertMillisecondsToSeconds(Date.now());

/**
* Dates provided in a JWT payload are in seconds, as per the NumericDate object in the JWT specification.
* See https://datatracker.ietf.org/doc/html/rfc7519#section-2
* We convert them to milliseconds before creating JS Date objects.
*/
if (payload.exp < now) {
throw new jwt.TokenExpiredError(
"The provided DesignToken has expired.",
new Date(convertSecondsToMilliseconds(payload.exp))
);
}

if (payload.iat > now) {
throw new jwt.NotBeforeError(
"Invalid issue date for DesignToken",
new Date(convertSecondsToMilliseconds(payload.iat))
);
}

if (payload.nbf > now) {
throw new jwt.NotBeforeError(
"Cannot verify DesignToken prior to the NotBefore date",
new Date(convertSecondsToMilliseconds(payload.nbf))
);
}

return payload;
};

const convertSecondsToMilliseconds = (seconds: number) => seconds * 1000;
const convertMillisecondsToSeconds = (milliseconds: number) =>
milliseconds / 1000;
2 changes: 1 addition & 1 deletion examples/design_token/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
},
"dependencies": {
"cors": "^2.8.5",
"express": "^5.0.0-beta.2",
"express": "^4.19.2",
"jsonwebtoken": "^9.0.2",
"jwks-rsa": "^3.1.0"
}
Expand Down
24 changes: 12 additions & 12 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
],
"dependencies": {
"@canva/app-ui-kit": "^3.4.0",
"@canva/asset": "^1.4.0",
"@canva/asset": "^1.5.0",
"@canva/design": "^1.6.0",
"@canva/error": "^1.1.0",
"@canva/platform": "^1.0.1",
Expand Down

0 comments on commit 6a83079

Please sign in to comment.