BA
Better Auth•2w ago
Joshua

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?
Solution:
pass accessType: "offline" in your google config
Jump to solution
19 Replies
KiNFiSH
KiNFiSH•2w ago
yeah you can do it in you auth config please make sure to do include this options -
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
refreshAccessToken: async (refreshToken) => {
// do you logic

},
},
google: {
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
refreshAccessToken: async (refreshToken) => {
// do you logic

},
},
Joshua
JoshuaOP•2w ago
oh wow thank you I never even knew
KiNFiSH
KiNFiSH•2w ago
yeah i should add it somewhere on the docs thanks for callout tho
Joshua
JoshuaOP•2w ago
this is a great library btw. Moved from clerk and don't regret it
KiNFiSH
KiNFiSH•2w ago
lets goo! . hope this will your last one to try auth. 🙂
Joshua
JoshuaOP•2w ago
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
bekacru
bekacru•2w ago
databaseHooks: {
user: {
create: {
after: async (user, refreshToken) => {
await Agent.create({
userId: user.id,
name: user.name,
email: user.email,
refreshToken: refreshToken,
});
},
},
},
databaseHooks: {
user: {
create: {
after: async (user, refreshToken) => {
await Agent.create({
userId: user.id,
name: user.name,
email: user.email,
refreshToken: refreshToken,
});
},
},
},
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 database
Joshua
JoshuaOP•2w ago
ok so this with the account hook is how to do it?
bekacru
bekacru•2w ago
databaseHooks: {
account: {
create: {
after: async (account, ctx) => {
const user = await ctx?.context.internalAdapter.findUserById(account.userId)
await Agent.create({
userId: account.userId,
refreshToken: account.refershToken,
//for name and email you'd need to make a db call to retrive the user info (e.g
name: user.name,
email: user.email,
});
},
},
},
databaseHooks: {
account: {
create: {
after: async (account, ctx) => {
const user = await ctx?.context.internalAdapter.findUserById(account.userId)
await Agent.create({
userId: account.userId,
refreshToken: account.refershToken,
//for name and email you'd need to make a db call to retrive the user info (e.g
name: user.name,
email: user.email,
});
},
},
},
Joshua
JoshuaOP•2w ago
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"], });
No description
Solution
bekacru
bekacru•2w ago
pass accessType: "offline" in your google config
Joshua
JoshuaOP•2w ago
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"], });
Joshua
JoshuaOP•2w ago
No description
Joshua
JoshuaOP•2w ago
Yeah I've tried placing it in a different position in the google object put it's not working
bekacru
bekacru•2w ago
not really sure why google isn't returning refershToken. The only requirement it is that accessType needs to be offline
Joshua
JoshuaOP•2w ago
could it have something to do with my authClient on the frontend?
bekacru
bekacru•2w ago
wait I think it's only returned the first time the user is linked to your app
Joshua
JoshuaOP•2w ago
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?
bekacru
bekacru•2w ago
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
GitHub
Sponsor @better-auth on GitHub Sponsors
Support better-auth's open source work

Did you find this page helpful?