Rate this page:
Asynchronously request a signed JWT from Trello for the current member.
1 2 3 4 5 6 7 8 9 10 11
window.TrelloPowerUp.initialize({
'board-buttons': async function (t, opts) {
if (t.isMemberSignedIn()) {
const jwt = await t.jwt({
state: JSON.stringify({ hello: 'world' }),
});
console.log(jwt);
}
return [];
}
});
If you checked the console you would find a JWT like:
1
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZFBsdWdpbiI6IjVlNjY3ODRjNjA2Y2IxMTYwYThmNWRjMCIsImlkQm9hcmQiOiI1ZTY2NzgxMTYwNmNiMTE2MGE4ZjViZjciLCJpZE1lbWJlciI6IjVlNjQ1ZGMyYzQyMDVlMTQxNjIxODQwNCIsInN0YXRlIjoidGVzdCIsImlhdCI6MTU4Mzg1ODY2OCwiZXhwIjoxNTgzODU5NTY4LCJpc3MiOiJ0cmVsbG8ifQ.GubnXxnGTN0-rk3hQL_BDMDYjh-cbKldpQNWBi5aIhxqiuPyVSE9grbBjk7DSU3nn8YT3GmqgLu0SUv4K-ir53GptEfRAN1_jRrMrLj5HNosteeqeQV18qK1v_Tg0EzLpJg29JF62dfrDwG-aYsdjMKAIDbY7gyWCyv8O7xsSdzj1mwiMXS2xbhNTIIatxKq6jiRV82lIHV6iCmir0_Gj4Xg1gbMLwG8FfijDmEQTpdXm6DdMsTmm_Ep-T-rFreSSIOF6Qq9Ee03EkkjHxzCqvWGZzU-bF6EVLU5oVdPs9V0_KOBcKsaoKgMaIsSgT5C1tVC_Am6YmFTUBtSDWg0AzGLn2-4dsL_mWfylSgNBqyANeVpFISZJaGNS5Zw8-lBzN3kO_0IvVWfF3ESaCDGra3rjEfphcnNWaVafGSsh2KftlZ_LWoc6lYTcTEow19IvfLU3R3f3Ywa3Gv7-WwQt0F2Npq6E4qGyQucmjy7-u4ns8KwAzP5sej23s6G1ni2utMiqOv1EPzyusR32bVhe7Ps0aANXgFIWlJtGo8rvJeSwrnXZodJx2L3GgY5WBMP271wgvQB-kOcAkf0uIP8WzAycEd8-voYBeB28KMIQatWpRngO4c-DexG4Wr1LAt4YmbyDZzxC4mQZah4kkxsx-0IxA06UhqqETAllVjtUIQ
We can use https://jwt.io to better understand what this JWT contains.
We see the payload is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
{
// the id of your Power-Up
idPlugin: "5e66784c606cb1160a8f5dc0",
// the id of the board the user is currently using your Power-Up on
idBoard: "5e667811606cb1160a8f5bf7",
// the id of the member currently using your Power-Up
idMember: "5e645dc2c4205e1416218404",
// optional Power-Up defined state, max of 2048 characters
state: "test",
// issued at time, in seconds
iat: 1583858668,
// expiration time, in seconds
exp: 1583859568,
// issuer
iss: "trello"
}
The purpose of these JWTs is for you to be able to secure the communication between your Power-Up and your server. If you need to know that a request made by your Power-Up was made on behalf of a particular Trello user, you have two main ways of accomplishing that.
t.jwt()
method and send the resulting JWT with requests to your server.Here we will go into more details on what you would do on your server to decode and validate the JWT.
To start we recommend checking out the recommended libraries for your programming language / environment on jwt.io.
For this example we will assume a NodeJS environment and use jsonwebtoken.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
const bent = require('bent');
const jwt = require('jsonwebtoken');
const getJSON = bent('json', { 'user-agent': 'bent/7.1.1' });
let publicKeys;
let publicKeysExpiry;
const getPublicKeys = async () => {
// get a fresh set if needed
if (!publicKeys || publicKeysExpiry < Date.now()) {
const resp = await getJSON('https://api.trello.com/1/resource/jwt-public-keys');
publicKeys = resp.keys;
// cache for 4 hours
publicKeysExpiry = Date.now() + 14400000;
}
return publicKeys;
};
const decodeAndValidate = async (token) => {
const publicKeys = await getPublicKeys();
// the vast majority of the time, Trello will provide a single public key
// but should Trello need to rotate our keys we may for brief periods serve
// two public keys
const errors = [];
for (let key of publicKeys) {
try {
decoded = jwt.verify(token, key);
return decoded;
} catch (err) {
errors.push(err);
}
}
// there are a variety of reasons it might not be valid
// the JWT could be expired, or the signature could be invalid for example
throw errors[0];
};
Ok, so how do we know Trello's public key? Trello publishes a list of our in use public keys at: https://api.trello.com/1/resource/jwt-public-keys
1 2 3 4 5
{
"keys": [
"-----BEGIN PUBLIC KEY-----\nMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvBoGlGS7BZSHL5G2HWIu\nlWC+5QlUGe25630GfuKiLBzOF5N2BnBq5fMwM1W86Ur4zgfJt88UidWxyAw14JD3\nnPLjtRQZVJQNtoesVhhzXuDe+/jNWXNLJfgwRV7+Jl/p2B+vIMOjdN5QZp+mjNM8\nx/TJjHIldtIDHJJUZ1NbI0GLQ4a9VtZz+B0WquQkeSUVmuiA/nFZP6w0mGWRz+qr\nuO9pZnQwU6pHOLzbZpGOAbnsMelE1C4D7ofHH6i/sXvPHmgNwe7ndkC+6FcPrbB8\n+imYJVoR3am5AwIAjDLHz1BM4IVmJrNJknh/RaFZNAZ4573oZPrq/szlG7BGugKo\nz0DjbbrW5NjO+9/B+4mXtt4k7uc8C4WoaPYFX0SZVLgEOyxnsvHO+Cp/4U8XiZel\nW1He30argtYFx/LtMnj6+PiFbsx5hOsiiHpdobFHImy/5dLReIC7HAhYI+NjXCru\nKINBV5F9fbA2YAUVWdFnDs4xdh6eGQCXsZkczS8/EZ5HnQzwc9Lpr0pZTkxB1089\nwls56RLb/GVWloRAwXmMCdRDKj2g9HbQWcCLjVavwCUg8zGgl0R0LxLfpPd0qUxj\nQ/m9a5+R5P6+YMVlY8ve5Ou6B4IU7k+g5/Qbyf6dpJtZhE2R8LMtKNai5SGlCMy9\n1gfQ+Ynk+Ve6h5RiJOIbrf0CAwEAAQ==\n-----END PUBLIC KEY-----"
]
}
This is a list so that if Trello needs to rotate our private key, we can do so without breaking your Power-Ups, as we will publish the new public key in advance of beginning to sign with its private key counterpart.
We recommend that you poll this route perhaps daily, but at most hourly, and also have logic in your application to request the latest public keys in the event of a signature verification error.
Rate this page: