title: Verify JWT token in Next.js middleware throws Module not found: Can't resolve 'crypto' error
body: <p>I'm trying to use JWT verification for authentication with middleware, but unfortunately, I'm getting some errors that cannot find a solution for.</p>
  <pre class="lang-errors prettyprint-override"><code>./node_modules/jwa/index.js:3:0
  Module not found: Can't resolve 'crypto'
  
  Import trace for requested module:
  ./node_modules/jws/lib/sign-stream.js
  ./node_modules/jws/index.js
  ./node_modules/jsonwebtoken/verify.js
  ./middleware.ts
  
  https://nextjs.org/docs/messages/module-not-found
  
  You're using a Node.js module (crypto) which is not supported in the Edge Runtime.
  Learn more: https://nextjs.org/docs/api-reference/edge-runtime
  </code></pre>
  <p><strong>package.json</strong></p>
  <pre class="lang-json prettyprint-override"><code>{
    &quot;scripts&quot;: {
      &quot;dev&quot;: &quot;next dev&quot;,
      &quot;build&quot;: &quot;next build&quot;,
      &quot;start&quot;: &quot;next start&quot;,
      &quot;lint&quot;: &quot;next lint&quot;
    },
    &quot;dependencies&quot;: {
      &quot;@emotion/react&quot;: &quot;^11.9.3&quot;,
      &quot;@emotion/styled&quot;: &quot;^11.9.3&quot;,
      &quot;@mui/material&quot;: &quot;^5.8.6&quot;,
      &quot;@prisma/client&quot;: &quot;^4.0.0&quot;,
      &quot;axios&quot;: &quot;^0.27.2&quot;,
      &quot;buffer&quot;: &quot;^6.0.3&quot;,
      &quot;cookie&quot;: &quot;^0.5.0&quot;,
      &quot;jsonwebtoken&quot;: &quot;^8.5.1&quot;,
      &quot;next&quot;: &quot;12.2.0&quot;,
      &quot;react&quot;: &quot;18.2.0&quot;,
      &quot;react-dom&quot;: &quot;18.2.0&quot;,
      &quot;react-hook-form&quot;: &quot;^7.33.0&quot;
    },
    &quot;devDependencies&quot;: {
      &quot;@types/node&quot;: &quot;18.0.0&quot;,
      &quot;@types/react&quot;: &quot;18.0.14&quot;,
      &quot;@types/react-dom&quot;: &quot;18.0.5&quot;,
      &quot;eslint&quot;: &quot;8.18.0&quot;,
      &quot;eslint-config-next&quot;: &quot;12.2.0&quot;,
      &quot;prisma&quot;: &quot;^4.0.0&quot;,
      &quot;typescript&quot;: &quot;4.7.4&quot;
    }
  }
  </code></pre>
  <p><strong>middleware.ts</strong></p>
  <pre><code>import { NextResponse } from &quot;next/server&quot;;
  import verify from &quot;jsonwebtoken/verify&quot;;
  import { urlToHttpOptions } from &quot;url&quot;;
  import type { NextRequest } from 'next/server'
  
  const secret = process.env.SECRET;
  
  export default function middleware(req: NextRequest) {
      const { cookies } = req;
      const { search, protocol, host } = req.nextUrl
  
      const jwt = cookies.OutsiteJWT;
      const url = req.url;
  
      if (url.includes('/dashboard')) {
          if (jwt === undefined) {
              return NextResponse.redirect(&quot;http://localhost:3000/login&quot;);
          }
  
          try {
              verify(jwt, secret); // &lt;---- ERROR COMES FROM HERE
              return NextResponse.next();
          } catch (error) {
              return NextResponse.redirect(&quot;/login&quot;);
          }
      }
  
      return NextResponse.next();
  }
  </code></pre>
  <p><strong>/pages/api/auth/login.ts</strong></p>
  <pre class="lang-ts prettyprint-override"><code>/* eslint-disable import/no-anonymous-default-export */
  import { sign } from &quot;jsonwebtoken&quot;;
  import { serialize } from &quot;cookie&quot;;
  
  const secret = process.env.SECRET;
  
  export default async function (req, res) {
      const { username, password } = req.body;
  
      // Check in the database
      // if a user with this username
      // and password exists
      if (username === &quot;Admin&quot; &amp;&amp; password === &quot;Admin&quot;) {
          const token = sign(
              {
                  exp: Math.floor(Date.now() / 1000) + 60 * 60 * 24 * 30, // 30 days
                  username: username,
              },
              secret
          );
  
          const serialised = serialize(&quot;OursiteJWT&quot;, token, {
              httpOnly: true,
              secure: process.env.NODE_ENV !== &quot;development&quot;,
              sameSite: &quot;strict&quot;,
              maxAge: 60 * 60 * 24 * 30,
              path: &quot;/&quot;,
          });
  
          res.setHeader(&quot;Set-Cookie&quot;, serialised);
  
          res.status(200).json({ message: &quot;Success!&quot; });
      } else {
          res.status(401).json({ message: &quot;Invalid credentials!&quot; });
      }
  }
  </code></pre>
  <p>I've tried commenting out the <em>try/catch</em> to check if the token is set, and it works correctly, but when I try to verify in the middleware it fails.</p>
  <p>In version 12.2.0 the <a href="https://nextjs.org/docs/advanced-features/middleware" rel="nofollow noreferrer">middleware</a> is stable but also has some changes.</p>
  <p>Does somebody else encounter similar issues or know how to solve this?</p>