Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JWT signature url and sub are mismatching #38

Open
dejoma opened this issue Dec 6, 2024 · 0 comments
Open

JWT signature url and sub are mismatching #38

dejoma opened this issue Dec 6, 2024 · 0 comments

Comments

@dejoma
Copy link

dejoma commented Dec 6, 2024

Setup overview

image

Steps:

  1. Trigger background job in NextJS with the following code:
const WEBSCRAPER_URL = "https://backend.my-domain.com/webscraper";

const result = await startBackgroundJob(
      'myJobName',
      { ...payload },
      { urlOverride: WEBSCRAPER_URL }
);

// The above function summarized:
const startBackgroundJob = async (jobKey, payload, options) => {
  const url = options.urlOverride ?? `my-domain.com/api/jobs?jobkey=${jobKey}`
  const request = {
      url,
      body: payload,
      delay: options?.delay,
      contentBasedDeduplication: true
  };
  await queue.enqueueJSON(request);
}

// Full version of that same function
const startBackgroundJob = async (
  jobName: JobKey,
  payload: JobPayload,
  options?: {
    delay?: number;
    queueName?: string;
    urlOverride?: string;
  }
): Promise<JobResult> => {
  noStore(); // import { unstable_noStore as noStore } from 'next/cache';

  try {
    const url =
      options?.urlOverride ??
      new URL(
        `/api/jobs?job=${jobName}`,
        process.env.NODE_ENV === 'production'
          ? process.env.NEXT_PUBLIC_HOST_URL
          : process.env.TUNNEL_URL
      ).toString();

    const request = {
      url,
      body: payload,
      delay: options?.delay,
      contentBasedDeduplication: true
    };

    let qstashMessageId: string;
    if (options?.queueName) {
      const queue = jobClient.queue({
        queueName: options.queueName
      });

      const { messageId } = await queue.enqueueJSON(request);
      qstashMessageId = messageId;
    } else {
      // import { Client as JobClient } from '@upstash/qstash';
      const { messageId } = await jobClient.publishJSON(request);
      qstashMessageId = messageId;
    }

    return {
      success: true,
      message: `Messsage ID from QStash: ${qstashMessageId}`
    };
  } catch (error) {
    console.error(`Error starting job '${jobName}': ${error}`);
    return {
      success: false,
      error: `Error starting job '${jobName}': ${error}`
    };
  }
};

In the logs of that function I see the following:

iss: Upstash, sub: https://backend.my-domain.com/webscraper, url: https://backend.my-domain.com

So I invoked with domain.com/path, but somehow the URL that I have in the event in AWS Lambda is not the same:

# From the docs  https://upstash.com/docs/qstash/quickstarts/aws-lambda/python
url = 'https://{}'.format(event['requestContext']['domainName'])
decoded = jwt.decode(jwt_token, options={"verify_signature": False})
sub = decoded['sub']
if sub != url:
        raise Exception("Invalid subject: {}".format(sub))

Also when you just get a regular URL, so without a path, you will get a mismatch because one of the two has a trailing backslash. So with and without a path it won't work, the intended verify method that you have posted in the docs is my suspicion.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant