feat: switch to JWKS verification

This commit is contained in:
M1000fr 2024-12-11 00:41:55 +01:00
parent 124a46e0d1
commit 2091aec376
5 changed files with 76 additions and 24 deletions

View File

@ -26,9 +26,9 @@ const Auth = () => {
borderRadius: "5px", borderRadius: "5px",
cursor: "pointer", cursor: "pointer",
}} }}
onClick={() => signIn("discord")} onClick={() => signIn("oauth2")}
> >
Sign in with Discord Sign in with OAuth2
</button> </button>
</div> </div>
) : ( ) : (

View File

@ -11,7 +11,7 @@ const FetchWithSession = () => {
if (status === "authenticated" && session) { if (status === "authenticated" && session) {
try { try {
const response = await fetch( const response = await fetch(
`${process.env.NEXT_PUBLIC_API_URL}/`, `${process.env.NEXT_PUBLIC_API_URL}/ping`,
{ {
method: "GET", method: "GET",
headers: { headers: {

View File

@ -1,35 +1,61 @@
import { AuthOptions } from "next-auth"; import { AuthOptions } from "next-auth";
import DiscordProvider from 'next-auth/providers/discord';
import jwt from 'jsonwebtoken';
export const authOptions: AuthOptions = { export const authOptions: AuthOptions = {
providers: [ providers: [
DiscordProvider({ {
clientId: process.env.DISCORD_CLIENT_ID!, id: "oauth2",
clientSecret: process.env.DISCORD_CLIENT_SECRET!, 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: { session: {
strategy: "jwt", strategy: "jwt",
}, },
callbacks: { callbacks: {
async jwt({ token, account, user }) { async jwt({ token, account, user }) {
if (account) { if (account) {
token.accessToken = jwt.sign( token.accessToken = account.access_token;
{ token.refreshToken = account.refresh_token;
userId: user?.id, token.expiresAt = Date.now() + account.expires_in * 1000000;
provider: account.provider,
timestamp: Date.now(),
},
process.env.NEXTAUTH_SECRET!,
{ expiresIn: "1h" }
);
} }
if (user) {
token.userId = user.id;
}
return token; return token;
}, },
async session({ session, 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; return session;
}, },
}, },

11
src/types/env.d.ts vendored Normal file
View File

@ -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;
}
}

View File

@ -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 NextAuth, { DefaultSession } from "next-auth";
import { JWT } from "next-auth/jwt";
declare module "next-auth" { declare module "next-auth" {
interface Session { interface Session extends DefaultSession {
accessToken: string; 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" { declare module "next-auth/jwt" {
interface JWT { interface JWT {
accessToken: string; accessToken: string;
refreshToken: string;
expiresAt: number;
userId: string;
} }
} }