Worker script exceeded time limit when verify jwt

I try to implement jwt verify on worker and get script exceeded time limit

import jwt from 'jsonwebtoken';

const handleRequest = async () => {
  console.log('verifying...')
  const foo = await jwt.verify(
    `eyJhbGciOiJSUzI1NiIsImtpZCI6ImEyYjkxODJiMWI0NmNiN2ZjN2MzMTFlZTgwMjFhZDY1MmVlMjc2MjIiLCJ0eXAiOiJKV1QifQ.eyJuYW1lIjoiVG9kc2Fwb3JuIEJhbmplcmRraXQiLCJwaWN0dXJlIjoiaHR0cHM6Ly9saDMuZ29vZ2xldXNlcmNvbnRlbnQuY29tL2EtL0FPaDE0R2o0bk9BYWJtQ0wxbU9IWGU1WGFtVFRnWEhEa1B3TEhXVWtrbGMwM0E9czk2LWMiLCJhZG1pbiI6dHJ1ZSwiaXNzIjoiaHR0cHM6Ly9zZWN1cmV0b2tlbi5nb29nbGUuY29tL2ZveGZveC1sZWFybiIsImF1ZCI6ImZveGZveC1sZWFybiIsImF1dGhfdGltZSI6MTYxMTQ4NDQ4MiwidXNlcl9pZCI6InJrT0JaRk1YSmxlV3lyVGZBMzJxVUdRa3JCQTMiLCJzdWIiOiJya09CWkZNWEpsZVd5clRmQTMycVVHUWtyQkEzIiwiaWF0IjoxNjExNTA5MjgyLCJleHAiOjE2MTE1MTI4ODIsImVtYWlsIjoia2F0b3B6QGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJmaXJlYmFzZSI6eyJpZGVudGl0aWVzIjp7Imdvb2dsZS5jb20iOlsiMTExOTk4MjIyNjU0NTIxNjgyOTExIl0sImVtYWlsIjpbImthdG9wekBnbWFpbC5jb20iXX0sInNpZ25faW5fcHJvdmlkZXIiOiJnb29nbGUuY29tIn19.kv0Dl9mSVzuPx-lbG9tqEaT6hKm3fkza4-fHNXvo2tNReEXNIFmpJ2iXgCBUeby4OFrwwmGrxEA_z0RcVfqqi8Oj2fVFsss5fWkctzOcTDjFDSQYEjUb_Pk_CSf08GRdVfZP2V1H3hCFpHktLIewjTQDd-dmqWAVaaqJqanagOMkzKk_qpn9klLgJwu7sDQgePZTLQGGWgmZ4tXT3LZH2Aq8Q09lvsVDcrYMQuRkl0lKtpwIHcGiw4dLaPbZuz5x8yiUNbZ0mvfEb7qD386Q4Jvm1ueqQeTEmHNTjWo3Nh9b9aKD0VoLAt7cA6p3oAZA-BTJf0VUJ-Ssrf8PgkNhcg`,
    `-----BEGIN CERTIFICATE-----\nMIIDHDCCAgSgAwIBAgIIMxXZH+DC+3YwDQYJKoZIhvcNAQEFBQAwMTEvMC0GA1UE\nAxMmc2VjdXJldG9rZW4uc3lzdGVtLmdzZXJ2aWNlYWNjb3VudC5jb20wHhcNMjEw\nMTE2MDkyMDEzWhcNMjEwMjAxMjEzNTEzWjAxMS8wLQYDVQQDEyZzZWN1cmV0b2tl\nbi5zeXN0ZW0uZ3NlcnZpY2VhY2NvdW50LmNvbTCCASIwDQYJKoZIhvcNAQEBBQAD\nggEPADCCAQoCggEBAM7lNNMbuBwxNa/sPTPCmbkGVGsKsbHUCCf/Iu6LmasUcPNe\n+eZ70II1lRmIldKJB/2Mcc9lY4wqWYXkoKFOfFJeSck5ZQNOc4h9lBAK4NUuxKtz\nkxxK1FQ9fzOL9Q9mVvc2UGCsACFTTJgKkEx0gCBKSQOUJaNRO7MODl6FrZxpPRQ0\nkM2bepFKfTXdDow90cchsDyz1Jvdt0USsguoh2snGvOtK73FVHHcnrdUDJ+eP52u\nh1It4SZOSFwNkWcbdE4dxbFRjPkt0TmjnHD42Canu2263NlssSE3g9FtQNjLqrlQ\nKzMsrN1onTRzpbQJ7oNrz+DChbAb54uy2Ic7zhUCAwEAAaM4MDYwDAYDVR0TAQH/\nBAIwADAOBgNVHQ8BAf8EBAMCB4AwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwIwDQYJ\nKoZIhvcNAQEFBQADggEBACx632r/drfl4m3C56HhBtpN6Lpvwf9IlI6O0974TIhL\nit4Q5B5by7x8inCXTOhmB6anOwaB26YyEjG3I2HjcpIxFp/UJKT/u824yqAyLOHV\n3DfiW6KVNcfZF+48K8B+yqLRRkAwSWpNkoC/8wrkyW+AAnQwUed9vU0p0jbKvtpt\nU/8/ZMf6rnwtOHkPa4QJ6mHxrRSlBmXkYuCCi5RHzXOh1qHCeCxFzW+hf5jGRBEI\ncNzsYKovovNnmpHTlqjHqotBv4jgnyWWUirM5W1LojlI1ibeGya6bUTqpgo/BY29\nBsABttwbeN5aJRu020cJD/Egx5Um507Dp06ClowtvJE=\n-----END CERTIFICATE-----\n`,
    { algorithms: ['RS256'] });

  console.log('foo:', foo)

  return new Response("OK", {
    status: 200,
  })
}

addEventListener('fetch', (event) => {
  event.respondWith(handleRequest())
})

And here’s console log

verifying...
script exceeded time limit
Uncaught (in response) Error: internal error

If I understand correctly, this code reach 10ms limit (it took ~56ms to execute this locally on mbp) so the question is any workaround to accomplish this or maybe this is not possible to do this on worker?

I think paid plan allows 50ms of CPU time, but yeah - still lower than your requirement, which is 56ms.

I’m able to verify JWTs using the native web crypto APIs. Here’s the library: https://www.npmjs.com/package/@cfworker/jwt

You might be able to use it directly but in any case the source code should provide some ideas.

4 Likes

For any encryption related work, you should only use the native Web Crypto APIs.

JS-only encryption will consume the CPU-time, maybe not on a few requests, but at load it will accumulate.

You can see which protocols Cloudflare Supports here:

1 Like

Thanks! This pretty close, I can now decode but not able to verify, in my case I have to use the keys from https://www.googleapis.com/robot/v1/metadata/x509/[email protected]

but it seem like @cfworker/jwt that use /.well-known/jwks.json which google doesn’t provided.

So I assume that I have to convert pem to jwk somehow, And now I stuck here (provided answer there didn’t work because it use private key) :point_right: https://stackoverflow.com/questions/65261515/x509-public-key-to-jwk-in-web-workers-environment

Any hint is welcome I’m pretty stuck here :see_no_evil:

PEM to JWK:

There’s a isValidJwt function on this blog post you can use to validate JWT if you don’t want to use a library.

Thanks, anyway this example use RSA but google use x.509 which I can’t find how to use it with native crypto.subtle.importKey.

I will take a look, Thanks

Finally made it!

Here’s my result without optimize on mbp

decodeJwt: 0.7978515625 ms
decode: 0.1240234375 ms
import: 11.0859375 ms
exportKey: 1.425048828125 ms
importKey: 1.60595703125 ms
verifyJwtSignature: 15.384033203125 ms

sum: 32.32470703125 ms

Anyway the code itself seem to be all native function already.
Maybe it can optimize (or cached hash on k/v) somehow.

Thanks! :+1:

1 Like

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.