From 2091aec376bf1c091055bb6863bb8f5369197cbb Mon Sep 17 00:00:00 2001 From: M1000fr Date: Wed, 11 Dec 2024 00:41:55 +0100 Subject: [PATCH] feat: switch to JWKS verification --- src/app/components/Auth.tsx | 4 +- src/app/components/FetchWithSession.tsx | 2 +- src/authOptions.ts | 62 ++++++++++++++++++------- src/types/env.d.ts | 11 +++++ src/types/next-auth.d.ts | 21 +++++++-- 5 files changed, 76 insertions(+), 24 deletions(-) create mode 100644 src/types/env.d.ts diff --git a/src/app/components/Auth.tsx b/src/app/components/Auth.tsx index 73d1601..c43e4a2 100644 --- a/src/app/components/Auth.tsx +++ b/src/app/components/Auth.tsx @@ -26,9 +26,9 @@ const Auth = () => { borderRadius: "5px", cursor: "pointer", }} - onClick={() => signIn("discord")} + onClick={() => signIn("oauth2")} > - Sign in with Discord + Sign in with OAuth2 ) : ( diff --git a/src/app/components/FetchWithSession.tsx b/src/app/components/FetchWithSession.tsx index d2a84c4..2080803 100644 --- a/src/app/components/FetchWithSession.tsx +++ b/src/app/components/FetchWithSession.tsx @@ -11,7 +11,7 @@ const FetchWithSession = () => { if (status === "authenticated" && session) { try { const response = await fetch( - `${process.env.NEXT_PUBLIC_API_URL}/`, + `${process.env.NEXT_PUBLIC_API_URL}/ping`, { method: "GET", headers: { diff --git a/src/authOptions.ts b/src/authOptions.ts index 17bfe2b..98d6fd3 100644 --- a/src/authOptions.ts +++ b/src/authOptions.ts @@ -1,36 +1,62 @@ import { AuthOptions } from "next-auth"; -import DiscordProvider from 'next-auth/providers/discord'; -import jwt from 'jsonwebtoken'; export const authOptions: AuthOptions = { providers: [ - DiscordProvider({ - clientId: process.env.DISCORD_CLIENT_ID!, - clientSecret: process.env.DISCORD_CLIENT_SECRET!, - }), + { + id: "oauth2", + name: "oauth2", + type: "oauth", + clientId: process.env.OAUTH_CLIENT_ID, + clientSecret: process.env.OAUTH_CLIENT_SECRET, + authorization: { + url: process.env.OAUTH_AUTHORIZATION_URL, + params: { + scope: "openid email profile", + response_type: "code", + }, + }, + token: process.env.OAUTH_TOKEN_URL, + userinfo: process.env.OAUTH_USERINFO_URL, + issuer: process.env.OAUTH_ISSUER, + jwks_endpoint: process.env.OAUTH_JWKS_ENDPOINT, + profile(profile) { + return { + id: profile.sub || profile.id, + name: + profile.name || + `${profile.given_name} ${profile.family_name}`, + email: profile.email, + image: profile.picture || null, + }; + }, + }, ], - secret: process.env.NEXTAUTH_SECRET, session: { strategy: "jwt", }, callbacks: { async jwt({ token, account, user }) { if (account) { - token.accessToken = jwt.sign( - { - userId: user?.id, - provider: account.provider, - timestamp: Date.now(), - }, - process.env.NEXTAUTH_SECRET!, - { expiresIn: "1h" } - ); + token.accessToken = account.access_token; + token.refreshToken = account.refresh_token; + token.expiresAt = Date.now() + account.expires_in * 1000000; } + + if (user) { + token.userId = user.id; + } + return token; }, async session({ session, token }) { - session.accessToken = token.accessToken; + if (token) { + session.user.id = token.userId; + session.accessToken = token.accessToken; + session.refreshToken = token.refreshToken; + session.expiresAt = token.expiresAt; + } + return session; }, }, -}; \ No newline at end of file +}; diff --git a/src/types/env.d.ts b/src/types/env.d.ts new file mode 100644 index 0000000..b5b3be9 --- /dev/null +++ b/src/types/env.d.ts @@ -0,0 +1,11 @@ +declare namespace NodeJS { + interface ProcessEnv { + OAUTH_CLIENT_ID: string; + OAUTH_CLIENT_SECRET: string; + OAUTH_AUTHORIZATION_URL: string; + OAUTH_TOKEN_URL: string; + OAUTH_USERINFO_URL: string; + OAUTH_ISSUER: string; + OAUTH_JWKS_ENDPOINT: string; + } +} diff --git a/src/types/next-auth.d.ts b/src/types/next-auth.d.ts index 863e852..24562b5 100644 --- a/src/types/next-auth.d.ts +++ b/src/types/next-auth.d.ts @@ -1,14 +1,29 @@ -// eslint-disable-next-line @typescript-eslint/no-unused-vars +/* eslint-disable @typescript-eslint/no-unused-vars */ import NextAuth, { DefaultSession } from "next-auth"; +import { JWT } from "next-auth/jwt"; declare module "next-auth" { - interface Session { + interface Session extends DefaultSession { accessToken: string; + refreshToken: string; + expiresAt: number; + user: { + id: string; + } & DefaultSession["user"]; + } + + interface Account { + expires_in: number; + access_token: string; + refresh_token: string; } } declare module "next-auth/jwt" { interface JWT { - accessToken: string; + accessToken: string; + refreshToken: string; + expiresAt: number; + userId: string; } }