core/pages/api/auth/discord/callback.ts

82 lines
2.4 KiB
TypeScript

import { NextApiRequest } from 'next'
import fetch from 'node-fetch'
import { serialize } from 'cookie'
import { DiscordEnpoints } from '@utils/Constants'
import { formData } from '@utils/Tools'
import { OauthCallbackSchema } from '@utils/Yup'
import ResponseWrapper from '@utils/ResponseWrapper'
import { DiscordTokenInfo, DiscordUserInfo } from '@types'
import { update } from '@utils/Query'
import { verify } from '@utils/Jwt'
import RequestHandler from '@utils/RequestHandler'
const Callback = RequestHandler().get(async (req: ApiRequest, res) => {
const validate = await OauthCallbackSchema.validate(req.query)
.then(r => r)
.catch(e => {
ResponseWrapper(res, { code: 400, errors: e.errors })
return null
})
if (!validate) return
res.statusCode = 200
const token: DiscordTokenInfo = await fetch(DiscordEnpoints.Token, {
method: 'POST',
body: formData({
client_id: process.env.DISCORD_CLIENT_ID,
redirect_uri: process.env.KOREANBOTS_URL + '/api/auth/discord/callback',
client_secret: process.env.DISCORD_CLIENT_SECRET,
scope: process.env.DISCORD_SCOPE,
grant_type: 'authorization_code',
code: req.query.code,
}),
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
}).then(r => r.json())
if (token.error) return ResponseWrapper(res, { code: 400, errors: ['올바르지 않은 코드입니다.'] })
const user: DiscordUserInfo = await fetch(DiscordEnpoints.Me, {
method: 'GET',
headers: {
Authorization: `${token.token_type} ${token.access_token}`,
},
}).then(r => r.json())
const userToken = await update.assignToken({
id: user.id,
access_token: token.access_token,
expires_in: token.expires_in,
refresh_token: token.refresh_token,
email: user.email,
username: user.username,
discriminator: user.discriminator,
verified: user.verified
})
if(userToken === 1) return res.redirect(301, 'https://docs.koreanbots.dev/bots/account/unverified')
else if(userToken === 2) return res.redirect(301, 'https://docs.koreanbots.dev/bots/account/blocked')
const info = verify(userToken)
res.setHeader(
'set-cookie',
serialize('token', userToken, {
expires: new Date(info.exp * 1000),
secure: process.env.NODE_ENV === 'production',
httpOnly: true,
sameSite: 'lax',
path: '/',
})
)
res.redirect(301, '/callback/discord')
})
interface ApiRequest extends NextApiRequest {
query: {
code: string
}
}
export default Callback