Connecting to google APIs using Next.js OAuth 2.0
Unanswered
Orinoco Crocodile posted this in #help-forum
Orinoco CrocodileOP
So, I’ve never used OAuth before, so forgive me if some of the things I say sound dumb, but I’ll do my best.
I’m developing a website internally for my company that connects to two google APIs, the Drive API and Gmail API. The OAuth protocol has already been set up because I used a template file, so that was convenient, but now I’m having trouble getting the token generated (?) by the user logging in to connect to the Drive API and Gmail API. I specified the scopes in the […nextauth].js file, and I think I’ve set up everything correctly in my API route to connect to google’s APIs, now all that remains is actually getting the users token scoped for those APIs. I’m trying to retrieve the token within the API route, and I tried using getServerSession(), getToken(), and useSession(). The best luck I had was with getToken(), but I don’t think it returned the proper token scoped for the APIs.
I understand if this is a little confusing, but I’ll provide the necessary files
I’m developing a website internally for my company that connects to two google APIs, the Drive API and Gmail API. The OAuth protocol has already been set up because I used a template file, so that was convenient, but now I’m having trouble getting the token generated (?) by the user logging in to connect to the Drive API and Gmail API. I specified the scopes in the […nextauth].js file, and I think I’ve set up everything correctly in my API route to connect to google’s APIs, now all that remains is actually getting the users token scoped for those APIs. I’m trying to retrieve the token within the API route, and I tried using getServerSession(), getToken(), and useSession(). The best luck I had was with getToken(), but I don’t think it returned the proper token scoped for the APIs.
I understand if this is a little confusing, but I’ll provide the necessary files
6 Replies
Orinoco CrocodileOP
import { google } from 'googleapis';
import { getSession } from 'next-auth/client';
export default async (req, res) => {
try {
const session = await getSession({ req });
if (!session) {
return res.status(401).json({ error: 'Unauthorized' });
}
const accessToken = session?.user?.accessToken;
const refreshToken = session?.user?.refreshToken;
if (!accessToken || !refreshToken) {
return res.status(401).json({ error: 'Unauthorized' });
}
const { sheetId, sheetName } = req.query; // Extract sheetId and sheetName from the query parameters
if (!sheetId || !sheetName) {
return res.status(400).json({ error: 'Sheet ID and sheetName are required' });
}
const oauth2Client = new google.auth.OAuth2();
oauth2Client.setCredentials({
access_token: accessToken,
refresh_token: refreshToken,
});
if (oauth2Client.isTokenExpiring()) {
const { tokens } = await oauth2Client.refreshAccessToken();
const newAccessToken = tokens.access_token;
session.user.accessToken = newAccessToken;
}
const sheetsAPI = google.sheets({ version: 'v4', auth: oauth2Client });
// Fetch the spreadsheet metadata to get the list of sheets
const spreadsheetInfo = await sheetsAPI.spreadsheets.get({
spreadsheetId: sheetId,
});
// Check if the provided sheetName exists in the list of sheets
const sheetExists = spreadsheetInfo.data.sheets.some((sheet) => sheet.properties.title === sheetName);
if (!sheetExists) {
return res.status(404).json({ error: 'Sheet does not exist in the spreadsheet' });
}
const response = await sheetsAPI.spreadsheets.values.get({
spreadsheetId: sheetId,
range: `${sheetName}!A1:C10`, // Use the sheetName parameter in the range
});
res.status(200).json(response.data);
} catch (error) {
console.error('An error occurred:', error);
res.status(500).json({ error: 'Something went wrong' });
}
};The previous code is my route, and this is my Next Auth file
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
const GOOGLE_OAUTH_ID = process.env.GOOGLE_OAUTH_ID
const GOOGLE_OAUTH_SECRET = process.env.GOOGLE_OAUTH_SECRET
//Scopes provided only allow an authorized user to access files specified in code and only send emails on behalf of the user
export const authOptions = {
theme: {
colorScheme: 'light'
},
callbacks: {
async signIn({ account, profile, email, credentials }) {
if (account.provider === "google") {
return profile.email_verified && email.endsWith("@company.com")
}
return false
},
},
providers: [
GoogleProvider({
clientId: GOOGLE_OAUTH_ID,
clientSecret: GOOGLE_OAUTH_SECRET,
checks: 'none',
authorizationUrl: 'https://accounts.google.com/o/oauth2/v2/auth?hd=company.com',
authorization: {
params: {
scope: 'https://www.googleapis.com/auth/drive'
},
},
})
],
}
export default NextAuth(authOptions)first off, try to nail down the culprit.
in ur case, this sounds that it is not related to Google stuff, but Auth.js stuff.
more specifically, callbacks such as jwt and session.
in ur case, this sounds that it is not related to Google stuff, but Auth.js stuff.
more specifically, callbacks such as jwt and session.
here is my poc project, where invoke Google Calender API with user's token.
see how i use accessToken and refreshToken.
https://github.com/tfutada/zenn-nextjs/blob/main/app/options.ts
see how i use accessToken and refreshToken.
https://github.com/tfutada/zenn-nextjs/blob/main/app/options.ts
plus don't forget to configure authorization dialong in GCP console.
@tafutada777 here is my poc project, where invoke Google Calender API with user's token.
see how i use accessToken and refreshToken.
https://github.com/tfutada/zenn-nextjs/blob/main/app/options.ts
Orinoco CrocodileOP
Thank you! I’ll look into this more tomorrow! I really appreciate it