0

I am implementing the Google OAuth 2.0 authorization code flow to fetch Gmail data. However, during the token exchange step on my backend, I consistently encounter the following error:

Error during Google OAuth callback: GaxiosError: invalid_grant
...
error_description: 'code_verifier or verifier is not needed.'**

What I am doing:

On the frontend (React Native), I use @react-native-google-signin/google-signin configured as follows:

GoogleSignin.configure({
  scopes: ['https://www.googleapis.com/auth/gmail.readonly', 'email', 'profile'],
  webClientId: '<MY_CLIENT_ID>', // Google Cloud Console web client ID
  offlineAccess: true,
  forceCodeForRefreshToken: true,
});

After user sign-in, I obtain the serverAuthCode and send it to my backend API to exchange for tokens.

On the backend (Node.js with the googleapis library), I call:

const { tokens } = await oauth2Client.getToken({
  code: receivedCode,
});

I do not use or generate any code_verifier anywhere in the flow.

The problem:

The error indicates that "code_verifier": "undefined" is included in the token request.
The error message states: 'code_verifier or verifier is not needed.'
My backend does not use PKCE or send any code_verifier.
My redirect URI in Google Cloud matches the URI used in both the frontend and backend.
Despite these checks, I still receive the invalid_grant error.

What I suspect:

  • The backend is inadvertently sending a code_verifier parameter with a value of undefined.
  • There may be a mismatch in the redirect URI or misuse of PKCE parameters.

What I tried:

  1. Verified that the redirect URI is identical in both the frontend and backend.
  2. Ensured no code_verifier parameter is explicitly added.
  3. Checked the OAuth credentials in Google Cloud Console.

Questions:

  1. Does Google expect a code_verifier only when using PKCE?
  2. How can I prevent code_verifier=undefined from being sent?
  3. How can I verify that the redirect URIs exactly match?
  4. What are the best practices for debugging invalid_grant errors in the OAuth 2.0 code flow?

2 Answers 2

0

Answers
1
. YES
2. Using the Node.js package, I could not find any built-in way, so I patched the package. Another way is to use Axios, etc (API call), see below.

Patch file PROJECT/node_modules/google-auth-library/build/src/auth/oauth2client.js line 184
REMOVE from values object

code_verifier: options.codeVerifier,

Then add

if (options.codeVerifier) {
  values.code_verifier = options.codeVerifier;
}

3. I use the request body to send the redirect URL to the server so multiple clients can send their own redirect URLs ( every redirect url used by any client needs to be whitelisted in the Google Console app)
4. Catch errors and read the message passed by Google.

    try{...} catch (err: any) {
        const status =
          (typeof err.code === 'string' && parseInt(err.code)) ||
          err.response?.status ||
          HttpStatus.BAD_GATEWAY;
        const message =
          err.response?.data?.error_description ||
          err.response?.data?.error ||
          err.message;
        console.log(status, message)
      }
Sign up to request clarification or add additional context in comments.

2 Comments

For the 2nd answer If I changed that locallly but how can I do in Production.
body: URLSearchParams { 'client_id' => '322573818287-ol6701o67oqcfosr2bh9cnq8vuscstpe.apps.googleusercontent.com', 'code_verifier' => 'undefined', 'code' => '4/0AUJR-x7qQhq9ktt4LnImKZW0KHijB5gBZzCRJhwqhXrGMTJC24OQZA12lSugGXfm0a4EdA', 'grant_type' => '<<REDACTED> - See errorRedactor option in gaxios for configuration>.', 'redirect_uri' => '04gctvwn-8000.inc1.devtunnels.ms/apis/auth/google/callback', 'client_secret' => '<<REDACTED> - See errorRedactor option in gaxios for configuration>.' }, still the code_verifier comming undefiend
0

I think this is a bug in 150.0.1 of the googleapis module in npm.

I rolled back to 149.0.0 and no longer have this issue.

I agree with your assessment, that undefined values are being serialized as strings, causing the backend to think it's PKCE.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.