diff --git a/package-lock.json b/package-lock.json
index 7d1a0148278e4085556d1e1f4cfedd421ad4ec6b..bdb592671fb8394c21092da8a6a6bb41c5820ff1 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -48,6 +48,7 @@
         "@types/cytoscape-fcose": "^2.2.4",
         "@types/leaflet": "^1.9.12",
         "@types/node": "^20.10.5",
+        "@types/node-fetch": "^2.6.11",
         "@types/react": "^18.3.3",
         "@types/react-dom": "^18.2.18",
         "@types/react-leaflet-markercluster": "^3.0.4",
@@ -3291,6 +3292,16 @@
         "undici-types": "~5.26.4"
       }
     },
+    "node_modules/@types/node-fetch": {
+      "version": "2.6.11",
+      "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz",
+      "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==",
+      "dev": true,
+      "dependencies": {
+        "@types/node": "*",
+        "form-data": "^4.0.0"
+      }
+    },
     "node_modules/@types/numeral": {
       "version": "2.0.5",
       "resolved": "https://registry.npmjs.org/@types/numeral/-/numeral-2.0.5.tgz",
diff --git a/package.json b/package.json
index 80f1b02c8dd829ca26f89cc07a8dbcf4140a81eb..a3349c236e8a15032c6227e9b30663b18f5ba7b9 100644
--- a/package.json
+++ b/package.json
@@ -54,6 +54,7 @@
     "@types/cytoscape-fcose": "^2.2.4",
     "@types/leaflet": "^1.9.12",
     "@types/node": "^20.10.5",
+    "@types/node-fetch": "^2.6.11",
     "@types/react": "^18.3.3",
     "@types/react-dom": "^18.2.18",
     "@types/react-leaflet-markercluster": "^3.0.4",
diff --git a/pages/api/auth/[...nextauth].ts b/pages/api/auth/[...nextauth].ts
index 6bc263531e475708b23775a74eba2e876c15e586..2a5307254390aa40525302ef0a9fa92cbeb5933a 100644
--- a/pages/api/auth/[...nextauth].ts
+++ b/pages/api/auth/[...nextauth].ts
@@ -5,25 +5,69 @@ import {
 import NextAuth, { AuthOptions } from 'next-auth';
 import { JWT } from 'next-auth/jwt';
 import { OAuthConfig } from 'next-auth/providers';
+import fetch from 'node-fetch';
 
 const token_endpoint_auth_method = process.env.NEXTAUTH_CLIENT_SECRET
   ? 'client_secret_basic'
   : 'none';
 
-const authActive = process.env.AUTH_ACTIVE?.toLowerCase() != 'false';
+const authActive = process.env.AUTH_ACTIVE?.toLowerCase() !== 'false';
+
+async function refreshAccessToken(token: JWT): Promise<JWT> {
+  try {
+    const raw = JSON.stringify({
+      client_id: process.env.NEXTAUTH_CLIENT_ID,
+      grant_type: 'refresh_token',
+      refresh_token: token.refreshToken as string,
+    });
+
+    const response = await fetch(process.env.TOKEN_ENDPOINT!, {
+      method: 'POST',
+      headers: {
+        'Content-Type': 'application/json',
+      },
+      body: raw,
+      redirect: 'follow',
+    });
+
+    if (response.ok) {
+      const data: {
+        access_token: string;
+        expires_in: number;
+        refresh_token: string;
+      } = await response.json();
+
+      return {
+        ...token,
+        accessToken: data.access_token,
+        accessTokenExpires:
+          Math.floor(Date.now() / 1000) + (data.expires_in - 300), // Store expiry as a Unix timestamp (in seconds)
+        refreshToken: data.refresh_token,
+      };
+    } else {
+      return {
+        ...token,
+        error: `${response.statusText}`,
+      };
+    }
+  } catch (error) {
+    return {
+      ...token,
+      error: `${error}`,
+    };
+  }
+}
+
 const wfoProvider: OAuthConfig<WfoUserProfile> = {
   id: process.env.NEXTAUTH_ID || '',
-  name: process.env.NEXTAUTH_ID || '',
+  name: 'GEANT Identity Provider',
   type: 'oauth',
-  clientId: process.env.NEXTAUTH_CLIENT_ID || '',
-  clientSecret: process.env.NEXTAUTH_CLIENT_SECRET || undefined,
-  wellKnown:
-    process.env.NEXTAUTH_WELL_KNOWN_OVERRIDE ??
-    `${process.env.NEXTAUTH_ISSUER || ''}/.well-known/openid-configuration`,
+  clientId: process.env.NEXTAUTH_CLIENT_ID,
+  wellKnown: process.env.NEXTAUTH_WELL_KNOWN_OVERRIDE,
   authorization: {
     params: {
-      scope:
-        process.env.NEXTAUTH_AUTHORIZATION_SCOPE_OVERRIDE ?? 'openid profile',
+      scope: process.env.NEXTAUTH_AUTHORIZATION_SCOPE_OVERRIDE,
+      prompt: 'consent',
     },
   },
   idToken: true,
@@ -35,7 +79,6 @@ const wfoProvider: OAuthConfig<WfoUserProfile> = {
       if (!context.provider.wellKnown || !tokens.access_token) {
         return {};
       }
-
       return await client.userinfo(tokens.access_token);
     },
   },
@@ -55,13 +98,25 @@ const wfoProvider: OAuthConfig<WfoUserProfile> = {
 export const authOptions: AuthOptions = {
   providers: authActive ? [wfoProvider] : [],
   callbacks: {
-    async jwt({ token, account, profile }) {
+    async jwt({ token, account, profile }): Promise<JWT> {
       // The "account" is only available right after signing in -- adding useful data to the token
       if (account) {
         token.accessToken = account.access_token;
-        token.profile = profile;
+        token.refreshToken = account.refresh_token;
+        token.accessTokenExpires = account.expires_at as number;
+
+        token.profile = profile as WfoUserProfile;
+      }
+
+      const now = Math.floor(Date.now() / 1000);
+      if (
+        typeof token.accessTokenExpires === 'number' &&
+        now < token.accessTokenExpires
+      ) {
+        return token;
       }
-      return token;
+
+      return await refreshAccessToken(token);
     },
     async session({ session, token }: { session: WfoSession; token: JWT }) {
       // Assign data to the session to be available in the client through the useSession hook
@@ -72,4 +127,5 @@ export const authOptions: AuthOptions = {
     },
   },
 };
+
 export default NextAuth(authOptions);