From f2db2a2a0a3a09b34e6f28b8a1d43e3d0992d04e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9B=90=EB=8D=94?= Date: Wed, 27 Jan 2021 16:46:14 +0900 Subject: [PATCH] feat: added discord login callback --- pages/api/auth/discord/callback.ts | 64 ++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 4 deletions(-) diff --git a/pages/api/auth/discord/callback.ts b/pages/api/auth/discord/callback.ts index 1951cf8..d3146ab 100644 --- a/pages/api/auth/discord/callback.ts +++ b/pages/api/auth/discord/callback.ts @@ -1,8 +1,64 @@ -import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next' +import { NextApiRequest, NextApiResponse } from 'next' +import nc from 'next-connect' +import fetch from 'node-fetch' +import cookie from 'cookie' -const Callback: NextApiHandler = (_req: NextApiRequest, res: NextApiResponse) => { - res.statusCode = 200 - res.json({ happy: 'hacking' }) +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' + +const Callback = nc() + .get(async(req, 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 }) + const info = verify(userToken) + res.setHeader('set-cookie', cookie.serialize('token', userToken, { + expires: new Date(info.exp * 1000), + secure: process.env.NODE_ENV === 'production', + path: '/' + })) + res.redirect(301, '/') + }) + +interface ApiRequest extends NextApiRequest { + query: { + code: string + } } export default Callback