diff --git a/package-lock.json b/package-lock.json index 2e3f610..c890e27 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "ketcher-standalone": "^3.2.0", "lucide-react": "^0.487.0", "next": "15.5.2", - "next-auth": "^5.0.0-beta.25", + "next-auth": "^5.0.0-beta.29", "pino": "^9.3.2", "react": "19.1.0", "react-dom": "19.1.0", @@ -110,7 +110,6 @@ "version": "0.40.0", "resolved": "https://registry.npmjs.org/@auth/core/-/core-0.40.0.tgz", "integrity": "sha512-n53uJE0RH5SqZ7N1xZoMKekbHfQgjd0sAEyUbE+IYJnmuQkbvuZnXItCU7d+i7Fj8VGOgqvNO7Mw4YfBTlZeQw==", - "license": "ISC", "dependencies": { "@panva/hkdf": "^1.2.1", "jose": "^6.0.6", @@ -3773,7 +3772,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/@panva/hkdf/-/hkdf-1.2.1.tgz", "integrity": "sha512-6oclG6Y3PiDFcoyk8srjLfVKyMfVCKJ27JwNPViuXziFpmdz+MZnZN/aKY0JGXgYuO/VghU0jcOAZgWXZ1Dmrw==", - "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } @@ -11091,7 +11089,6 @@ "version": "6.1.0", "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.0.tgz", "integrity": "sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==", - "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } @@ -13336,7 +13333,6 @@ "version": "5.0.0-beta.29", "resolved": "https://registry.npmjs.org/next-auth/-/next-auth-5.0.0-beta.29.tgz", "integrity": "sha512-Ukpnuk3NMc/LiOl32njZPySk7pABEzbjhMUFd5/n10I0ZNC7NCuVv8IY2JgbDek2t/PUOifQEoUiOOTLy4os5A==", - "license": "ISC", "dependencies": { "@auth/core": "0.40.0" }, @@ -13873,7 +13869,6 @@ "version": "3.8.1", "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.1.tgz", "integrity": "sha512-olkZDELNycOWQf9LrsELFq8n05LwJgV8UkrS0cburk6FOwf8GvLam+YB+Uj5Qvryee+vwWOfQVeI5Vm0MVg7SA==", - "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } @@ -14423,7 +14418,6 @@ "version": "10.24.3", "resolved": "https://registry.npmjs.org/preact/-/preact-10.24.3.tgz", "integrity": "sha512-Z2dPnBnMUfyQfSQ+GBdsGa16hz35YmLmtTLhM169uW944hYL6xzTYkJjC07j+Wosz733pMWx0fgON3JNw1jJQA==", - "license": "MIT", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -14433,7 +14427,6 @@ "version": "6.5.11", "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-6.5.11.tgz", "integrity": "sha512-ubnauqoGczeGISiOh6RjX0/cdaF8v/oDXIjO85XALCQjwQP+SB4RDXXtvZ6yTYSjG+PC1QRP2AhPgCEsM2EvUw==", - "license": "MIT", "peerDependencies": { "preact": ">=10" } diff --git a/package.json b/package.json index 858cc3d..69323f3 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "ketcher-standalone": "^3.2.0", "lucide-react": "^0.487.0", "next": "15.5.2", - "next-auth": "^5.0.0-beta.25", + "next-auth": "^5.0.0-beta.29", "pino": "^9.3.2", "react": "19.1.0", "react-dom": "19.1.0", @@ -81,4 +81,4 @@ "react": "19.1.0", "react-dom": "19.1.0" } -} \ No newline at end of file +} diff --git a/src/auth.ts b/src/auth.ts index eb28b11..abd8a78 100644 --- a/src/auth.ts +++ b/src/auth.ts @@ -1,9 +1,8 @@ import NextAuth, { DefaultSession } from 'next-auth'; -import KeycloakProvider from 'next-auth/providers/keycloak'; import { DefaultJWT } from '@auth/core/jwt'; import { jwtDecode } from 'jwt-decode'; -import Keycloak from 'next-auth/providers/keycloak'; +import KeycloakProvider from 'next-auth/providers/keycloak'; import { logger } from '@/logger'; const log = logger.child({ module: 'error' }); @@ -27,25 +26,43 @@ declare module 'next-auth' { } export const { auth, handlers, signIn, signOut } = NextAuth({ - providers: [Keycloak], + session: { + strategy: 'jwt', + maxAge: 180 * 24 * 60 * 60, + }, + providers: [ + KeycloakProvider({ + issuer: process.env.AUTH_KEYCLOAK_ISSUER, + clientId: process.env.AUTH_KEYCLOAK_ID!, + clientSecret: process.env.AUTH_KEYCLOAK_SECRET, + authorization: { + params: { + scope: 'openid profile email offline_access', + }, + }, + }), + ], callbacks: { jwt: async ({ token, user, account }) => { // Initial sign in if (account && account.access_token) { token.accessToken = account.access_token; token.refreshToken = account.refresh_token; - if (account.expires_at) { - token.accessTokenExpires = account.expires_at * 1000; - } + const expiresAt = (account as any).expires_at + ? (account as any).expires_at * 1000 + : (account as any).expires_in + ? Date.now() + (account as any).expires_in * 1000 + : undefined; + if (expiresAt) token.accessTokenExpires = expiresAt; } // return token; // Return previous token if the access token has not expired yet - if ( - !token.accessTokenExpires || - Date.now() < (token.accessTokenExpires as number) - ) { + const expires = token.accessTokenExpires as number | undefined; + const hasValidExpiry = typeof expires === 'number'; + const isStillValid = hasValidExpiry && Date.now() < expires - 60_000; + if (isStillValid) { return token; }