Enable token refresh

This commit is contained in:
GHOSCHT 2024-05-19 21:34:55 +02:00
parent ca2eef3d08
commit 857b44d810
Signed by: ghoscht
GPG key ID: 2C2C1C62A5388E82

68
auth.ts
View file

@ -1,13 +1,24 @@
import NextAuth,{ type DefaultSession } from "next-auth"; import NextAuth, { type DefaultSession } from "next-auth";
import Authentik from "next-auth/providers/authentik"; import Authentik from "next-auth/providers/authentik";
import { PrismaAdapter } from "@auth/prisma-adapter" import { PrismaAdapter } from "@auth/prisma-adapter"
import { PrismaClient } from "@prisma/client" import { PrismaClient } from "@prisma/client"
import { JWT } from "next-auth/jwt"
const prisma = new PrismaClient() const prisma = new PrismaClient()
declare module "next-auth" { declare module "next-auth" {
interface Session { interface Session {
access_token: string | undefined; access_token: string | undefined;
error?: "RefreshAccessTokenError"
}
}
declare module "next-auth/jwt" {
interface JWT {
access_token: string
expires_at: number
refresh_token: string
error?: "RefreshAccessTokenError"
} }
} }
@ -20,26 +31,49 @@ export const { handlers, auth, signIn, signOut } = NextAuth({
authorization: { params: { scope: 'openid profile email offline_access' } }, authorization: { params: { scope: 'openid profile email offline_access' } },
})], })],
callbacks: { callbacks: {
async jwt({token, account}) { async session({ session, user }) {
if (account) { const [authentikAccount] = await prisma.account.findMany({
token = Object.assign({}, token, { access_token: account.access_token }); where: { userId: user.id, provider: "authentik" },
} })
return token
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
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,
}, },
async session({session, user}) {
const getToken = await prisma.account.findFirst({
where: { where: {
userId: user.id, provider_providerAccountId: {
provider: "authentik",
providerAccountId: authentikAccount.providerAccountId,
}, },
}); },
})
let accessToken: string | undefined = undefined; } catch (error) {
if (getToken) { console.error("Error refreshing access token", error)
accessToken = getToken.access_token!; // The error property will be used client-side to handle the refresh token error
session.error = "RefreshAccessTokenError"
} }
}
session.access_token = accessToken; return session
return session;
} }
} }
}); });