question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItĀ collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Recommended approach to share session information between applications on subdomains

See original GitHub issue

Question šŸ’¬

Hello! First of all, thanks for all the great work on this amazing library!

I’m trying to implement a solution in which i have the same authentication on subdomains as well as on main domain. What is the recommended approach to share session information between all applications?

This is a continuation of a discussion that started on some previous issues, like #405, #794, #1668. All those issues are now closed without a full example or definitive answer, so i decided to make a summary of what was previously discussed, in hope that i can get some help on deciding what is the best approach to do that integration on all domains and subdomains of my application and help document that approach for others in the same need.

How to reproduce ā˜•ļø

The application i’m working on is, actually, an ecosystem of applications, and not all of them are made with Next.js (or even with React). Many are legacy applications written in JSP.

The main one isn’t an Next.js app and will live in ā€œwww.my-domain.comā€. It will have sub-domains, as in ā€œapp1.my-domain.comā€, ā€œapp2.my-domain.comā€, etc. As explained in the FAQ:

If you are using a different framework for you website, you can create a website that handles sign in with Next.js and then access those sessions on a website that does not use Next.js as long as the websites are on the same domain.

If you use NextAuth.js on a website with a different subdomain then the rest of your website (e.g. auth.example.com vs www.example.com) you will need to set a custom cookie domain policy for the Session Token cookie.

So, since the main application isn’t a React / Next.js app, I will have to implement an auth application so i can use NextAuth: ā€œauth.my-domain.comā€. Notice that it’s the ONLY application that includes NextAuth - from my understanding, it makes no sence to add NextAuth to all my other Next.js applications.

I created a diagram to help illustrate the ecosystem:

image

To set a custom cookie domain policy for the Session Token cookie, i did in my […nextauth] API route what was originally posted by @Xodarap in https://github.com/nextauthjs/next-auth/issues/405#issuecomment-737593528:

const useSecureCookies = process.env.NEXTAUTH_URL.startsWith('https://')
const cookiePrefix = useSecureCookies ? '__Secure-' : ''
const hostName = Url(process.env.NEXTAUTH_URL).hostname
const options = {
  cookies: {
    sessionToken: 
    {
      name: `${cookiePrefix}next-auth.session-token`,
      options: {
        httpOnly: true,
        sameSite: 'lax',
        path: '/',
        secure: useSecureCookies,
        domain: hostName == 'localhost' ? hostName : '.' + hostName // add a . in front so that subdomains are included
      }
    },
  },
}

Doing like that, i was successfully able to access the cookie ā€œ__Secure-next-auth.session-tokenā€, created by ā€œauth.my-domain.comā€ and set in the domain ā€œ.my-domain.comā€, in all my other applications.

@iaincollins said in https://github.com/nextauthjs/next-auth/issues/405#issuecomment-737814371 that he was evaluating ways to make that configuration easier, but the issue #405 was closed because of inactivity.

As @iaincollins explained in https://github.com/nextauthjs/next-auth/issues/417#issuecomment-656606639:

Session Tokens are typically stored in cookies. To best protect against session hijacking (e.g. from third party JavaScript in advertising, tracking, browser extensions, XSS) these should be server only readable cookies that are not accessible directly from JavaScript. This is the model NextAuth.js uses.

If a user is signed in, any request from the client will have a secure, sever only readable cookie set that can be used to either look up a session in a database (if it is a database session token) or decoded and verified (if it is a JSON Web Token) to identify the user.

Using server readable only cookies is secure without a CSRF token.

So in regards to the protection needed to secure my backend all is done: the backend will receive the cookies together with the requests made by the frontend and decode and verify the identity of the user.

What i still don’t know is what is the best approach to sharing the session information between all the frontend applications. Should i just read the information in the cookie in each of my applications? Because, doing like that, the cookie lifespam won’t be increased, like happens when i access the ā€œsessionā€ endpoint or the ā€œuseSessionā€ / ā€œgetSessionā€ client. For example:

https://github.com/nextauthjs/next-auth/blob/75ca097ff7585016264f4c6848e58da74c77aaf8/src/server/routes/session.js#L58-L62

@iaincollins posted in https://github.com/nextauthjs/next-auth/issues/796#issuecomment-718765049 a quite great explanation of the challanges of defining the maxAge of the JWT. I quote:

By default, a Next.js Single Page App using NextAuth.js will load session once and on subsequent page transitions, the useSession hook will reuse the response it already has.

However, the app wide session state WILL be updated in the SPA if the window loses/regains focus or if the user logs out in another window in the same browser (it uses event hooks to do this) OR anytime you call getSession() in your app. This makes Single Page Apps efficient by default - they don’t check your session on every page navigation, which keeps network traffic down and page responses snappy - but keeps the session state from getting stale by instead re-validating when a page gains focus again.

So i think it would be of great loss if we don’t access the session via the ā€œsessionā€ endpoint and, as a result, lose on that great functionality provided by NextAuth.

The problem: As @subhendukundu commented in https://github.com/nextauthjs/next-auth/issues/794#issuecomment-875620767, i’m also having problens trying to use the endpoints provided by NextAuth on my ā€œauth.my-domain.comā€ (like ā€œhttps://auth.my-domain.com/api/auth/sessionā€) application.

First, i was getting CORS related errors when i tried to consume the endpoints. About those, i get that may be related to the way Next.js protects it’s API routes, but i think it is usefull to document the solution here, since it will be a mandatory step for the solution to work. I followed the guide provided in the Vercel documentation and in the Next.js documentation - in the ā€œnext.config.jsā€ file, i created a ā€œheadersā€ function:

// next.config.js
// NEXT_PUBLIC_ENV is an environment variable defined on my .env, with values 'development', 'staging' or 'production' in the respective environments.
module.exports = {
  async headers() {
    // To help with local development...
    if (process.env.NEXT_PUBLIC_ENV === 'development') {
      return [
        {
          source: "/api/auth/:path*",
          headers: [
            { key: 'Access-Control-Allow-Credentials', value: 'true' },
            { key: 'Access-Control-Allow-Origin', value: '*' },
            { key: 'Access-Control-Allow-Methods', value: 'GET, OPTIONS, PATCH, DELETE, POST, PUT' },
            { key: 'Access-Control-Allow-Headers', value: 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version' },
          ],
        },
      ];
    }

    // In the other environments...
    return [
      // https://vercel.com/support/articles/how-to-enable-cors#enabling-cors-in-a-next.js-app
      // https://nextjs.org/docs/api-reference/next.config.js/headers#header-cookie-and-query-matching
      {
        // matching all auth API routes
        source: "/api/auth/:path*",
         // if the origin has '.my-domain.com'...
        has: [
          { type: 'header', key: 'Origin', value: '(?<serviceName>^https:\/\/.*\.my-domain\.com$)' },
        ],
        // these headers will be applied
        headers: [
          { key: 'Access-Control-Allow-Credentials', value: 'true' },
          { key: 'Access-Control-Allow-Origin', value: '*' },
          { key: 'Access-Control-Allow-Methods', value: 'GET, OPTIONS, PATCH, DELETE, POST, PUT' },
          { key: 'Access-Control-Allow-Headers', value: 'X-CSRF-Token, X-Requested-With, Accept, Accept-Version, Content-Length, Content-MD5, Content-Type, Date, X-Api-Version' },
        ],
      },
    ];
  }
};

(edit: the code i previously posted to configure CORS was wrong (i was checking the host of the request, and the correct way to do that is checking the ā€œOriginā€ header). With that configuration, my applications on my subdomains can access the auth endpoints from my ā€œhttps://auth.my-domain.comā€, and it still keeps protected from access made from other domains.

I’m using ā€œfetchā€ to get the data from the ā€œhttps://auth.my-domain.com/api/auth/sessionā€ endpoint. Something like that:

const a = await fetch('https://auth.my-domain.com/api/auth/session');
const b = await a.json();
// b will have the session information

If i do that fetch inside my ā€œauth.my-domain.comā€ application, it works as expected, bringing the session information. The problem is that, if i try to do that same fetch from my ā€œapp2.my-domain.comā€, for example, i don’t receive the session information, only an empty object ({}). Why is that happening? Did i do something wrong?

Also, despite all the references i provided, i still don’t know if that is the recommended approach to share the session information between my applications.

Thanks in advance!

Documentation feedback

  • Found the documentation helpful
  • Found documentation but was incomplete
  • Could not find relevant documentation
  • Found the example project helpful
  • Did not find the example project helpful

Contributing šŸ™ŒšŸ½

Yes, I am willing to help answer this question in a PR

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Reactions:6
  • Comments:23 (3 by maintainers)

github_iconTop GitHub Comments

12reactions
raphaelpccommented, Sep 27, 2021

My system using the NextAuth login implementation goes into production next week or the other, wish me luck kkk After that, i hope to make a guide of the configs i had to do to get all working (i only had to use patch-package do resolve proxy issues i was having inside my corporate proxy, but everything else i was able to accomplish with the NextAuth configuration only).

3reactions
zomarscommented, Jan 4, 2022

A minimal reproduction example would be nice 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

Sharing session between 2 web apps on different subdomains
The only way to access app2 is from app1, so I'm looking for a way to have the users being automatically authenticated on...
Read more >
Cross-Origin Web Sessions
Using the query parameters approach is a simple and effective way to transfer credentials from one domain to another. The server generates aĀ ......
Read more >
Maintaining session between main domain and sub domain
If you want to share sessions between domains, you would need to implement some sort of session transfer method when you switch domains....
Read more >
Sharing session between multiple subdomains - Stack Overflow
To share sessions across sub-domains, you need to configure two things. You need the proper cookie settings for the session cookie so thatĀ ......
Read more >
Session sharing - Sharing login state between web apps
In this post I explain how you can session sharing is done between web apps on the same domain and subdomain using Node.js,...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found