From 15d631c412b3c13c8d996d409a524d1061286cf4 Mon Sep 17 00:00:00 2001 From: ekadin-mtc <105028623+ekadin-mtc@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:28:55 -0400 Subject: [PATCH] feat(JWT Node): Add an option to allow a "kid" (key ID) header claim (#9797) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: कारतोफ्फेलस्क्रिप्ट™ --- packages/nodes-base/nodes/Jwt/Jwt.node.ts | 22 +- .../nodes/Jwt/test/jwt.workflow.json | 474 +++++++++++++----- 2 files changed, 359 insertions(+), 137 deletions(-) diff --git a/packages/nodes-base/nodes/Jwt/Jwt.node.ts b/packages/nodes-base/nodes/Jwt/Jwt.node.ts index 816a48da13..3f86671b8c 100644 --- a/packages/nodes-base/nodes/Jwt/Jwt.node.ts +++ b/packages/nodes-base/nodes/Jwt/Jwt.node.ts @@ -260,6 +260,20 @@ export class Jwt implements INodeType { }, }, }, + { + displayName: 'Key ID', + name: 'kid', + type: 'string', + placeholder: 'e.g. 123456', + default: '', + description: + 'The kid (key ID) claim is an optional header claim, used to specify the key for validating the signature', + displayOptions: { + show: { + '/operation': ['sign'], + }, + }, + }, { displayName: 'Override Algorithm', name: 'algorithm', @@ -349,6 +363,7 @@ export class Jwt implements INodeType { ignoreExpiration?: boolean; ignoreNotBefore?: boolean; clockTolerance?: number; + kid?: string; }; try { @@ -375,9 +390,12 @@ export class Jwt implements INodeType { secretOrPrivateKey = formatPrivateKey(credentials.privateKey); } - const token = jwt.sign(payload, secretOrPrivateKey, { + const signingOptions: jwt.SignOptions = { algorithm: options.algorithm ?? credentials.algorithm, - }); + }; + if (options.kid) signingOptions.keyid = options.kid; + + const token = jwt.sign(payload, secretOrPrivateKey, signingOptions); returnData.push({ json: { token }, diff --git a/packages/nodes-base/nodes/Jwt/test/jwt.workflow.json b/packages/nodes-base/nodes/Jwt/test/jwt.workflow.json index b87ef4e7e1..5330e25914 100644 --- a/packages/nodes-base/nodes/Jwt/test/jwt.workflow.json +++ b/packages/nodes-base/nodes/Jwt/test/jwt.workflow.json @@ -1,15 +1,15 @@ { - "name": "My workflow 31", + "name": "JWT Test Workflow", "nodes": [ { "parameters": {}, - "id": "fcc3e9dc-90c9-4b26-9b44-e661e0ebf658", + "id": "66c858d2-822e-4177-a379-d5e2aef9f6da", "name": "When clicking ‘Test workflow’", "type": "n8n-nodes-base.manualTrigger", "typeVersion": 1, "position": [ - 780, - 380 + -260, + 840 ] }, { @@ -22,39 +22,38 @@ }, "options": {} }, - "id": "6b1ba38f-60d8-482a-a7d4-4fee7054334b", - "name": "JWT", + "id": "675b43b8-f079-4bcf-8ea2-52c3c60a3a42", + "name": "Sign with claims", "type": "n8n-nodes-base.jwt", "typeVersion": 1, "position": [ - 1000, - 380 + 120, + 400 ], "credentials": { "jwtAuth": { - "id": "AosB7WdhmVA3be8t", - "name": "JWT Auth test" + "id": "kDnfvqrCBJvtlX3o", + "name": "JWT Auth account" } } }, { "parameters": { - "operation": "decode", - "token": "={{ $json.token }}", + "useJson": true, "options": {} }, - "id": "d07b9335-29a0-41bc-a6c4-0232d94a0559", - "name": "JWT1", + "id": "c24f27d7-48fc-47c3-864d-f05456abe7c2", + "name": "Sign with JSON Payload", "type": "n8n-nodes-base.jwt", "typeVersion": 1, "position": [ - 1260, - 220 + 120, + 840 ], "credentials": { "jwtAuth": { - "id": "AosB7WdhmVA3be8t", - "name": "JWT Auth test" + "id": "kDnfvqrCBJvtlX3o", + "name": "JWT Auth account" } } }, @@ -68,38 +67,18 @@ "ignoreNotBefore": true } }, - "id": "b6228805-f0c1-479d-bbec-cefcde7298e3", - "name": "JWT2", + "id": "ff74f160-8f43-4cd1-a089-4698713ea12d", + "name": "Verify1", "type": "n8n-nodes-base.jwt", "typeVersion": 1, "position": [ - 1280, - 440 + 380, + 480 ], "credentials": { "jwtAuth": { - "id": "AosB7WdhmVA3be8t", - "name": "JWT Auth test" - } - } - }, - { - "parameters": { - "useJson": true, - "options": {} - }, - "id": "56ede43f-6771-4341-8c17-ba4b9185711a", - "name": "JWT3", - "type": "n8n-nodes-base.jwt", - "typeVersion": 1, - "position": [ - 1000, - 640 - ], - "credentials": { - "jwtAuth": { - "id": "G45TOKX5kBEraTr1", - "name": "JWT Auth test PEM" + "id": "kDnfvqrCBJvtlX3o", + "name": "JWT Auth account" } } }, @@ -109,18 +88,39 @@ "token": "={{ $json.token }}", "options": {} }, - "id": "1b57af10-710f-4b86-9020-e1fc43a222cd", - "name": "JWT4", + "id": "9fcb58bd-f28b-4106-a3ab-ad2a64b6b0f5", + "name": "Decode2", "type": "n8n-nodes-base.jwt", "typeVersion": 1, "position": [ - 1280, - 640 + 380, + 740 ], "credentials": { "jwtAuth": { - "id": "G45TOKX5kBEraTr1", - "name": "JWT Auth test PEM" + "id": "kDnfvqrCBJvtlX3o", + "name": "JWT Auth account" + } + } + }, + { + "parameters": { + "operation": "decode", + "token": "={{ $json.token }}", + "options": {} + }, + "id": "913e5542-12a0-4a48-9646-4fba648ec95b", + "name": "Decode1", + "type": "n8n-nodes-base.jwt", + "typeVersion": 1, + "position": [ + 380, + 300 + ], + "credentials": { + "jwtAuth": { + "id": "kDnfvqrCBJvtlX3o", + "name": "JWT Auth account" } } }, @@ -130,18 +130,45 @@ "token": "={{ $json.token }}", "options": {} }, - "id": "9a658330-ecc3-4007-9524-534ad15a3a40", - "name": "JWT5", + "id": "c888549a-b1fb-47e8-bf90-07cec2b32483", + "name": "Verify2", "type": "n8n-nodes-base.jwt", "typeVersion": 1, "position": [ - 1280, - 860 + 380, + 920 ], "credentials": { "jwtAuth": { - "id": "G45TOKX5kBEraTr1", - "name": "JWT Auth test PEM" + "id": "kDnfvqrCBJvtlX3o", + "name": "JWT Auth account" + } + } + }, + { + "parameters": { + "claims": { + "audience": "test", + "issuer": "test", + "jwtid": "123", + "subject": "test" + }, + "options": { + "kid": "custom-kid" + } + }, + "id": "3aedaf15-026d-4874-99c1-ab5940f18c73", + "name": "Sign with kid", + "type": "n8n-nodes-base.jwt", + "typeVersion": 1, + "position": [ + 120, + 1280 + ], + "credentials": { + "jwtAuth": { + "id": "kDnfvqrCBJvtlX3o", + "name": "JWT Auth account" } } }, @@ -165,13 +192,13 @@ }, "options": {} }, - "id": "51a6c4b9-ebae-4ffa-a870-9915c3304cd5", - "name": "Edit Fields", + "id": "9d8471ca-b918-4450-b2e3-735799399d39", + "name": "Decode1 Output", "type": "n8n-nodes-base.set", "typeVersion": 3.3, "position": [ - 1500, - 220 + 580, + 300 ] }, { @@ -194,42 +221,13 @@ }, "options": {} }, - "id": "9e97ea34-ec32-4935-b116-e40815567e1c", - "name": "Edit Fields1", + "id": "dd0aa97d-a485-4cc3-a8af-55e73fb21716", + "name": "Verify1 Output", "type": "n8n-nodes-base.set", "typeVersion": 3.3, "position": [ - 1520, - 440 - ] - }, - { - "parameters": { - "assignments": { - "assignments": [ - { - "id": "46ed5c03-d41a-4387-988e-2ed3821f32d4", - "name": "payload.my_field_1", - "value": "={{ $json.payload.my_field_1 }}", - "type": "string" - }, - { - "id": "0007786e-3f93-4146-8e10-32ab8e088b81", - "name": "payload.my_field_2", - "value": "={{ $json.payload.my_field_2 }}", - "type": "string" - } - ] - }, - "options": {} - }, - "id": "f205e447-2a98-48ef-bba5-12e9aecab90e", - "name": "Edit Fields2", - "type": "n8n-nodes-base.set", - "typeVersion": 3.3, - "position": [ - 1520, - 860 + 580, + 480 ] }, { @@ -252,18 +250,163 @@ }, "options": {} }, - "id": "0788f03e-0c1c-4e21-a408-9441930cd82f", - "name": "Edit Fields3", + "id": "f47b9996-ce95-4b72-a9ae-5e5a616ff982", + "name": "Decode2 Output", "type": "n8n-nodes-base.set", "typeVersion": 3.3, "position": [ - 1520, - 640 + 580, + 740 + ] + }, + { + "parameters": { + "assignments": { + "assignments": [ + { + "id": "46ed5c03-d41a-4387-988e-2ed3821f32d4", + "name": "payload.my_field_1", + "value": "={{ $json.payload.my_field_1 }}", + "type": "string" + }, + { + "id": "0007786e-3f93-4146-8e10-32ab8e088b81", + "name": "payload.my_field_2", + "value": "={{ $json.payload.my_field_2 }}", + "type": "string" + } + ] + }, + "options": {} + }, + "id": "5ba29142-407f-4e39-a3ed-28dff742070a", + "name": "Verify2 Output", + "type": "n8n-nodes-base.set", + "typeVersion": 3.3, + "position": [ + 580, + 920 + ] + }, + { + "parameters": { + "operation": "decode", + "token": "={{ $json.token }}", + "options": { + "complete": true + } + }, + "id": "ab038c41-45eb-4679-a71d-fc3c60797983", + "name": "Decode3", + "type": "n8n-nodes-base.jwt", + "typeVersion": 1, + "position": [ + 380, + 1180 + ], + "credentials": { + "jwtAuth": { + "id": "kDnfvqrCBJvtlX3o", + "name": "JWT Auth account" + } + } + }, + { + "parameters": { + "operation": "verify", + "token": "={{ $json.token }}", + "options": { + "complete": true + } + }, + "id": "3442124e-af80-4cb0-bae0-4716f5a367af", + "name": "Verify3", + "type": "n8n-nodes-base.jwt", + "typeVersion": 1, + "position": [ + 380, + 1360 + ], + "credentials": { + "jwtAuth": { + "id": "kDnfvqrCBJvtlX3o", + "name": "JWT Auth account" + } + } + }, + { + "parameters": { + "assignments": { + "assignments": [ + { + "id": "1289f607-d46f-45f5-953a-1492f3b50bbd", + "name": "payload.audience", + "value": "={{ $json.payload.audience }}", + "type": "string" + }, + { + "id": "e32ae71b-62ca-45e5-8351-2fd9ab7451ef", + "name": "payload.jwtid", + "value": "={{ $json.payload.jwtid }}", + "type": "string" + }, + { + "id": "99695f75-e483-4e12-8316-b669f73a7dfe", + "name": "header.kid", + "value": "={{ $json.header.kid }}", + "type": "string" + } + ] + }, + "options": {} + }, + "id": "28786e3b-9f7b-42e1-b5d2-b5484870b51a", + "name": "Decode3 Output", + "type": "n8n-nodes-base.set", + "typeVersion": 3.3, + "position": [ + 580, + 1180 + ] + }, + { + "parameters": { + "assignments": { + "assignments": [ + { + "id": "3ff845d5-9c2c-4744-bc33-a7318b4741fc", + "name": "payload.audience", + "value": "={{ $json.payload.audience }}", + "type": "string" + }, + { + "id": "d1206579-634e-472a-9190-a176cf2477a1", + "name": "payload.jwtid", + "value": "={{ $json.payload.jwtid }}", + "type": "string" + }, + { + "id": "1d39fe9e-d513-4bcf-8f2e-3bce3b45e37b", + "name": "header.kid", + "value": "={{ $json.header.kid }}", + "type": "string" + } + ] + }, + "options": {} + }, + "id": "3a4dbfb1-4d3c-479c-a848-a8c3e148b4ab", + "name": "Verify3 Output", + "type": "n8n-nodes-base.set", + "typeVersion": 3.3, + "position": [ + 580, + 1360 ] } ], "pinData": { - "Edit Fields": [ + "Decode1 Output": [ { "json": { "payload": { @@ -273,7 +416,7 @@ } } ], - "Edit Fields1": [ + "Verify1 Output": [ { "json": { "payload": { @@ -283,7 +426,7 @@ } } ], - "Edit Fields3": [ + "Decode2 Output": [ { "json": { "payload": { @@ -293,7 +436,7 @@ } } ], - "Edit Fields2": [ + "Verify2 Output": [ { "json": { "payload": { @@ -302,6 +445,32 @@ } } } + ], + "Decode3 Output": [ + { + "json": { + "payload": { + "audience": "test", + "jwtid": "123" + }, + "header": { + "kid": "custom-kid" + } + } + } + ], + "Verify3 Output": [ + { + "json": { + "payload": { + "audience": "test", + "jwtid": "123" + }, + "header": { + "kid": "custom-kid" + } + } + } ] }, "connections": { @@ -309,88 +478,131 @@ "main": [ [ { - "node": "JWT", + "node": "Sign with claims", "type": "main", "index": 0 }, { - "node": "JWT3", - "type": "main", - "index": 0 - } - ] - ] - }, - "JWT": { - "main": [ - [ - { - "node": "JWT1", + "node": "Sign with JSON Payload", "type": "main", "index": 0 }, { - "node": "JWT2", + "node": "Sign with kid", "type": "main", "index": 0 } ] ] }, - "JWT3": { + "Sign with claims": { "main": [ [ { - "node": "JWT4", + "node": "Decode1", "type": "main", "index": 0 }, { - "node": "JWT5", + "node": "Verify1", "type": "main", "index": 0 } ] ] }, - "JWT1": { + "Sign with JSON Payload": { "main": [ [ { - "node": "Edit Fields", + "node": "Decode2", + "type": "main", + "index": 0 + }, + { + "node": "Verify2", "type": "main", "index": 0 } ] ] }, - "JWT2": { + "Verify1": { "main": [ [ { - "node": "Edit Fields1", + "node": "Verify1 Output", "type": "main", "index": 0 } ] ] }, - "JWT4": { + "Decode2": { "main": [ [ { - "node": "Edit Fields3", + "node": "Decode2 Output", "type": "main", "index": 0 } ] ] }, - "JWT5": { + "Decode1": { "main": [ [ { - "node": "Edit Fields2", + "node": "Decode1 Output", + "type": "main", + "index": 0 + } + ] + ] + }, + "Verify2": { + "main": [ + [ + { + "node": "Verify2 Output", + "type": "main", + "index": 0 + } + ] + ] + }, + "Sign with kid": { + "main": [ + [ + { + "node": "Decode3", + "type": "main", + "index": 0 + }, + { + "node": "Verify3", + "type": "main", + "index": 0 + } + ] + ] + }, + "Decode3": { + "main": [ + [ + { + "node": "Decode3 Output", + "type": "main", + "index": 0 + } + ] + ] + }, + "Verify3": { + "main": [ + [ + { + "node": "Verify3 Output", "type": "main", "index": 0 } @@ -398,15 +610,7 @@ ] } }, - "active": false, "settings": { "executionOrder": "v1" - }, - "versionId": "f70ffef1-3c5d-4991-a3aa-b4141b93e4cb", - "meta": { - "templateCredsSetupCompleted": true, - "instanceId": "be251a83c052a9862eeac953816fbb1464f89dfbf79d7ac490a8e336a8cc8bfd" - }, - "id": "H0sZEXDuE7VIP5vz", - "tags": [] + } }