Skip to content
Snippets Groups Projects

add refresh token logic

Merged Mohammad Torkashvand requested to merge feature/NAT-761-add-refresh-token-logic into develop
All threads resolved!
4 files
+ 82
13
Compare changes
  • Side-by-side
  • Inline
Files
4
@@ -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.NEXTAUTH_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);
Loading