Looking to integrate my custom API into a custom GPT action with OAuth using Google authentication

"Hello everyone,

I’m looking to integrate my custom API into a custom GPT action with OAuth using Google authentication. I want to use Google login to obtain an access token, which will then serve as a middleware to access any route in my API. I’ve tried writing code using googleapis and passport, but I haven’t had success.

I’ve added the ChatGPT callback URL in Google redirect settings, and my custom API host domain matches with the auth and token URLs in ChatGPT. However, I’m unsure about the correct code to write for the auth URL and token URL routes.

Can anyone provide guidance or share a correct code example for setting up the auth URL and token URL routes to successfully authenticate with Google OAuth and obtain an access token?

Thank you in advance for your help!"

const express = require('express');
const bodyParser = require('body-parser')
var jsonParser = bodyParser.json()
const path = require('path');
const cors = require('cors'); // Import the CORS middleware
const { google } = require("googleapis");
const Cookies = require("js-cookie");
const cookieParser = require('cookie-parser');
const app = express();
const PORT = process.env.PORT || 3000;

const CLIENT_ID = process.env.CLIENT_ID;
const CLIENT_SECRET = process.env.CLIENT_SECRET;
const REDIRECT_URI = process.env.REDIRECT_URI;
const SCOPES = ["email", "profile"];

const authClient = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI);


// const corsOptions = {
//     origin: 'https://customer-data-platform-qdk5bgyaea-el.a.run.app',
//     optionsSuccessStatus: 200 // 
//   };

// app.use(cors(corsOptions));
app.use(bodyParser.json());
app.use(cookieParser()); // Add cookie parser middleware



const verifyTokenMiddleware = async (req, res, next) => {
    try {
        let idToken;
        if (req.headers.authorization) {
            idToken = req.headers.authorization.split(" ")[1];

            const ticket = await authClient.verifyIdToken({
                idToken: idToken,
                audience: CLIENT_ID,
            });
            const payload = ticket.getPayload();
            req.user = {
                userId: payload.sub,
                email: payload.email,
                name: payload.name,
            };
            next();
        } else {
            return res.status(401).json({ error: "No token found" });
        }
    } catch (error) {
        console.error('Error verifying token:', error);
        return res.status(401).json({ error: 'Unauthorized' });
    }
};


app.get("/login", (req, res) => {
    const { client_id, response_type, redirect_uri, state } = req.query;
    console.log(req.query);
    const CLIENT_ID = client_id;
    const REDIRECT_URI = redirect_uri;
    const authClient = new google.auth.OAuth2(CLIENT_ID, CLIENT_SECRET, REDIRECT_URI);

    // Use query parameters or default values
    const authUrl = authClient.generateAuthUrl({
        scope: SCOPES,
        client_id: client_id || CLIENT_ID,
        redirect_uri: redirect_uri || REDIRECT_URI,
        response_type: response_type || code,
        state: state || STATE,
    });

    res.redirect(authUrl);
});

app.get("/token", async (req, res) => {
    const code = req.query.code;
    console.log(req.query, req.body);
    const grantType = req.query.grant_type;
    const redirectUri = req.query.redirect_uri;
    const clientId = req.query.client_id;
    const clientSecret = req.query.client_secret;

    if (!code || !grantType || !redirectUri || !clientId || !clientSecret) {
        return res.status(400).send("Required parameters are missing");
    }

    try {
        // Verify the code and exchange it for tokens using client ID and secret
        const { tokens } = await authClient.getToken({
            code: code,
            clientId: clientId,
            clientSecret: clientSecret,
            redirectUri: redirectUri
        }); 
        console.log(tokens);
        const accessToken = tokens.access_token;
        const expiryDate = tokens.expiry_date;
        const idToken = tokens.id_token;

        const refreshToken = tokens.refresh_token;

        // Redirect to the back website with access token and refresh token
        // Set the content type of the response to JSON
        res.setHeader('Content-Type', 'application/json');

        res.status(200).json({
            idToken: idToken,
            access_token: accessToken,
            refresh_token: refreshToken,
            expiry_date: expiryDate
        });
    } catch (error) {
        console.error("Error processing Google OAuth callback:", error);
        res.status(500).send("Internal Server Error");
    }
});


app.get('/api/test', verifyTokenMiddleware, async (req, res) => {
    try {
        // Assume req.query.userKey is passed from the frontend
        const userKey = req.query.userKey;

        // Mock user data
        const users = {
            1: {
                "cdd": {
                    "src": [
                        {
                            "value": "API",
                            "labels": [],
                            "timestamp": "170797592000"
                        }
                    ]
                },
               
                    ]
                }
            }


        };

        // Check if the userKey exists in the users object
        if (users[userKey]) {
            res.send(users[userKey]);
        } else {
            res.status(404).json({ message: 'User not found' });
        }
    } catch (error) {
        console.error(error.message);
        res.status(500).json({ message: 'Server error' });
    }
});


app.get('/Unauthorized', (req, res) => {
    res.status(401).json({ error: 'Unauthorized' });
});
app.get("/success", (req, res) => {
    // Retrieve the idToken from the cookie
    const idToken = req.cookies.idToken;

    // Check if the idToken exists
    if (!idToken) {
        return res.status(401).send("No ID token found");
    }

    // Set the Authorization header with the idToken
    res.setHeader('Authorization', `Bearer ${idToken}`);

    // Send the response
    res.status(200).send({ idToken: idToken });
});
// Start the server
app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});

1 Like