-1

I have a SPA with NextJs that submits a contact form to Google sheet, which works perfectly fine locally and give me a 500 error in production. on my .env file I have as following:

NEXT_PUBLIC_GOOGLE_CLIENT_EMAIL=
NEXT_PUBLIC_GOOGLE_PRIVATE_KEY=
NEXT_PUBLIC_GOOGLE_SHEET_ID=

I do have the actual secret on my .env.local file,

and here is my submit.js file

import { google } from 'googleapis'
require('dotenv-flow').config()

export default async function handler(req, res) {
  if (req.method !== 'POST') {
    return res.status(405).send('Only POST requests are allowed!')
  }
// log to see the secret which are visible in local  
  console.log('process.env', process.env)
 console.log(
      'email process with error ',
      process.env.NEXT_PUBLIC_GOOGLE_CLIENT_EMAIL
    )
  const body = req.body

  try {
    const auth = new google.auth.GoogleAuth({
      credentials: {
        client_email: process.env.NEXT_PUBLIC_GOOGLE_CLIENT_EMAIL,
        private_key: process.env.NEXT_PUBLIC_GOOGLE_PRIVATE_KEY?.replace(
          /\\n/g,
          '\n'
        ),
      },
      scopes: [
        'https://www.googleapis.com/auth/drive',
        'https://www.googleapis.com/auth/drive.file',
        'https://www.googleapis.com/auth/spreadsheets',
      ],
    })
    const sheets = google.sheets({
      auth,
      version: 'v4',
    })

    const submittedAt = new Date().toUTCString()

    const response = await sheets.spreadsheets.values.append({
      spreadsheetId: process.env.NEXT_PUBLIC_GOOGLE_SHEET_ID,
      range: 'A1:F1',
      valueInputOption: 'USER_ENTERED',
      requestBody: {
        values: [
          [
            body.name,
            body.company,
            body.product,
            body.email,
            body.phone,
            submittedAt,
          ],
        ],
      },
    })

   
    return res.status(201).json({
      data: response.data,
    })
  } catch (error) {
    console.log(
      'email process with error ',
      process.env.NEXT_PUBLIC_GOOGLE_CLIENT_EMAIL
    )
// the log fo r this error is down below
    console.log('error.code', error)
    return res.status(error.code).send({ message: error.message })
  }
}

error.code Error: The incoming JSON object does not contain a client_email field error.code Error: The incoming JSON object does not contain a client_email field

Ps, the secrets are injected with aws and are visible in the cloud watch log.

question1, Do I need to have these secrets in my Dockerfile?
question2, can it be CSP related? ( which hasn't been implemented)

** Update I tried setting the key in dockerfile which didn't work also tried to add csp with class component to _document.js/ or by adding next config which didnt work as well

** update On the production/development environment, I can not read the values although its been injected from the vault

  • 1
    So what is the _actual_ error? The 500 status code is not meant to give any relevant info away. You either need to check the relevant log file to see what _caused_ the error, or do some more debugging inside of your own code (if that is the one that triggers the 500 error at the end there; although then you should already know what `error` contained?) – CBroe May 24 '23 at 10:59
  • I put the error in my question – peakyBlinders May 24 '23 at 12:50
  • And that is coming from where exactly? Is it the `new google.auth.GoogleAuth` call, or the `sheets.spreadsheets.values.append` call? – CBroe May 24 '23 at 13:22
  • its from the new google.auth.GoogleAuth call, when I log the email or the keys on handle submit, they are all undefined(empty) – peakyBlinders May 24 '23 at 14:55

1 Answers1

0

I found that the NEXT_PUBLIC_ should not be used here and after removing them it start working. but still another secret(GTM) which should use the prefix is not loading

Update and solution

So it turns out that I need to make a call to server.js and request for the env variables: the server.js is something like this :

export default function handler(req, res) {
  const publicEnv = Object.keys(process.env)
    .filter((key) => key.startsWith('NEXT_PUBLIC'))
    .reduce((acc, key) => {
      acc[key] = process.env[key]
      return acc
    }, {})

  res.status(200).json(publicEnv)
}