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

100
auth.ts
View file

@ -1,45 +1,79 @@
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"
}
}
export const { handlers, auth, signIn, signOut } = NextAuth({ export const { handlers, auth, signIn, signOut } = NextAuth({
adapter: PrismaAdapter(prisma), adapter: PrismaAdapter(prisma),
providers: [Authentik({ providers: [Authentik({
clientId: process.env.AUTH_OIDC_CLIENT_ID, clientId: process.env.AUTH_OIDC_CLIENT_ID,
clientSecret: process.env.AUTH_OIDC_CLIENT_SECRET, clientSecret: process.env.AUTH_OIDC_CLIENT_SECRET,
issuer: process.env.AUTH_OIDC_ISSUER, issuer: process.env.AUTH_OIDC_ISSUER,
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
},
async session({session, user}) {
const getToken = await prisma.account.findFirst({
where: {
userId: user.id,
},
});
let accessToken: string | undefined = undefined; if (authentikAccount.expires_at * 1000 < Date.now()) {
if (getToken) { console.info("refreshing token");
accessToken = getToken.access_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",
})
session.access_token = accessToken; const tokens = await response.json()
return session;
} 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,
},
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
}
}
}); });