GHOSCHT
383b84d103
previously the old token was still being used in the session even though a new one has been saved in the database
85 lines
2.6 KiB
TypeScript
85 lines
2.6 KiB
TypeScript
import NextAuth from "next-auth";
|
|
import Authentik from "next-auth/providers/authentik";
|
|
import { PrismaAdapter } from "@auth/prisma-adapter"
|
|
import { PrismaClient } from "@prisma/client"
|
|
import { JWT } from "next-auth/jwt"
|
|
|
|
const prisma = new PrismaClient()
|
|
|
|
declare module "next-auth" {
|
|
interface Session {
|
|
access_token: string | undefined;
|
|
error?: "RefreshAccessTokenError"
|
|
}
|
|
}
|
|
|
|
declare module "next-auth/jwt" {
|
|
interface JWT {
|
|
access_token: string
|
|
expires_at: number
|
|
refresh_token: string
|
|
error?: "RefreshAccessTokenError"
|
|
}
|
|
}
|
|
|
|
export const { handlers, auth, signIn, signOut } = NextAuth({
|
|
adapter: PrismaAdapter(prisma),
|
|
providers: [Authentik({
|
|
clientId: process.env.AUTH_OIDC_CLIENT_ID,
|
|
clientSecret: process.env.AUTH_OIDC_CLIENT_SECRET,
|
|
issuer: process.env.AUTH_OIDC_ISSUER,
|
|
authorization: { params: { scope: 'openid profile email offline_access' } },
|
|
})],
|
|
callbacks: {
|
|
async session({ session, user }) {
|
|
const [authentikAccount] = await prisma.account.findMany({
|
|
where: { userId: user.id, provider: "authentik" },
|
|
})
|
|
let newAccessToken;
|
|
|
|
if (!authentikAccount.expires_at || !authentikAccount.refresh_token) {
|
|
throw "Expiry time or refresh token not set";
|
|
}
|
|
|
|
if (authentikAccount.expires_at * 1000 < Date.now()) {
|
|
console.info("refreshing token");
|
|
try {
|
|
const response = await fetch(process.env.AUTH_OIDC_TOKEN_URL!, {
|
|
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
body: new URLSearchParams({
|
|
client_id: process.env.AUTH_OIDC_CLIENT_ID!,
|
|
client_secret: process.env.AUTH_OIDC_CLIENT_SECRET!,
|
|
grant_type: "refresh_token",
|
|
refresh_token: authentikAccount.refresh_token,
|
|
}),
|
|
method: "POST",
|
|
})
|
|
|
|
const tokens = await response.json()
|
|
|
|
if (!response.ok) throw tokens
|
|
newAccessToken = tokens.access_token;
|
|
await prisma.account.update({
|
|
data: {
|
|
access_token: tokens.access_token,
|
|
expires_at: Math.floor(Date.now() / 1000 + tokens.expires_in),
|
|
refresh_token:
|
|
tokens.refresh_token ?? authentikAccount.refresh_token,
|
|
},
|
|
where: {
|
|
provider_providerAccountId: {
|
|
provider: "authentik",
|
|
providerAccountId: authentikAccount.providerAccountId,
|
|
},
|
|
},
|
|
})
|
|
} catch (error) {
|
|
console.error("Error refreshing access token", error)
|
|
// The error property will be used client-side to handle the refresh token error
|
|
session.error = "RefreshAccessTokenError"
|
|
}
|
|
}
|
|
return { ...session, access_token: newAccessToken ?? authentikAccount.access_token }
|
|
}
|
|
}
|
|
});
|