0

In this moment I authenticate user in each API. I want to add a middleware to do it only once.

So I created a file named _middleware.ts under /pages/api and used the same approach I did for every API.

I have the following code:

_middleware.ts

import { NextApiRequest } from 'next';
import type { NextFetchEvent, NextRequest } from 'next/server';
import { NextResponse } from 'next/server';
import { getUserIdOrFail } from './utils/jwt';

export async function middleware(req: NextRequest, ev: NextFetchEvent) {
  const authToken = req.headers.get('Authorization');
  let userId: string;
  try {
    userId = await getUserIdOrFail({
      headers: { authorization: authToken },
    } as NextApiRequest);
  } catch (err) {
    //return 401
  }

  // here usereId might contain the userId if correctly authenticated

  return NextResponse.next();
}

jwt.ts

import { sign, verify } from 'jsonwebtoken';
import { config } from './config';
import { User } from '../models/user';
import { jwtSchema } from './schemas/jwtSchema';
import { NextApiRequest } from 'next';

export const buildJwt = (user: User) =>
  sign({ id: user._id }, config.JWT_KEY, { expiresIn: config.JWT_EXPIRATION });

export const verifyJwt = <T>(jwt: string) => {
  try {
    return verify(jwt, config.JWT_KEY) as T;
  } catch (e) {
    return null;
  }
};

export async function getUserIdOrFail(req: NextApiRequest) {
  const authorizationHeader = req.headers.authorization;
  if (!authorizationHeader || !authorizationHeader.startsWith('Bearer ')) {
    throw new Error();
  }

  const jwt = authorizationHeader.replace('Bearer ', '');
  const parsed = verifyJwt(jwt);

  const { value, error } = jwtSchema.validate(parsed);
  if (error) {
    throw new Error();
  }

  return value.id as string;
}

Basically with this code I get the bearer token that server gave to the user when he logged in or registered contained into the Authorization header and verify if it is valid. If it is valid I take the userId and use it to do operations with the DB.

The problem is that it does the stuff if I use it in the api files, but in this file it goes into error (catch block with this error). Is it a jsonwebtoken problem? Should I to do it differently? Or should I leave it in the way it actually is?

Loudrous
  • 1,039
  • 10
  • 29

1 Answers1

3

The problem with this approach is that the jasonwebtoken library uses Dynamic code evaluation which is not allowed into the file _middleware.ts in next.js. To solve this need to use another library or do it in the api files.

Loudrous
  • 1,039
  • 10
  • 29