Git Product home page Git Product logo

Comments (6)

iaincollins avatar iaincollins commented on May 4, 2024

Great question! The nextjs-starter project actually does this.

The simplest way to do it is to not pass a port to NextAuth, in which case you can use the instance of Express it returns and then set the Next.js routing behaviour and start Express listening after you have added your custom routes:

'use strict'

const next = require('next')
const nextAuth = require('next-auth')
const nextAuthConfig = require('./next-auth.config')

const nextApp = next({
  dir: '.',
  dev: (process.env.NODE_ENV === 'development')
})

nextApp
.prepare()
.then(() => {
  return nextAuthConfig()
})
.then(nextAuthOptions => {
  // Don't pass a port to NextAuth!
  if (nextAuthOptions.port) delete nextAuthOptions.port

  return nextAuth(nextApp, nextAuthOptions)
})
.then(nextAuthApp => {

  // Get instance of Express from NextAuth instance
  const express = nextAuthApp.express

  // Configure additional routes here
  express.use("/api/v1/users", users);
  
  // Default catch-all handler to allow Next.js to handle all other routes
  express.all('*', (req, res) => {
    let nextRequestHandler = nextApp.getRequestHandler()
    return nextRequestHandler(req, res)
  })

  express.listen(process.env.PORT, err => {
    if (err) throw err
    console.log('> Ready on http://localhost:' + process.env.PORT)
  })
})
.catch(err => {
  console.log('An error occurred, unable to start the server')
  console.log(err)
})

If you want to do stuff with Express before you call NextAuth, you can also pass an Express instance to it, which it will use if passed:

'use strict'

const next = require('next')
const nextAuth = require('next-auth')
const nextAuthConfig = require('./next-auth.config')

// You can define a your own Express instance here and do stuff before passing
// it to NextAuth if you want
const express = require('express')
const expressApp = express()

const nextApp = next({
  dir: '.',
  dev: (process.env.NODE_ENV === 'development')
})

nextApp
.prepare()
.then(() => {
  return nextAuthConfig()
})
.then(nextAuthOptions => {

  // Pass your own Express instance to NextAuth - and don't pass a port!
  if (nextAuthOptions.port) delete nextAuthOptions.port
  nextAuthOptions.expressApp = expressApp

  nextAuth(nextApp, nextAuthOptions)
  
  // Configure additional routes here
  expressApp.use("/api/v1/users", users);
  
  // Default catch-all handler to allow Next.js to handle all other routes
  expressApp.all('*', (req, res) => {
    let nextRequestHandler = nextApp.getRequestHandler()
    return nextRequestHandler(req, res)
  })

  expressApp.listen(process.env.PORT, err => {
    if (err) throw err
    console.log('> Ready on http://localhost:' + process.env.PORT)
  })
})
.catch(err => {
  console.log('An error occurred, unable to start the server')
  console.log(err)
})

from next-auth.

iaincollins avatar iaincollins commented on May 4, 2024

Have updated my response to fix a typo.

Feel free to re-open this issue if it's not resolved for you!

from next-auth.

 avatar commented on May 4, 2024

Hi,

I tried this but when I make a request to the API route from getInitialProps it initializes a new session in the session store. Is there anything I can do to prevent that?

from next-auth.

iaincollins avatar iaincollins commented on May 4, 2024

Great question!

Client Side HTTP Calls

If happening on the client side, it is probably happening because you are not sending session cookies with your AJAX request so the server doesn't see that you already have a session.

Try using fetch (or isomorphic-fetch) with the credentials: 'same-origin' option, which tells the browser to attach the session cookie to the request. Note that the session cookie cannot be read from JavaScript (by design). XMLHttpRequest does this automatically.

fetch('/api/my-endpoint', {
  credentials: 'same-origin'
})
.then(response => {
   // …
})

Server Side HTTP Calls

If it is happening when you make calls to an HTTP endpoint from code running server side that's a bit of a different story. Code running server side will of course not have a session cookie (as the cookie lives on the client only).

There is actually a pull request #23 from @rmcalvert addresses the fact that new sessions get created automatically by default and - when I'm back off my holiday early next month I plan on merging it in.

So, you will automatically stop seeing this behaviour in a future update, as sessions will only be created when you users log in (and nothing will be saved until then). This is better than the more classic session behaviour, which creates a session for every new client it thinks it sees up front (leaving them to be expired if they are never used).

I haven't just merged this update in already as I'm going to switch CSRF over to a different model - as currently it depends on the classic session behaviour. In future the CSRF Token will use the Double Submit Cookie method to continue to provide Cross Site Request Forgery protection (which is equally secure, but works differently and is more lightweight).

Supporting Isomorphic Calls That Need Authentication

If you need to be able to make authenticated calls from both the client and the server, you can pass the req object from getInitialProps({req}) your function and you can use that when running server side to handle authentication in your function.

I don't want to go into it unless it's useful, but happy to provide a fuller explanation / example of it if it's relevant to what you want to do.

from next-auth.

webbygregg avatar webbygregg commented on May 4, 2024

Would love to see an authentication example, if possible.

I tried using your code above and received a "express.all is not a function" error. in the first one and a "nextApp.getRequestHandler() is not a function" in the second

from next-auth.

ericadamski avatar ericadamski commented on May 4, 2024

Supporting Isomorphic Calls That Need Authentication
If you need to be able to make authenticated calls from both the client and the server, you can pass the req object from getInitialProps({req}) your function and you can use that when running server side to handle authentication in your function.

I don't want to go into it unless it's useful, but happy to provide a fuller explanation / example of it if it's relevant to what you want to do.
#8 (comment)

Do you mind giving an example? This would be super helpful!

from next-auth.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.