Give JWK independent value semantics for thread-safe copies

This commit is contained in:
jdb committed 2026-09-29 08:26:50 -05:00
1 parent 47393ec84f
commit d037c84e8c
8 files changed
+220 -9

No files matched your search

+47
View File
@@ -0,0 +1,47 @@
when compileOption("threads"):
import std/[json, options, tables, unittest]
import jwt_full
type
KeyCache = Table[string, JwkSet]
WorkerInput = tuple[keys: KeyCache, passed: ptr bool]
proc useKeys(input: WorkerInput) {.thread.} =
var keys = input.keys
try:
for i in 0 ..< 50:
let key = keys["issuer"][0]
let metadata = key["metadata"].get
metadata["labels"][0].str = "worker"
var material = key.octKey
material.k[0] = '!'
# Both metadata and parsed key material remain intact after modifying
# accessor results. Each worker also signs and verifies with its copy.
if key["metadata"].get["labels"][0].getStr != "original": return
if key.octKey.k[0] == '!': return
let token = sign(payload = "payload",
header = initJoseHeader(%*{"alg": "HS256"}), key = key)
token.validate(HS256, key)
keys["issuer"].setLen(0)
input.passed[] = true
except CatchableError:
input.passed[] = false
suite "jwt_full/jwk thread isolation":
test "workers copy key caches and use their keys independently":
let node = %*{
"kty": "oct", "alg": "HS256", "kid": "original",
"k": "MDEyMzQ1Njc4OWFiY2RlZjAxMjM0NTY3ODlhYmNkZWY",
"metadata": {"labels": ["original"]}}
let original = {"issuer": @[initJwk(node)]}.toTable
var workers: array[4, Thread[WorkerInput]]
var passed: array[4, bool]
for i in 0 ..< workers.len:
createThread(workers[i], useKeys, (original, addr passed[i]))
joinThreads(workers)
check passed == [true, true, true, true]
check original["issuer"].len == 1
check original["issuer"][0]["metadata"].get == node["metadata"]
check original["issuer"][0].octKey.k == node["k"].getStr