'Nodemailer 3LO OAuth give GaxiosError: unauthorized_client

In emailTransporter.js my code like below.

const nodemailer = require('nodemailer');
const { google } = require("googleapis");
const path = require('path');
const OAuth2 = google.auth.OAuth2;

require('dotenv').config({path: path.join(__dirname, '.env')});

const oauth2Client = new OAuth2(
    process.env.CLIENT_ID, // ClientID
    process.env.CLIENT_SECRET, // Client Secret
    "https://developers.google.com/oauthplayground" // Redirect URL
);

oauth2Client.setCredentials({
    refresh_token: process.env.REFRESH_TOKEN
});
const accessToken = oauth2Client.getAccessToken();

let transporter = nodemailer.createTransport({
    host: 'smtp.gmail.com',
    port: 465,
    secure: true,
    auth: {
        type: "OAuth2",
        user: process.env.USER_EMAIL, 
        clientId: process.env.CLIENT_ID,
        clientSecret: process.env.CLIENT_SECRET,
        refreshToken: process.env.REFRESH_TOKEN,
        accessToken: accessToken
    },
    tls: {
        rejectUnauthorized: false
    }
});

module.exports = transporter;

In auth.js I use emailTransporter exports from emailTransporter.js to send some email options. But node give me error like this:

D:\nodejs\node_modules\gaxios\build\src\gaxios.js:129 throw new common_1.GaxiosError(Request failed with status code ${translatedResponse.status}, opts, translatedResponse); ^

GaxiosError: unauthorized_client at Gaxios._request (D:\nodejs\node_modules\gaxios\build\src\gaxios.js:129:23) at processTicksAndRejections (node:internal/process/task_queues:96:5) at async OAuth2Client.refreshTokenNoCache (D:\nodejs\node_modules\google-auth-library\build\src\auth\oauth2client.js:174:21) at async OAuth2Client.refreshAccessTokenAsync (D:\nodejs\node_modules\google-auth-library\build\src\auth\oauth2client.js:198:19) at async OAuth2Client.getAccessTokenAsync (D:\nodejs\node_modules\google-auth-library\build\src\auth\oauth2client.js:227:23) { response: { config: { method: 'POST', url: 'https://oauth2.googleapis.com/token', data: 'refresh_token=1%2F%2F04PvTQnD4_86nCgYIARAAGAQSNwF-L9IrTdRMaV9mdIMhyEhFeJeKGSvqYnbgkCw-18aF7ZFmRgpWoWiQM3EXozwMiXzvfYwmAwc&client_id=543495663437-d59lg6u1a77o9a2uinf83idb0md991l9.apps.googleusercontent.com&client_secret=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&grant_type=refresh_token', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'google-api-nodejs-client/7.11.0', 'x-goog-api-client': 'gl-node/16.13.2 auth/7.11.0', Accept: 'application/json' }, paramsSerializer: [Function: paramsSerializer], body: 'refresh_token=1%2F%2F04PvTQnD4_86nCgYIARAAGAQSNwF-L9IrTdRMaV9mdIMhyEhFeJeKGSvqYnbgkCw-18aF7ZFmRgpWoWiQM3EXozwMiXzvfYwmAwc&client_id=543495663437-d59lg6u1a77o9a2uinf83idb0md991l9.apps.googleusercontent.com&client_secret=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&grant_type=refresh_token', validateStatus: [Function: validateStatus], responseType: 'json' }, data: { error: 'unauthorized_client', error_description: 'Unauthorized' }, headers: { 'alt-svc': 'h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"', 'cache-control': 'no-cache, no-store, max-age=0, must-revalidate', connection: 'close', 'content-encoding': 'gzip', 'content-type': 'application/json; charset=utf-8', date: 'Wed, 19 Jan 2022 03:47:31 GMT', expires: 'Mon, 01 Jan 1990 00:00:00 GMT', pragma: 'no-cache', server: 'scaffolding on HTTPServer2', 'transfer-encoding': 'chunked', vary: 'Origin, X-Origin, Referer', 'x-content-type-options': 'nosniff', 'x-frame-options': 'SAMEORIGIN', 'x-xss-protection': '0' }, status: 401, statusText: 'Unauthorized', request: { responseURL: 'https://oauth2.googleapis.com/token' } }, config: { method: 'POST', url: 'https://oauth2.googleapis.com/token', data: 'refresh_token=1%2F%2F04PvTQnD4_86nCgYIARAAGAQSNwF-L9IrTdRMaV9mdIMhyEhFeJeKGSvqYnbgkCw-18aF7ZFmRgpWoWiQM3EXozwMiXzvfYwmAwc&client_id=543495663437-d59lg6u1a77o9a2uinf83idb0md991l9.apps.googleusercontent.com&client_secret=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&grant_type=refresh_token', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'User-Agent': 'google-api-nodejs-client/7.11.0', 'x-goog-api-client': 'gl-node/16.13.2 auth/7.11.0', Accept: 'application/json' }, paramsSerializer: [Function: paramsSerializer], body: 'refresh_token=1%2F%2F04PvTQnD4_86nCgYIARAAGAQSNwF-L9IrTdRMaV9mdIMhyEhFeJeKGSvqYnbgkCw-18aF7ZFmRgpWoWiQM3EXozwMiXzvfYwmAwc&client_id=543495663437-d59lg6u1a77o9a2uinf83idb0md991l9.apps.googleusercontent.com&client_secret=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&grant_type=refresh_token', validateStatus: [Function: validateStatus], responseType: 'json' }, code: '401' }



Solution 1:[1]

In https://developers.google.com/oauthplayground/, I have to choose option Use your own credentials at top right side. Fill in the cliendId and clientSecret and it already worked.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Hung Vo