import jwt from 'jsonwebtoken' //eslint-disable-line type AccessTokenResponse = { access_token: string, token_type: string, expires_in: number, refresh_token: string, scope: string } type DiscordUser = { id: string, username: string, discriminator: string, avatar: string, bot?: boolean, system?: boolean, mfa_enabled?: boolean, banner?: string, accent_color?: number, locale?: string, verified?: boolean, email?: string, flags?: number, premium_type?: number, public_flags?: number } export default defineEventHandler(async (event) => { const { code }: { code?: string } = getQuery(event) if (!code) { return sendRedirect(event, '/', 302) } let tokenResponse: AccessTokenResponse let authorizationResponse: DiscordUser try { tokenResponse = await $fetch('https://discord.com/api/oauth2/token', { method: 'POST', body: new URLSearchParams({ client_id: config.discordClientId, client_secret: config.discordClientSecret, code, grant_type: 'authorization_code', redirect_uri: config.oauthRedirectUri, scope: 'identify' }), headers: { 'Content-Type': 'application/x-www-form-urlencoded' } }) authorizationResponse = await $fetch('https://discord.com/api/users/@me', { headers: { authorization: `Bearer ${tokenResponse.access_token}` } }) } catch (e) { console.error('Discord authentication failed', e) throw createError({ statusCode: 500, statusMessage: 'Discord authentication failed' }) } try { const user = await UserModel.findOneAndUpdate({ 'discord.id': authorizationResponse.id }, { $set: { discord: { id: authorizationResponse.id, username: authorizationResponse.username, avatarHash: authorizationResponse.avatar } }, $setOnInsert: { username: authorizationResponse.username } }, { upsert: true, returnDocument: 'after' }) const token = jwt.sign({ accessToken: tokenResponse.access_token, refreshToken: tokenResponse.refresh_token, discordId: authorizationResponse.id, userId: user._id }, config.jwtSecret, { expiresIn: tokenResponse.expires_in }) setCookie(event, 'jwt', token, { httpOnly: true, maxAge: tokenResponse.expires_in * 1000 }) } catch (e) { console.error('Updating user information failed', e) throw createError({ statusCode: 500, statusMessage: 'Updating user information failed' }) } return sendRedirect(event, '/', 302) })