Skip to content

Commit

Permalink
fix: validate token on isAuthenticated
Browse files Browse the repository at this point in the history
  • Loading branch information
DanielRivers committed Oct 18, 2024
1 parent 0f43965 commit c3e89c6
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 33 deletions.
12 changes: 6 additions & 6 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,9 @@
"dependencies": {
"@babel/preset-env": "^7.23.9",
"@kinde-oss/kinde-typescript-sdk": "2.9.1",
"@kinde/jwt-decoder": "^0.2.0",
"cookie": "^1.0.0",
"crypto-js": "^4.1.1",
"jwt-decode": "^3.1.2",
"uncrypto": "^0.1.3"
},
"files": [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,19 @@
import jwt_decode from 'jwt-decode';
import {NextResponse} from 'next/server';
import {config} from '../config/index';
import {isTokenValid} from '../utils/pageRouter/isTokenValid';
import {type KindeAccessToken, KindeIdToken} from '../../types';
import {jwtDecoder} from '@kinde/jwt-decoder';

const trimTrailingSlash = (str) =>
str && str.charAt(str.length - 1) === '/' ? str.slice(0, -1) : str;

export function authMiddleware(request) {
let isAuthenticated = false;
const nextUrl = trimTrailingSlash(request.nextUrl.href);
const logoutUrl = trimTrailingSlash(config.postLogoutRedirectURL);
const kinde_token = request.cookies.get('kinde_token');
const isLogoutUrl = nextUrl === logoutUrl;

if (kinde_token) {
const payload = jwt_decode(JSON.parse(kinde_token.value).access_token);
isAuthenticated = true;
}
const isAuthenticated = isTokenValid(kinde_token?.value);

if (!isAuthenticated && !isLogoutUrl) {
return NextResponse.redirect(
Expand Down Expand Up @@ -60,8 +57,12 @@ const handleMiddleware = async (req, options, onSuccess) => {
return response;
}

const accessTokenValue = jwt_decode(req.cookies.get('access_token').value);
const idTokenValue = jwt_decode(req.cookies.get('id_token')?.value);
const accessTokenValue = jwtDecoder<KindeAccessToken>(
req.cookies.get('access_token').value
);
const idTokenValue = jwtDecoder<KindeIdToken>(
req.cookies.get('id_token')?.value
);

const isAuthorized = options?.isAuthorized
? options.isAuthorized({req, token: accessTokenValue})
Expand Down Expand Up @@ -96,6 +97,7 @@ const handleMiddleware = async (req, options, onSuccess) => {
export function withAuth(...args) {
// most basic usage - no options
if (!args.length || args[0] instanceof Request) {
// @ts-ignore
return handleMiddleware(...args);
}

Expand All @@ -112,5 +114,6 @@ export function withAuth(...args) {

// includes options
const options = args[0];
// @ts-ignore
return async (...args) => await handleMiddleware(args[0], options);
}
16 changes: 7 additions & 9 deletions src/handlers/setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import jwtDecode from 'jwt-decode';
import {jwtDecoder} from '@kinde/jwt-decoder';
import {KindeAccessToken, KindeIdToken} from '../../types';
import {config} from '../config/index';
import {generateUserObject} from '../utils/generateUserObject';
Expand All @@ -14,17 +14,15 @@ export const setup = async (routerClient) => {
routerClient.sessionManager
);

const accessTokenEncoded = await routerClient.sessionManager.getSessionItem(
'access_token'
);
const accessTokenEncoded =
await routerClient.sessionManager.getSessionItem('access_token');

const idTokenEncoded = await routerClient.sessionManager.getSessionItem(
'id_token'
);
const idTokenEncoded =
await routerClient.sessionManager.getSessionItem('id_token');

const accessToken = jwtDecode(accessTokenEncoded);
const accessToken = jwtDecoder<KindeAccessToken>(accessTokenEncoded);

const idToken = jwtDecode(idTokenEncoded);
const idToken = jwtDecoder<KindeIdToken>(idTokenEncoded);

const permissions = await routerClient.kindeClient.getClaimValue(
routerClient.sessionManager,
Expand Down
10 changes: 5 additions & 5 deletions src/session/getUser.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import jwtDecode from 'jwt-decode';
import {NextApiRequest, NextApiResponse} from 'next';
import {KindeAccessToken, KindeIdToken, KindeUser} from '../../types';
import {config} from '../config/index';
import {generateUserObject} from '../utils/generateUserObject';
import {sessionManager} from './sessionManager';
import {jwtDecoder} from '@kinde/jwt-decoder';

export const getUserFactory =
(req: NextApiRequest, res: NextApiResponse) =>
async <T = Record<string, any>>(): Promise<KindeUser<T>> => {
try {
const idToken = jwtDecode(
const idToken = jwtDecoder<KindeIdToken>(
(await sessionManager(req, res).getSessionItem('id_token')) as string
) as KindeIdToken;
);

const accessToken = jwtDecode(
const accessToken = jwtDecoder<KindeAccessToken>(
(await sessionManager(req, res).getSessionItem(
'access_token'
)) as string
) as KindeAccessToken;
);
return generateUserObject(idToken, accessToken) as KindeUser<T>;
} catch (error) {
if (config.isDebugMode) {
Expand Down
9 changes: 8 additions & 1 deletion src/session/isAuthenticated.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import {isTokenValid} from '../utils/pageRouter/isTokenValid';
import {getUserFactory} from './getUser';

/**
Expand All @@ -7,6 +8,12 @@ import {getUserFactory} from './getUser';
* @returns {() => Promise<boolean>}
*/
export const isAuthenticatedFactory = (req, res) => async () => {
const accessToken = await sessionManager(req, res).getSessionItem(
'access_token'
);

const validToken = isTokenValid(accessToken);

const user = await getUserFactory(req, res)();
return Boolean(user);
return validToken && Boolean(user);
};
6 changes: 3 additions & 3 deletions src/utils/pageRouter/isTokenValid.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import jwt_decode from 'jwt-decode';
import {jwtDecoder, TokenPart} from '@kinde/jwt-decoder';
import {config} from '../../config/index';

const isTokenValid = (token) => {
const accessToken = (token && token.access_token) || token;
if (!accessToken) return false;

const accessTokenHeader = jwt_decode(accessToken, {header: true});
const accessTokenPayload = jwt_decode(accessToken);
const accessTokenHeader = jwtDecoder(accessToken, TokenPart.header);
const accessTokenPayload = jwtDecoder(accessToken);
let isAudienceValid = true;
if (config.audience)
isAudienceValid =
Expand Down

0 comments on commit c3e89c6

Please sign in to comment.