Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to implement passport with next-connect in Next 14? #244

Open
RicardoNRevs opened this issue Mar 6, 2024 · 1 comment
Open

How to implement passport with next-connect in Next 14? #244

RicardoNRevs opened this issue Mar 6, 2024 · 1 comment

Comments

@RicardoNRevs
Copy link

Hi everyone.
Previously, I've followed this example project https://github.com/vercel/next.js/tree/canary/examples/with-passport-and-next-connect to connect an external SSO with my app and works with this passport configuration without any problem

lib/passport.ts
const __CALLBACK__ = process.env.CALLBACK_URL
const __ENTRY_POINT__ = process.env.ENTRY_POINT
const __ISSUER__ = process.env.ISSUER
const __CERTIFICATE__ = process.env.CERTIFICATE

passport.serializeUser((user, cb) => {
    process.nextTick(function () {
        return cb(null, user);
    });
});
  

passport.deserializeUser(function (req, id, done) {
  // deserialize the username back into user object
  process.nextTick(function () {
    return cb(null, user);
  });
});

passport.use(
    new SAMLStrategy(
        {
            callbackUrl: __CALLBACK__,
            entryPoint: __ENTRY_POINT__,
            issuer: __ISSUER__,
            cert: __CERTIFICATE__
        },
        (profile, done) => {
            return saveUser(profile);
        }
    )
);

const saveUser = (user) => {
    return new Promise((resolve, reject) => {
      resolve("Successful");
    });
};

export default passport;

then I call it in the login API like this

import passport from "@/lib/passport";

const handler = nextConnect();

handler.use(passport .initialize()).get(passport.authenticate("saml"),{});

export default handler;

All this work with "next-connect": "^0.6.1", "passport": "^0.4.1", "passport-saml": "^3.2.4"

Now I'm trying to replicate that in NextJS v14 with "next-connect": "^1.0.0-next.3" but I got the following issue

Error: No response is returned from route handler 'C:\dummy\nextjs-portal-v1\src\app\api\login\route.ts'. Ensure you return a `Response` or a `NextResponse` in all branches of your handler.
    at C:\dummy\nextjs-portal-v1\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:63974
    at async eU.execute (C:\dummy\nextjs-portal-v1\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:53964)
    at async eU.handle (C:\dummy\nextjs-portal-v1\node_modules\next\dist\compiled\next-server\app-route.runtime.dev.js:6:65062)
    at async doRender (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\base-server.js:1333:42)
    at async cacheEntry.responseCache.get.routeKind (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\base-server.js:1555:28)
    at async DevServer.renderToResponseWithComponentsImpl (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\base-server.js:1463:28)
    at async DevServer.renderPageComponent (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\base-server.js:1856:24)
    at async DevServer.renderToResponseImpl (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\base-server.js:1894:32)
    at async DevServer.pipeImpl (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\base-server.js:911:25)
    at async NextNodeServer.handleCatchallRenderRequest (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\next-server.js:271:17)
    at async DevServer.handleRequestImpl (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\base-server.js:807:17)
    at async C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\dev\next-dev-server.js:331:20
    at async Span.traceAsyncFn (C:\dummy\nextjs-portal-v1\node_modules\next\dist\trace\trace.js:151:20)
    at async DevServer.handleRequest (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\dev\next-dev-server.js:328:24)
    at async invokeRender (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\lib\router-server.js:163:21)
    at async handleRequest (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\lib\router-server.js:342:24)
    at async requestHandlerImpl (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\lib\router-server.js:366:13)
    at async Server.requestListener (C:\dummy\nextjs-portal-v1\node_modules\next\dist\server\lib\start-server.js:140:13)

This is the api/login/route.ts file

import { createEdgeRouter } from "next-connect";
import type { NextRequest, NextResponse } from "next/server";

import passport from "@/lib/passport";

const router = createEdgeRouter<NextRequest, { params?: unknown }>();

router.use(passport.initialize() as any)
    .get(
        passport.authenticate("saml", {
            failureRedirect: "/",})
    );

export async function GET(request: NextRequest, ctx: { params?: unknown }) {
    return router.run(request, ctx) as Promise<NextResponse>;
}
      

The @/lib/passport it's almost the same as before

import passport from "passport";
import { Strategy as SAMLStrategy, Profile } from "passport-saml";


const __CALLBACK__ = process.env.CALLBACK_URL
const __ENTRY_POINT__ = process.env.ENTRY_POINT
const __ISSUER__ = process.env.ISSUER
const __CERTIFICATE__ = process.env.CERTIFICATE

passport.serializeUser((user: any, done) => {
    done(null, user);
});

passport.deserializeUser((user: any, done) => {
    done(null, user);
})

passport.use(
    new SAMLStrategy(
    {
        callbackUrl: __CALLBACK__,
        entryPoint: __ENTRY_POINT__,
        issuer: __ISSUER__,
        cert: __CERTIFICATE__ || ''
    }, (profile: Profile | null | undefined, done: (err: Error | null, user?: any) => void) => {
        if (profile) {
            return done(null, profile);
        } else {
            return done(new Error("Invalid profile"));
        }
    })
);
      

export default passport;

Did I miss something when I'm calling the passport implementation?
Thanks for your help

@Keith-Web3
Copy link

@RicardoNRevs, were you able to find a working solution?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants