aws4-axios icon indicating copy to clipboard operation
aws4-axios copied to clipboard

Calling a Lambda Function URL secured through IAM_AUTH always returns HTTP 403 Forbidden

Open Janosch opened this issue 7 months ago • 0 comments

I have an AWS Lambda function which I would like to call via a function URL IAM_AUTH. I am struggling to make the request work with aws4-axios. What does work is:

  • A request to a Lambda function URL with authentication NONE
  • A request to a Lambda function URL with authentication IAM_AUTH, using long-term AWS credentials

However, If I use temporary security credentials with IAM_AUTH, I get HTTP 403 and the message The security token included in the request is invalid.

This is how I create the interceptor:

const configureLambdaCredentials = async () => {
        const {credentials} = await fetchAuthSession()
        if (credentials !== undefined) {
            const interceptor = aws4Interceptor({
                options: {
                    region: 'us-east-1',
                    service: 'lambda'
                },
                credentials: {
                    accessKeyId: credentials.accessKeyId,
                    secretAccessKey: credentials.secretAccessKey,
                    sessionToken: credentials.sessionToken
                }
            })
            axios.interceptors.request.use(interceptor)
        }
    }

And this is how I make the request:

const options = {
      method: 'POST',
      url: `${import.meta.env.VITE_API_URL}/prompt`,
      headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json;charset=UTF-8'
      },
      data: {
          message: prompt,
      }
  };
  const response = await axios(options);
}

At first I thought I am doing something wrong, maybe some sort of misconfiguration. But when I use aws4fetch instead of aws4-axios, it works. This is the code:

async function prompt(userMessage: string, currentMessages: Message[]): Promise<void> {
        const session = await fetchAuthSession();
        const credentials = session?.credentials;

        if (!credentials) {
            throw new Error("Credentials not available");
        }

        const aws = new AwsClient({
            accessKeyId: credentials.accessKeyId,
            secretAccessKey: credentials.secretAccessKey,
            sessionToken: credentials.sessionToken,
            service: "lambda",
            region: "us-east-1"
        })

        const payload = {message: userMessage}
        const timeStart = performance.now();
        const response = await aws.fetch(`${import.meta.env.VITE_API_URL}/prompt`, {
            headers: {'Content-Type': 'application/json'},
            method: 'POST',
            body: JSON.stringify(payload)
        })
}

Attached are the request using aws4-axios that does not work and the request with aws4fetch that does work.

I noticed that aws4-axios signs the headers accept, content-length and content-type which aws4fetch does not sign. But I have no idea if this is the cause of the error.

request-aws4-axios.txt request-aws4fetch.txt

Janosch avatar Jul 07 '24 13:07 Janosch