How to implement passport with next-connect in Next 14?
RicardoNRevs opened this issue · comments
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