diff --git a/pages/api/auth/[...nextauth].ts b/pages/api/auth/[...nextauth].ts index a3db0439d8bdfd2d2ab5ed2b1ee404bba486dff2..fac476e3d72e90cbb8435776ac94cb377ba9a452 100644 --- a/pages/api/auth/[...nextauth].ts +++ b/pages/api/auth/[...nextauth].ts @@ -1,9 +1,49 @@ import NextAuth from 'next-auth' import KeycloakProvider from 'next-auth/providers/keycloak' -// import { UnstorageAdapter } from '@auth/unstorage-adapter' -// import { createStorage } from 'unstorage' -// const storage = createStorage() +const clientId = 'gwdg-fdoman-test' +const clientSecret = process.env.KEY_CLOAK_CLIENT_SECRET || '' +const issuer = 'https://keycloak.sso.gwdg.de/auth/realms/academiccloud' + +async function refreshAccessToken (token: any) { + try { + const url = + issuer + '/protocol/openid-connect/token?' + + new URLSearchParams({ + client_id: clientId, + client_secret: clientSecret, + grant_type: 'refresh_token', + refresh_token: token.refreshToken + }).toString() + + const response = await fetch(url, { + headers: { + 'Content-Type': 'application/x-www-form-urlencoded' + }, + method: 'POST' + }) + + const refreshedTokens = await response.json() + + if (!response.ok) { + throw refreshedTokens + } + + return { + ...token, + accessToken: refreshedTokens.access_token, + accessTokenExpires: Date.now() + refreshedTokens.expires_in * 1000, + refreshToken: refreshedTokens.refresh_token ?? token.refreshToken // Fall back to old refresh token + } + } catch (error) { + console.log(error) + + return { + ...token, + error: 'RefreshAccessTokenError' + } + } +} export const authOptions = { // adapter: UnstorageAdapter(storage), @@ -15,12 +55,9 @@ export const authOptions = { providers: [ // !!! Should be stored in .env file. KeycloakProvider({ - // clientId: 'fdo-manager-webui', - clientId: 'gwdg-fdoman-test', - // clientSecret: 'ay7l6jhECSohAZsEp6HYOaoXdARMQCei', - clientSecret: process.env.KEY_CLOAK_CLIENT_SECRET || '', - // issuer: 'http://localhost:8000/auth/realms/fdo-manager', - issuer: 'https://keycloak.sso.gwdg.de/auth/realms/academiccloud', + clientId, + clientSecret, + issuer, // authorization: { params: { scope: 'openid profile email' } }, profile (profile) { console.log('### profile', profile, '### ### ###') @@ -38,10 +75,12 @@ export const authOptions = { }, async session ({ session, user, token }: any) { console.log('### session', session, user, token, '### ### ###') - return { - ...session, - account: token.account - } + + session.user = token.user + session.accessToken = token.accessToken + session.error = token.error + + return session }, async redirect ({ url, baseUrl }: any) { console.log('### redirect', url, baseUrl, '### ### ###') @@ -49,13 +88,24 @@ export const authOptions = { }, async jwt ({ token, user, account, profile, isNewUser }: any) { console.log('### jwt', token, user, account, profile, isNewUser, '### ### ###') - if (account) { + + // Initial sign in + if (account && user) { return { - ...token, - account + accessToken: account.access_token, + accessTokenExpires: Date.now() + account.expires_in * 1000, + refreshToken: account.refresh_token, + user } } - return token + + // Return previous token if the access token has not expired yet + if (Date.now() < token.accessTokenExpires) { + return token + } + + // Access token has expired, try to update it + return refreshAccessToken(token) } }, secret: 'UItTuD1HcGXIj8ZfHUswhYdNd40Lc325R8VlxQPUoR0='