nextjs-auth0 icon indicating copy to clipboard operation
nextjs-auth0 copied to clipboard

Edge function support

Open andrewscofield opened this issue 4 years ago • 29 comments

Describe the problem you'd like to have solved

Authenticate users at the edge (https://vercel.com/features/edge-functions)

Describe the ideal solution

Middleware function for auth0 to get user object at page render.

andrewscofield avatar Oct 26 '21 21:10 andrewscofield

Thanks for raising this @andrewscofield - will prioritise this with the team

adamjmcgrath avatar Oct 27 '21 11:10 adamjmcgrath

Excited!

mirshko avatar Oct 27 '21 12:10 mirshko

would love to see this

adikari avatar Oct 29 '21 02:10 adikari

I'm looking forward to working with the Edge function!

Incidentally, I bypassed the cookie from the middleware to /api/auth/me using fetch to check the authentication status on the middleware. Requesting the api route from the Edge function is not the right way, as it hurts performance. I am using this approach as an interim one until formal support is in place.

https://github.com/aiji42/next-fortress/blob/main/src/auth0.ts

const verifyAuth0Session = async (
  req: NextRequest,
  apiEndpoint: string
): Promise<boolean> => {
  const res = await fetch(req.nextUrl.origin + '/api/auth/me', {
    headers: { cookie: req.headers.get('cookie') ?? '' }
  })

  return res.ok
}

(I am developing a plugin that uses Next.js middleware to check the authentication status of IDSaaS such as Auth0 and determine whether content is accessible or not. Hope this is helpful to someone. https://github.com/aiji42/next-fortress#control-by-auth0)

aiji42 avatar Nov 09 '21 02:11 aiji42

Would recommend checking https://github.com/vercel/examples/tree/main/edge-functions, particularly https://github.com/vercel/examples/tree/main/edge-functions/jwt-authentication

theMadness avatar Nov 09 '21 20:11 theMadness

Thanks for the recommendation. Yes, I did read it. However, the JWT stored in the cookie handled by nextjs-auth0 does not have a payload and there is only a small amount of information that can be retrieved from the header.

{
  "alg": "RS256",
  "enc": "A256GCM",
  "iat": 1636505290,
  "uat": 1636505291,
  "exp": 1636591691
}

https://community.auth0.com/t/token-in-appsession-cookie-cannot-be-decoded/60591/3

aiji42 avatar Nov 10 '21 01:11 aiji42

Any news about this?

GMaiolo avatar Nov 13 '21 23:11 GMaiolo

Hi @GMaiolo - thanks for checking. No news, we'll update this thread when we do

adamjmcgrath avatar Nov 15 '21 09:11 adamjmcgrath

Hi @adamjmcgrath, could you clarify if this is being currently developed, or if it hasn't started yet? I understand if there aren't any meaningful updates at this point, but it would be nice to have some indication of what is the priority this has internally. Being able to authenticate on the edge would be a game-changer for us, so I am really curious about this :)

paulobarcelos avatar Dec 09 '21 10:12 paulobarcelos

Hi @paulobarcelos - thanks for checking in on this. It's definitely on the roadmap, but it hasn't been started yet. I will update this thread when we make a start on this, probably early next year.

adamjmcgrath avatar Dec 13 '21 12:12 adamjmcgrath

This is much needed for our project as well. Looking forward to hearing a timeline!

duhfrazee avatar Jan 03 '22 16:01 duhfrazee

Same here!

ian97531 avatar Jan 03 '22 17:01 ian97531

I'm building a new app and seriously thinking about integrating auth0 and edge functions are better for user authentication by far.

andrefedev avatar Jan 18 '22 19:01 andrefedev

Really keen to see this land some time

fishactual avatar Apr 14 '22 01:04 fishactual

If anyone is interested, I wrote a middleware that reduces the number situations where the user sees a flash of content before being redirected to authenticate. This flash of content only occurs if you protect a page (or the whole app) using withPageAuthRequired to wrap the page component. If you wrap getServerSideProps the flash doesn't occur. I consider this temporary code that should be removed once a true edge function solution is available. Notice that it depends on AUTH0_BASE_URL being defined in the environment. Modify to suite your needs...

import { NextResponse } from "next/server";
// The sole purpose of this middleware is to reduce the number
// of situations in which the user sees a flash of content
// before being redirected to the IDP to authenticate.
// It DOES NOT verify the auth session in any way.
// It ONLY checks to see if the appSession cookie exists.
// As of [email protected] the "appSession" cookie name is not configurable so it is hard-coded below
export function middleware(req) {
  const appSessionCookieExists = req.cookies["appSession"] ? true : false;
  const { pathname, href } = req.nextUrl;
  if (appSessionCookieExists || pathname.startsWith("/api/")) {
    return NextResponse.next();
  } else {
    return NextResponse.redirect(
      `${process.env.AUTH0_BASE_URL}/api/auth/login?returnTo=${href}`
    );
  }
}

eatrocks avatar Apr 15 '22 17:04 eatrocks

Any roadmap updates on this? We just started building a Next.js/Auth0 app and would very much like to use this feature!

brianarpie-forme avatar Apr 28 '22 14:04 brianarpie-forme

No roadmap updates I'm afraid @brianarpie-forme - will update this thread when we start looking at this

adamjmcgrath avatar May 03 '22 10:05 adamjmcgrath

@eatrocks Thanks for the sharing the sample, I expanded the code a bit to work with the scenario if you are using more than 1 authSession.


import { NextResponse } from "next/server";
// Based on https://github.com/auth0/nextjs-auth0/issues/525#issuecomment-1100255629
// The sole purpose of this middleware is to reduce the number
// of situations in which the user sees a flash of content
// before being redirected to the IDP to authenticate.
// It DOES NOT verify the auth session in any way.
// It ONLY checks to see if the appSession cookie exists.
// As of [email protected] the "appSession" cookie name is not configurable so it is hard-coded below
export function middleware(req) {

  // Handles if you have appSession.1, appSession.0 and so-on
  const appSessionCookieExists = Object.keys(req.cookies).some(cookieName => cookieName.startsWith('appSession'));
  const { pathname, href } = req.nextUrl;

  if (appSessionCookieExists || pathname.startsWith("/api/")) {
    return NextResponse.next();
  } else {
    return NextResponse.redirect(
      `${process.env.AUTH0_BASE_URL}/api/auth/login?returnTo=${href}`
    );
  }
}

kanalo-shrek avatar May 10 '22 21:05 kanalo-shrek

I have a proof of concept for this (validated locally): https://gist.github.com/alexjtupper/b3a03277fde07797785072a1d0d0727d

This approach decrypts the JWE and returns the contents (including user details), all within the Edge Runtime (using the SubtleCrypto interface) - so you can use it for middleware!

This is very much an early version, and doesn't handle:

  • multiple appSession.{} cookies
  • multiple auth0 secrets
  • validating the JWE header (part of the process in the jose.JWA.decrypt process that @auth0-nextjs uses)
  • Any other auth configuration for your auth0 application than the vanilla configuration I’m using :)

alexjtupper avatar May 19 '22 13:05 alexjtupper

Wow! Very cool @alexjtupper, as I understand it your work makes it possible to session tasks on the middleware, except for redirect to login etc?

kanalo-shrek avatar May 19 '22 13:05 kanalo-shrek

Wow! Very cool @alexjtupper, as I understand it your work makes it possible to session tasks on the middleware, except for redirect to login etc?

It decrypts the session so you have access to the usual session data: { nickname: '...', name: '...', picture: '...', updated_at: '...', email: '...', email_verified: false, sub: 'auth0|...' }

I assume you can then safely make an authentication / authorisation decision. If you attempted to get the session using the getSession function in the gist I linked, and it resolved to null, you could return a redirect from the middleware so the user is forced to login just like @eatrocks did in their example

alexjtupper avatar May 19 '22 15:05 alexjtupper

@alexjtupper Very cool! Any thoughts of using the middleware to inject Authorisation Header into requests that we make to external APIs?

Currently I have this proxy API route that handles all client side fetches to external api, and we inject the auth header in there.

What I would like to do instead, using Next's rewrite config to fix issues with CORS and then use perhaps middleware to inject the required auth header into the fetch request. Is this possible?

patrykmaron avatar May 20 '22 11:05 patrykmaron

It might be worth having a think about the the new RFC the team at Next has created and where this library may sit within that proposal.

https://nextjs.org/blog/layouts-rfc

I am finding that this library is not ideal for complex apps with roles and where you need to control access to pages without making a lot of getServerSideProps calls.

It'd be great to be able to define this stuff as middleware.

fishactual avatar Jun 02 '22 07:06 fishactual

I guess no updates yet?

surajmandalcell avatar Jun 23 '22 20:06 surajmandalcell

Nope. I am switching a large enterprise app out to next-auth. The team over there seems more receptive to suggestions and familiar with what is happening in the Next.js community. No offence intended! This library has been useful.

fishactual avatar Aug 08 '22 22:08 fishactual

Nope. I am switching a large enterprise app out to next-auth. The team over there seems more receptive to suggestions and familiar with what is happening in the Next.js community. No offence intended! This library has been useful.

The same situation on my end, sadly.

GMaiolo avatar Aug 14 '22 01:08 GMaiolo

Hi @andrewscofield and all, happy to say that this feature is being actively worked on as part of the upcoming v2

I'll share an early version for testing as soon as it's available

adamjmcgrath avatar Aug 15 '22 07:08 adamjmcgrath

I saw that you merged this @adamjmcgrath🚀 When will the version for testing be available? And is there an ETA for v2?

employee451 avatar Sep 16 '22 09:09 employee451

Hi @employee451 - yep, it's in the vNext branch.

For the more adventurous, you can checkout that branch and build it from there (see https://github.com/auth0/nextjs-auth0#contributing)

For everyone else, we'll be putting a tag for the v2 beta up on npm in the next couple of weeks - we'll update this thread as soon as it's available.

adamjmcgrath avatar Sep 20 '22 09:09 adamjmcgrath

Hey @adamjmcgrath! Thank you so much for all the amazing work. When do you plan on releasing this? This is a very cool feature and I can't wait to start using it :p

kaipervinay avatar Oct 17 '22 10:10 kaipervinay