Is there a way to get the refresh token after using a social provider?
I didn't find it in the docs but I was wondering if it was possible to get the refresh token from google after sign up. I need it for a calendar integration that I am building. If not is there a way I can handle the oauth2 callback myself so I can get it?
19 Replies
yeah you can do it
in you auth config please make sure to do include this options -
oh wow thank you I never even knew
yeah i should add it somewhere on the docs
thanks for callout tho
this is a great library btw. Moved from clerk and don't regret it
lets goo! . hope this will your last one to try auth. 🙂
one more question, is it possible to use this in conjunction with the after hooks. An example of what I'm trying to do below:
export const auth = betterAuth({
emailAndPassword: {
enabled: true,
},
socialProviders: {
google: {
enabled: true,
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
scope: [
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/calendar.readonly",
"https://www.googleapis.com/auth/calendar.events",
],
refreshAccessToken: async (refreshToken) => {
console.log("refreshToken from google", JSON.stringify(refreshToken));
return {
refreshToken: refreshToken,
};
},
},
},
databaseHooks: {
user: {
create: {
after: async (user, refreshToken) => {
await Agent.create({
userId: user.id,
name: user.name,
email: user.email,
refreshToken: refreshToken,
});
},
},
},
},
database: mongodbAdapter(db),
trustedOrigins: ["http://localhost:5173"],
});
I was printing out because I can't seem to find it
I need to mention to that I'm not trying to refresh access tokens, I am trying to find the refreshTokens
@KiNFiSH @bekacru
this snippet isn't correct. the user db hook doesn't provider a refershToken. I recommend using
account
hook instead and fetching the additional user info from the databaseok so this with the account hook is how to do it?
When I tried this the refresh token isn't being returned. Could it be something I need to set on google's side?
this is my code:
export const auth = betterAuth({
emailAndPassword: {
enabled: true,
},
socialProviders: {
google: {
enabled: true,
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
scope: [
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/calendar.readonly",
"https://www.googleapis.com/auth/calendar.events",
],
}
},
databaseHooks: {
account: {
create: {
after: async (account, ctx) => {
try {
console.log("account created: ", JSON.stringify(account, null, 2))
console.log("refresh token: ", account.refreshToken)
const user = await ctx?.context.internalAdapter.findUserById(account.userId)
if (!user) {
throw new Error("User not found")
}
await Agent.create({
userId: user.id,
name: user.name,
email: user.email,
refreshToken: account.refreshToken
})
} catch (error) { console.log(error) throw new Error("Failed to create agent") } } } } }, database: mongodbAdapter(db), plugins: [openAPI()], trustedOrigins: ["http://localhost:5173"], });
} catch (error) { console.log(error) throw new Error("Failed to create agent") } } } } }, database: mongodbAdapter(db), plugins: [openAPI()], trustedOrigins: ["http://localhost:5173"], });

Solution
pass accessType: "offline" in your google config
tried this but the same was returned
my code:
export const auth = betterAuth({
emailAndPassword: {
enabled: true,
},
socialProviders: {
google: {
enabled: true,
accessType: "offline",
clientId: process.env.GOOGLE_CLIENT_ID as string,
clientSecret: process.env.GOOGLE_CLIENT_SECRET as string,
scope: [
"https://www.googleapis.com/auth/userinfo.email",
"https://www.googleapis.com/auth/userinfo.profile",
"https://www.googleapis.com/auth/calendar",
"https://www.googleapis.com/auth/calendar.readonly",
"https://www.googleapis.com/auth/calendar.events",
],
}
},
databaseHooks: {
account: {
create: {
after: async (account, ctx) => {
try {
console.log("account created: ", JSON.stringify(account, null, 2))
console.log("refresh token: ", account.refreshToken)
const user = await ctx?.context.internalAdapter.findUserById(account.userId)
if (!user) {
throw new Error("User not found")
}
await Agent.create({
userId: user.id,
name: user.name,
email: user.email,
refreshToken: account.refreshToken
})
} catch (error) { console.log(error) throw new Error("Failed to create agent") } } } } }, database: mongodbAdapter(db), plugins: [openAPI()], trustedOrigins: ["http://localhost:5173"], });
} catch (error) { console.log(error) throw new Error("Failed to create agent") } } } } }, database: mongodbAdapter(db), plugins: [openAPI()], trustedOrigins: ["http://localhost:5173"], });

Yeah I've tried placing it in a different position in the google object put it's not working
not really sure why google isn't returning refershToken. The only requirement it is that accessType needs to be offline
could it have something to do with my authClient on the frontend?
wait I think it's only returned the first time the user is linked to your app
oh ok that makes sense, I've been logging in and out with this account for test purposes. I'll give it a go again
ok it sends back the refresh token
Thank you so much
Do you have a buy me a coffee link?
Hey, thanks! don't worry this is my job :))
But If you’d like, you can sponsor the project on GitHub
https://github.com/sponsors/better-auth