Enable token refresh
This commit is contained in:
parent
ca2eef3d08
commit
857b44d810
1 changed files with 67 additions and 33 deletions
68
auth.ts
68
auth.ts
|
@ -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 { 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"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,26 +31,49 @@ export const { handlers, auth, signIn, signOut } = NextAuth({
|
|||
authorization: { params: { scope: 'openid profile email offline_access' } },
|
||||
})],
|
||||
callbacks: {
|
||||
async jwt({token, account}) {
|
||||
if (account) {
|
||||
token = Object.assign({}, token, { access_token: account.access_token });
|
||||
}
|
||||
return token
|
||||
async session({ session, user }) {
|
||||
const [authentikAccount] = await prisma.account.findMany({
|
||||
where: { userId: user.id, provider: "authentik" },
|
||||
})
|
||||
|
||||
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: {
|
||||
userId: user.id,
|
||||
provider_providerAccountId: {
|
||||
provider: "authentik",
|
||||
providerAccountId: authentikAccount.providerAccountId,
|
||||
},
|
||||
});
|
||||
|
||||
let accessToken: string | undefined = undefined;
|
||||
if (getToken) {
|
||||
accessToken = getToken.access_token!;
|
||||
},
|
||||
})
|
||||
} 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"
|
||||
}
|
||||
|
||||
session.access_token = accessToken;
|
||||
return session;
|
||||
}
|
||||
return session
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue