1
0
Fork 0

feat(nextauth): properly handle signout

When signing out, by default keycloak session is not terminated, this fixes it and sends a request to keycloak instance to terminate the keycloak session.
This commit is contained in:
Vojtěch Mareš 2023-09-03 10:50:40 +02:00
parent 2a7b833b2e
commit 377e9e9570
Signed by: vojtech.mares
GPG key ID: C6827B976F17240D

View file

@ -6,6 +6,9 @@ import {
type DefaultSession,
} from "next-auth";
import KeycloakProvider from "next-auth/providers/keycloak";
import { type KeycloakProfile } from "next-auth/providers/keycloak";
import { type JWT } from "next-auth/jwt";
import { type OAuthConfig } from "next-auth/providers";
import { env } from "~/env.mjs";
import { prisma } from "~/server/db";
@ -30,6 +33,18 @@ declare module "next-auth" {
// }
}
/**
* Part of the Keycloak fix/workaround, see code bellow for method `signOut`.
*
* @see https://stackoverflow.com/a/75526977
*/
declare module 'next-auth/jwt' {
interface JWT {
id_token?: string;
provider?: string;
}
}
/**
* Options for NextAuth.js used to configure adapters, providers, callbacks, etc.
*
@ -46,6 +61,18 @@ export const authOptions: NextAuthOptions = {
image: user.image,
},
}),
/**
* Part of the Keycloak fix/workaround, see code bellow for method `signOut`.
*
* @see https://stackoverflow.com/a/75526977
*/
async jwt({ token, account }) {
if (account) {
token.id_token = account.id_token
token.provider = account.provider
}
return token
},
},
adapter: PrismaAdapter(prisma),
providers: [
@ -68,6 +95,22 @@ export const authOptions: NextAuthOptions = {
* @see https://next-auth.js.org/providers/github
*/
],
events: {
/**
* Fix for Keycloak not destroying the session token on logout,
* we must send an extra request to delete the session.
*
* @see https://stackoverflow.com/a/75526977
*/
async signOut({ token }: { token: JWT }) {
if (token.provider === "keycloak") {
const issuerUrl = (authOptions.providers.find(p => p.id === "keycloak") as OAuthConfig<KeycloakProfile>).options!.issuer!
const logOutUrl = new URL(`${issuerUrl}/protocol/openid-connect/logout`)
logOutUrl.searchParams.set("id_token_hint", token.id_token!)
await fetch(logOutUrl);
}
},
}
};
/**