Next-auth: Authentication on subdirectory

Created on 29 Jul 2020  路  14Comments  路  Source: nextauthjs/next-auth

Your question(s)
Is it possible to setup authentication of a single app on a subdirectory of a domain? I am having trouble getting next-auth to play nice with nextjs's ability to customize an app's basepath (before the recent update to nextjs 9.5 and after the update to 9.5).

What are you trying to do
Hello. I am working on authentication for an app on a subdirectory of a domain like https://mydomain.com/myapp. I hadn't gotten it working quite right yet and I suspect it is because of something weird going on with having my app have a custom basePath in production since it works fine in my dev environment running off of localhost:300 (I can't seem to get a non null session back at: https://mydomain.com/myapp/api/auth/session even after returning a user object in the authorize handler of the Credentials provider. Things work fine in development using http://localhost:3000).

Another issue I am having has very recently cropped up after updating to v3 from v2.2. On v3, getSession calls seem to hit: https://mydomain/api/auth/session (even after setting NEXTAUTH_URL=https://mydomain.com/myapp) and gets back 404 responses while on v2.2, getSession calls hit: https://mydomain/myapp/api/auth/session and gets back a null session. Any insight into this?

Documentation feedback
Documentation refers to searching through online documentation, code comments and issue history. The example project refers to next-auth-example.

  • [x] Found the documentation helpful
  • [ ] Found documentation but was incomplete
  • [ ] Could not find relevant documentation
  • [x] Found the example project helpful
  • [ ] Did not find the example project helpful
question stale

Most helpful comment

Hey I just realized what the problem is, it's supported but recently realized the feature isn't documented.

*facepalm*

If you have a custom base path you can specify it client site this way:

import { Provider } from 'next-auth/client'

export default function App ({ Component, pageProps }) => {
  return (
    <Provider session={pageProps.session}
      options={{
        basePath: `/custom-app/api/auth`
      }}>
      <Component {...pageProps} />
    </Provider>
  )
}

You can absolute do what @zrrrzzt suggested (the client is happy to pick it up that way too).

Many thanks to folks contributing to this thread.

We'll need to update the docs.

All 14 comments

Hi there! Thanks for the detailed question and context.

This isn't something we had time to test with Next.js 9.5 as NextAuth.js 3.0 released the same day, so there might well be a bug here. The configuration you have sounds right, and I would expect that to work.

Hey, thanks for the response! I'll get you that info below.

A couple things I should mention maybe first:

  • Results don't seem to change with respect to changing which nextjs version I am using (v9.4 or v9.5) but I have still included Next v9.5 results after the results of using Next v9.4 for reference. Regardless of Next version, on Next Auth v3, getSession calls seem to hit: https://mydomain/api/auth/session (even after setting NEXTAUTH_URL=https://mydomain.com/myapp) and gets back 404 responses while on v2.2, getSession calls hit: https://mydomain/myapp/api/auth/session and gets back a null session.

  • I am using Brave Browser

  • I am returning null in authorize handler in Credentials if no user (login fail)

  • I am using custom pages object in [...nextauth].js for my own sign in page (I make sure to use camel case on v3.0.1, signIn: )

  • process.env.SITE: https://mydomain.com and process.env.BASE_PATH: /myapp

  • Since we use NEXTAUTH_URL: on v3.0.1, I've commented out site: process.env.SITE + process.env.BASE_PATH and baseUrl: process.env.BASE_PATH + "/api/auth" in the Provider options object on the _app.js page and also I've commented out site: process.env.SITE + process.env.BASE_PATH and basePath: process.env.BASE_PATH + "/api/auth" in options object on [...nextauth].js as well as.

  • For these particular cases below on v2.2, I am using exactly those site: options in _app.js and [...nextauth].js above uncommented with the baseUrl/basePath commented out although in the past I have tried various combinations of site and baseUrl/basePath options out of desperation to no avail and any baseUrl/basePath options changes didn't seem to have any effect for me on v2.2.

Next: v9.4.4 Next Auth: v3.0.1

  • https://mydomain.com/myapp/api/auth/signin
    Redirects to my custom sign in page as expected. I can submit correct or incorrect credentials that will show these cookies:
    Before
    image
    After
    image

  • https://mydomain.com/myapp/api/callback/credentials
    Form posts to this endpoint with correct credentials (a user object is returned in authorize handler) takes a second and returns a response code of 503. Incorrect credentials results in the login page being displayed again with a url of: https://mydomain.com/myapp/?callbackUrl=https://mydomain.com&error=CredentialsSignin when I expected the unbranded error page to show.

  • https://mydomain.com/myapp/api/auth/csrf
    I receive a csrf token back

  • https://mydomain.com/myapp/api/auth/providers
    i receive object with my credentials provider info

Next: v9.4.4 Next Auth: v2.2

I am not sure under what conditions, but I was able to get user data to load and https://mydomain.com/myapp/api/auth/session returned a session.
Some time after navigating to https://mydomain.com/myapp/api/auth/session, I navigated back in my browser to https://mydomain.com/myapp where I saw user data instead of login form. Unfortunately, I have not been able to get this to happen again.

  • https://mydomain.com/myapp/api/auth/signin
    Redirects to my custom sign in page as expected. These are the cookies before and after submitting correct credentials (incorrect credentials redirects to unbranded sign in error page as expected):
    Before
    image
    After
    imagem

  • https://mydomain.com/myapp/api/callback/credentials
    Form posts to this endpoint with correct credentials (a user object is returned in authorize handler) returns a 302 response and redirects to the correct page but login form (as expected when no session is returned) is displayed instead of user data, https://mydomain.com/myapp/api/auth/session returns empty session. Incorrect credentials redirects to unbranded sign in error page as expected.

  • https://mydomain.com/myapp/api/auth/csrf
    I receive a csrf token back

  • https://mydomain.com/myapp/api/auth/providers
    i receive object with my credentials provider info

Next: v9.5 Next Auth: v2.2 (results are similar to Next: v9.4 Next Auth: v2.2 case)

  • https://mydomain.com/myapp/api/auth/signin
    Redirects to my custom sign in page as expected. These are the cookies before and after submitting correct credentials (incorrect credentials redirects to unbranded sign in error page as expected):
    Before
    image
    After
    image

  • https://mydomain.com/myapp/api/callback/credentials
    Form posts to this endpoint with correct credentials (a user object is returned in authorize handler) returns a 302 response and redirects to the correct page but login form (as expected when no session is returned) is displayed instead of user data, https://mydomain.com/myapp/api/auth/session returns empty session. Incorrect credentials redirects to unbranded sign in error page as expected.

  • https://mydomain.com/myapp/api/auth/csrf
    I receive a csrf token back

  • https://mydomain.com/myapp/api/auth/providers
    i receive object with my credentials provider info

Next: v9.5 Next Auth: v3.0.1 (results are similar to Next: v9.4 Next Auth: v3.0.1 case)

  • https://mydomain.com/myapp/api/auth/signin
    Redirects to my custom sign in page as expected. I can submit correct or incorrect credentials that will show these cookies:
    Before
    image
    After
    image

  • https://mydomain.com/myapp/api/callback/credentials
    Form posts to this endpoint with correct credentials (a user object is returned in authorize handler) takes a second and returns a response code of 503. Incorrect credentials results in the login page being displayed again with a url of: https://mydomain.com/myapp/?callbackUrl=https://mydomain.com&error=CredentialsSignin when I expected the unbranded error page to show.

  • https://mydomain.com/myapp/api/auth/csrf
    I receive a csrf token back

  • https://mydomain.com/myapp/api/auth/providers
    i receive object with my credentials provider info

Apologies if these pictures aren't sufficient for showing the cookies. If there is a preferred way, I can get them to you in that manner. Also, I am just now figuring out how to add images so if taking a look at code snippets can help, I'll gladly provide. Thanks in advance for your help and time!

EDIT 2: Cloudflare was the issue on Next Auth v2.2 (see EDIT 1 below). The issue I had with Next Auth v3.0.1 remains

So I cleared cookies and rolled my production deployment to Next v9.5 and Next Auth v2.2 and began going over and proof reading my post above. Afterwards, I went back to my app and logged in and immediately got back user data and a session, https://webdeveloperbeau.com/recipemanager/api/auth/session returns a user session. I could navigate the site as well and the session remained. Here are the cookies the browser had at the time:

image

I signed out and cleared cookies just in case. Upon trying to sign in again, I don't get user data back and https://webdeveloperbeau.com/recipemanager/api/auth/session returns an empty session. So it seems to sometimes work but I don't know why?

EDIT 1: Okay, I am almost sure my CDN cloudflare is causing the problem of getting back a session on Next Auth v2.2. When I manually clear cookies, purge my cloudflare cache, and then finally wait 30 seconds for cloudlfare to purge to take effect, I can sign in and get back user data and a session! Taking a closer look, it looks like a set a page rule on https://mydomain/* to cache EVERYTHING and that was causing conflicts. After deleting that page rule, things work smoothly in production now using Next Auth v2.2.

@JSONJuggler This is incredibly complete, thank you for all the detail.

I'm going to come back to this and see if there is anything we can write up to help folks out in future.

I'd be interested to know if Next: v9.5 and Next Auth: v3.0.1 are playing nicely for you (sorry wasn't quite clear on that; I might just need to re-read the above; I will do that!).

I'm also interested in any recommendations you have for things we could do (e.g. a debug page? better console logs?) that would make debugging something like this easier.

Not a problem @iaincollins, thank you for creating such an awesome tool/library!

I am currently using Next: v9.5 and Next Auth: v2.2 in production
I have not run into any more problems after removing the aggressive Cloudflare caching page rule. (Next: v9.4 and Next Auth: v2.2 also worked well in production after removing the page rule)

I tried Next: v9.5 and Next Auth: v3.0.1 in production and still had issues after removing aggressive Cloudflare caching
On v3.0.1, my getSession() calls seemed to hit https://mydomain/api/auth/session (even after setting NEXTAUTH_URL=https://mydomain.com/myapp/api/auth) and gets back 404 responses while on v2.2, getSession() calls hit: https://mydomain/myapp/api/auth/session and gets the session back as a response (or null if user is not logged in).

Also on v3.0.1, incorrect credentials results in the login page being displayed again with a url of: https://mydomain.com/myapp/?callbackUrl=https://mydomain.com&error=CredentialsSignin when I expected the unbranded error page to show.

Recommendations
I don't feel the most comfortable giving recommendations because I'm still a newbie and I am also not sure exactly why Cloudflare's aggressive caching was behind the problem I was having on Next Auth v2.2 but if it is possible and makes sense to do so, I think it would be helpful to log a session's return status with an error message if it isn't returned (e.g. no user logged in/missing data from cookies/duplicate cookies or something?), maybe when hitting "/api/auth/session"

Correction: In all my above posts, NEXTAUTH_URL= https://mydomain.com/myapp/api/auth

Also forgot to mention (incase this helps)
On Next Auth v3.0.1, there are no errors present in my Heroku logs when NEXTAUTH_URL= https://mydomain.com/myapp/api/auth. I purposefully changed NEXTAUTH_URL to something nonsensical ( pi/auth in the following case ) and noticed these logs from Heroku:
image

And then i tried NEXTAUTH_URL= https://mydomain.com/myapp and these were the logs from Heroku:
image

In both of the above cases on Next Auth v3.0.1, browser network tab looked the same:
image

Browser network tab on Next Auth v2.2
image

Thank you, that's super useful!

To confirm, NEXTAUTH_URL=https://mydomain.com/myapp/api/auth should be working.

I assume https://mydomain.com/myapp/api/auth/providers returns a response.

I'll have a go at creating an app like this that uses Next.js 9.5 and see if I can replicate! Will keep you updated.

Thanks again for all the info you've provided.

Any update on this - facing the same issue with nextJS 9.5 and next-auth 3.1.0

It seems to ignore my custom basePath and request auth from /api/auth/session instead of /mypath/api/auth/session despite it being set explicitly in NEXTAUTH_URL=https://mydomain.com/myapp/api/auth

To replicate the problem with basePath just clone the example repo and add a next.config.js containing

module.exports = {
  basePath: '/myapp'
}

and a .env with NEXTAUTH_URL=http://localhost:3000/myapp/api/auth

The app will show the frontpage at http://localhost:3000/myapp and http://localhost:3000/myapp/api/auth/signin will take you to the signin page. But if you look in the dev tools network next-auth will do calls to http://localhost:3000/api/auth/session and get a 404


Server side everything looks ok. If you console logs __NEXTAUTH and _apiUrl

{
  baseUrl: 'http://localhost:3000',
  basePath: '/myapp/api/auth',
  keepAlive: 0,
  clientMaxAge: 0,
  _clientLastSync: 0,
  _clientSyncTimer: null,
  _eventListenersAdded: false,
  _clientSession: undefined,
  _clientId: 'bvip9uf3dxukfoco1ao',
  _getSession: [Function: _getSession]
}
http://localhost:3000/myapp/api/auth

Client side this is the result

{baseUrl: "http://localhost:3000", basePath: "/api/auth", keepAlive: 0, clientMaxAge: 0, _clientLastSync: 0,聽鈥
/api/auth

By adding a NEXT_PUBLIC_NEXTAUTH_URL to the mix and changing

  var __NEXTAUTH = {
    baseUrl: (0, _parseUrl.default)(process.env.NEXTAUTH_URL || process.env.NEXT_PUBLIC_NEXTAUTH_URL || 
    process.env.VERCEL_URL).baseUrl,
    basePath: (0, _parseUrl.default)(process.env.NEXTAUTH_URL || process.env.NEXT_PUBLIC_NEXTAUTH_URL).basePath,
    keepAlive: 0,
    clientMaxAge: 0,
    _clientLastSync: 0,
    _clientSyncTimer: null,
    _eventListenersAdded: false,
    _clientSession: undefined,
    _clientId: Math.random().toString(36).substring(2) + Date.now().toString(36),
   _getSession: () => {}
}

It looks like everything works as wanted clientside as well.


The best option would probably be to use NEXT_PUBLIC_NEXTAUTH_URL instead of NEXTAUTH_URL. All NEXT_PUBLIC_ envs are available clientside as well. That would however be a breaking change so I guess supporting both is a smoother start.

Hey I just realized what the problem is, it's supported but recently realized the feature isn't documented.

*facepalm*

If you have a custom base path you can specify it client site this way:

import { Provider } from 'next-auth/client'

export default function App ({ Component, pageProps }) => {
  return (
    <Provider session={pageProps.session}
      options={{
        basePath: `/custom-app/api/auth`
      }}>
      <Component {...pageProps} />
    </Provider>
  )
}

You can absolute do what @zrrrzzt suggested (the client is happy to pick it up that way too).

Many thanks to folks contributing to this thread.

We'll need to update the docs.

Sorry, forgot to mention that I tested the undocumented basePath i the Provider options yesterday.
Unfortunately that will not solve the problem. I did not research why, but it does not show up in the logs for either server nor client.

double sorry :-)

I did not set the basePath the whole way down to the auth folder.

Just re-read your comment @iaincollins and with the full path in Provider.options everything seems okay.

Hi there! It looks like this issue hasn't had any activity for a while. It will be closed if no further activity occurs. If you think your issue is still relevant, feel free to comment on it to keep ot open. Thanks!

Hi there! It looks like this issue hasn't had any activity for a while. To keep things tidy, I am going to close this issue for now. If you think your issue is still relevant, just leave a comment and I will reopen it. (Read more at #912) Thanks!

Was this page helpful?
0 / 5 - 0 ratings