Open deadcoder0904 opened 2 years ago
@alkihis i'm trying to make sense of these commented lines & i'm wondering if i can just let the user logged in for 365 days & not need to implement this. is that possible? see https://stackoverflow.com/a/14200115/6141587 & https://stackoverflow.com/a/39574303/6141587
if it's not possible, where do i put this code? can i place it in the same place as the callback route or a separate twitter client file where i make a class & put refresh & access token code there?
currently the twitter client file looks like this:
import TwitterApi from 'twitter-api-v2'
import { TWITTER_CONFIG } from '@/utils/index'
export const twitterClient = new TwitterApi({
clientId: TWITTER_CONFIG.CLIENT_ID,
clientSecret: TWITTER_CONFIG.CLIENT_SECRET,
})
and my callback looks like with the commented code implemented:
import { NextApiResponse } from 'next'
import TwitterApi from 'twitter-api-v2'
import handler from '@/server/api-route'
import { TWITTER_CONFIG } from '@/utils/index'
import { twitterClient } from '@/utils/twitter'
import { NextIronRequest } from '@/types/index'
// import { createUser } from '@/server/graphql/User/index'
const getVerifierToken = async (req: NextIronRequest, res: NextApiResponse) => {
const state = req.query.state as string
const code = req.query.code as string
const { state: storedState, codeVerifier } = req.session.twitter
if (storedState !== state) {
return res
.status(400)
.send(
'OAuth token is not known or invalid. Your request may have expired. Please renew the auth process.'
)
}
const {
client: loggedClient,
accessToken,
refreshToken,
expiresIn,
} = await twitterClient.loginWithOAuth2({
code,
codeVerifier,
redirectUri: TWITTER_CONFIG.CALLBACK_URL,
})
try {
const {
data: { id: userId, name, username, profile_image_url, description, url },
} = await loggedClient.v2.me()
console.log({ userId, name, username, profile_image_url, description, url })
console.log({ loggedClient, accessToken, refreshToken, expiresIn })
req.session.twitter = {
codeVerifier,
state,
accessToken,
refreshToken,
}
if (expiresIn > 0) {
console.log('not expired')
const freshInstance = new TwitterApi(accessToken)
} else {
console.log('expired')
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const { client: renewedInstance, accessToken: newAccessToken } =
await twitterClient.refreshOAuth2Token(refreshToken!)
}
req.session.user = { id: userId, username, name, profile_image: profile_image_url }
await req.session.save()
// await createUser({ userId: id, username, name, profile_image })
} catch (e) {
console.error(e)
}
res.redirect('/dashboard')
}
export default handler().get(getVerifierToken)
this causes me confusion as the renewedInstance
can't be used elsewhere outside as it's in the callback file which is a next.js api route.
if i try to put it in a common file, do i need to send it an instance like:
export const getTwitterClient = (
accessToken?: string,
expiresIn?: number,
instance?: TwitterApi
): TwitterApi => {
let twitterClient: TwitterApi = new TwitterApi({
clientId: TWITTER_CONFIG.CLIENT_ID,
clientSecret: TWITTER_CONFIG.CLIENT_SECRET,
})
if (accessToken) {
twitterClient = new TwitterApi(accessToken)
} else if (expiresIn && instance && expiresIn > 0) {
twitterClient = instance
}
return twitterClient
}
this lets me access twitterClient
irrespective of which file i'm in. it also means removing the commented code you have from the callback file.
i think prisma
does this to make it accessible in other files:
import { PrismaClient } from "@prisma/client";
// Make global.cachedPrisma work with TypeScript
declare global {
// NOTE: This actually needs to be a "var", let/const don't work here.
// eslint-disable-next-line no-var
var cachedPrisma: PrismaClient;
}
// Workaround to make Prisma Client work well during "next dev"
// @see https://www.prisma.io/docs/support/help-articles/nextjs-prisma-client-dev-practices
let prisma: PrismaClient;
if (process.env.NODE_ENV === "production") {
prisma = new PrismaClient();
} else {
if (!global.cachedPrisma) {
global.cachedPrisma = new PrismaClient();
}
prisma = global.cachedPrisma;
}
export default prisma;
the best-case scenario is to avoid implementing this as i can't find anyone who has done it before but would love a little guidance if you've got time :)
https://github.com/alkihis/twitter-api-v2-user-oauth2-flow-example/blob/ce032d65ab43d6bbaa63eff737775942724c5ad1/src/routes/callback.ts#L54-L64
or another example using v2 as i'm currently making an app using v2 :)