[Solved] use google auth to access other google apis (e.g. Calendar/Drive)

Hello, Once I've authenticated with better-auth for the Google provider, how can I go about using other Google APIs? (e.g. using googleapis, the Node.JS Client). In Next-Auth/Auth.js, this is possible because we have access to the accessToken and refreshToken: - https://github.com/nextauthjs/next-auth/issues/1162#issuecomment-766331341 But in better-auth, this is all I can see for the session:
"session": {
"id": "*****************************",
"expiresAt": "2025-01-24T03:49:44.053Z",
"token": "*****************************",
"createdAt": "2025-01-17T03:49:44.053Z",
"updatedAt": "2025-01-17T03:49:44.053Z",
"ipAddress": "::ffff:127.0.0.1",
"userAgent": "*****************************",
"userId": "*****************************",
"impersonatedBy": null
},
"session": {
"id": "*****************************",
"expiresAt": "2025-01-24T03:49:44.053Z",
"token": "*****************************",
"createdAt": "2025-01-17T03:49:44.053Z",
"updatedAt": "2025-01-17T03:49:44.053Z",
"ipAddress": "::ffff:127.0.0.1",
"userAgent": "*****************************",
"userId": "*****************************",
"impersonatedBy": null
},
GitHub
Using auth to access other googleapis · Issue #1162 · nextauthjs/ne...
Your question What is the best way of using next-auth as an auth instant to googleapis? What are you trying to do I'm trying to send a mail with gmail api from the backend. Feedback Documentati...
1 Reply
nktnet
nktnetOP3mo ago
Solved - you will need to query the account table, where your accessToken and refreshToken resides. Example (I'm using the drizzle-orm adapter):
import { google } from 'googleapis';
import { headers } from 'next/headers';
import { GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET } from '@/config/server';
import { db } from '@/db/db';
import { auth } from '@/lib/auth';

export default async function CalendarList() {
const session = await auth.api.getSession({
headers: await headers(),
});

if (!session?.user) {
return <div>Not logged in!</div>;
}

const googleAuth = new google.auth.OAuth2({
clientId: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
});

const account = await db.query.accountsTable.findFirst({
where: (table, { and, eq }) =>
and(eq(table.userId, session.user.id), eq(table.providerId, 'google')),
});

if (!account) {
return <div>Please also log in with Google at least once!</div>;
}

googleAuth.setCredentials({
access_token: account.accessToken,
refresh_token: account.refreshToken,
});

const calendar = google.calendar({ version: 'v3', auth: googleAuth });
const calendarList = await calendar.calendarList.list();
const writableCalendarList = calendarList.data.items?.filter(
(cal) => cal.accessRole && ['owner', 'writer'].includes(cal.accessRole),
);

return (
<div>
<div className="whitespace-pre-wrap">You are: {JSON.stringify(session, null, 2)}</div>
<div className="whitespace-pre-wrap">
Writable Calendars: {JSON.stringify(writableCalendarList, null, 2)}
</div>
</div>
);
}
import { google } from 'googleapis';
import { headers } from 'next/headers';
import { GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET } from '@/config/server';
import { db } from '@/db/db';
import { auth } from '@/lib/auth';

export default async function CalendarList() {
const session = await auth.api.getSession({
headers: await headers(),
});

if (!session?.user) {
return <div>Not logged in!</div>;
}

const googleAuth = new google.auth.OAuth2({
clientId: GOOGLE_CLIENT_ID,
clientSecret: GOOGLE_CLIENT_SECRET,
});

const account = await db.query.accountsTable.findFirst({
where: (table, { and, eq }) =>
and(eq(table.userId, session.user.id), eq(table.providerId, 'google')),
});

if (!account) {
return <div>Please also log in with Google at least once!</div>;
}

googleAuth.setCredentials({
access_token: account.accessToken,
refresh_token: account.refreshToken,
});

const calendar = google.calendar({ version: 'v3', auth: googleAuth });
const calendarList = await calendar.calendarList.list();
const writableCalendarList = calendarList.data.items?.filter(
(cal) => cal.accessRole && ['owner', 'writer'].includes(cal.accessRole),
);

return (
<div>
<div className="whitespace-pre-wrap">You are: {JSON.stringify(session, null, 2)}</div>
<div className="whitespace-pre-wrap">
Writable Calendars: {JSON.stringify(writableCalendarList, null, 2)}
</div>
</div>
);
}

Did you find this page helpful?