From 4aeef6a03c762baede557df9ecf1f1e4c25332b5 Mon Sep 17 00:00:00 2001 From: Nick Kosarev Date: Thu, 22 Aug 2024 17:21:38 +0200 Subject: [PATCH] chore: jwt creation on sign in (#214) --- .../website/src/server/api/auth/twitch.get.ts | 53 ++++++++++++++++--- libs/types/src/lib/types.ts | 1 - 2 files changed, 45 insertions(+), 9 deletions(-) diff --git a/apps/website/src/server/api/auth/twitch.get.ts b/apps/website/src/server/api/auth/twitch.get.ts index 59550e28..ba7ab57f 100644 --- a/apps/website/src/server/api/auth/twitch.get.ts +++ b/apps/website/src/server/api/auth/twitch.get.ts @@ -1,7 +1,8 @@ import jwt from 'jsonwebtoken' -import type { WebsiteProfile } from '@chat-game/types' +import type { TwitchAccessTokenResponse, WebsiteProfile } from '@chat-game/types' +import { getTokenInfo } from '@twurple/auth' -export default defineEventHandler((event) => { +export default defineEventHandler(async (event) => { const { public: publicEnv, jwtSecretKey } = useRuntimeConfig() const query = getQuery(event) @@ -13,17 +14,36 @@ export default defineEventHandler((event) => { } const code = query.code.toString() + const twitchResponse = await obtainTwitchAccessToken(code) + if (!twitchResponse?.access_token) { + throw createError({ + statusCode: 401, + statusMessage: 'Unauthorized', + }) + } - log(JSON.stringify(query), code) + const tokenInfo = await getTokenInfo(twitchResponse.access_token) + if (!tokenInfo.userId || !tokenInfo.userName) { + throw createError({ + statusCode: 400, + statusMessage: 'Wrong userId or userName', + }) + } + + const repository = new DBRepository() + + const profileInDB = await repository.findOrCreateProfile({ + userId: tokenInfo.userId, + userName: tokenInfo.userName, + }) const profile: WebsiteProfile = { - id: '123', - twitchToken: '2134', - twitchId: '1245', - userName: 'tester', + id: profileInDB.id, + twitchId: tokenInfo.userId, + userName: tokenInfo.userName, } - const token = jwt.sign({ profile }, jwtSecretKey, { expiresIn: '48h' }) + const token = jwt.sign({ profile }, jwtSecretKey, { expiresIn: '7d' }) setCookie(event, publicEnv.cookieKey, token, { path: '/', @@ -32,3 +52,20 @@ export default defineEventHandler((event) => { return sendRedirect(event, '/') }) + +async function obtainTwitchAccessToken(code: string) { + const { public: publicEnv, twitchSecretId } = useRuntimeConfig() + + try { + const response = await fetch( + `https://id.twitch.tv/oauth2/token?client_id=${publicEnv.twitchClientId}&client_secret=${twitchSecretId}&code=${code}&grant_type=authorization_code&redirect_uri=${publicEnv.signInRedirectUrl}`, + { + method: 'POST', + } + ) + return (await response.json()) as TwitchAccessTokenResponse + } catch (err) { + console.error('obtainTwitchAccessToken', err) + return null + } +} diff --git a/libs/types/src/lib/types.ts b/libs/types/src/lib/types.ts index be0f87ce..4bc48dbd 100644 --- a/libs/types/src/lib/types.ts +++ b/libs/types/src/lib/types.ts @@ -506,7 +506,6 @@ export interface TwitchAccessToken { export interface WebsiteProfile { id: string - twitchToken: string twitchId: string userName: string }