-
-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(middleware): introduce withAuth
Next.js method
#3657
Conversation
Codecov Report
@@ Coverage Diff @@
## main #3657 +/- ##
==========================================
- Coverage 12.94% 12.68% -0.26%
==========================================
Files 93 94 +1
Lines 1468 1498 +30
Branches 390 399 +9
==========================================
Hits 190 190
- Misses 1267 1297 +30
Partials 11 11
Continue to review full report at Codecov.
|
🎉 Experimental release published on npm! npm i next-auth@0.0.0-pr.3657.f1addc18 yarn add next-auth@0.0.0-pr.3657.f1addc18 |
Love this idea and is what i'm used to doing on the backend side if I was making a BFF! FWIW, something like the below is what I might use in a .NET app. The api is really easy and powerful. Might provide some inspiration here: services.AddAuthentication(options =>
{
options.DefaultScheme = "cookie";
options.DefaultChallengeScheme = "oidc";
options.DefaultSignOutScheme = "oidc";
})
.AddCookie("cookie", options =>
{
options.Cookie.Name = "__Host-bff";
options.Cookie.SameSite = SameSiteMode.Strict;
})
.AddOpenIdConnect("oidc", options =>
{
options.Authority = "https://localhost:3385";
options.ClientId = "react.bff";
options.ClientSecret = "secret";
options.ResponseType = "code";
options.ResponseMode = "query";
options.usePkce = true;
options.GetClaimsFromUserInfoEndpoint = true;
options.MapInboundClaims = false;
options.SaveTokens = true;
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("role");
options.Scope.Add("email");
options.Scope.Add("recipe_management_access");
options.Scope.Add("offline_access");
options.TokenValidationParameters = new()
{
NameClaimType = "name",
RoleClaimType = "role"
};
}); |
Thanks for addressing this feature! Some feedback:
|
withAuth(
(req, ev) => {/*your middleware*/},
{/*your options*/}
) This would allow us to put it either as any element in the chain.
|
Planning to test our your pr soon, will follow up with any DX feedback. |
great work.
each user(admin) has different roles indicated like above. // pages/accessPolicies/_middleware.js
import { withAuth } from "next-auth/next/middleware"
export default withAuth({
authorized: ({ token }) => token?.roles.includes('accesscontextmanager.accessPolicies')
}) |
@always-maap My example logic is simplified, but you can do much more complex checks since you get a function. The original Please see the changed files: next-auth/src/next/middleware.ts Lines 46 to 49 in 96d07ab
|
Is the NextRequest req variable available inside the authorized function? I have a scenario where specific paths are accessible when the user isn't logged in and I need to check the current pathname. |
@Rees1993 literally the comment above yours :D There is also another way. You can include a middleware only for a subset of pages, if your URL structure allows it. (eg.: Useful resource: https://nextjs.org/docs/middleware#execution-order |
@balazsorban44 Well I think I might need to go to the opticians! Unfortunately these pages are all at the base level (pages/contact.js, pages/login.js etc.) so I don't think it would work. Thanks for that link though as I forgot about that functionality. Otherwise, I'm all for this middleware and look forward to testing it! |
73aa828
to
cb0ba9e
Compare
Moved |
…t-auth into feat/with-auth-middleware
} | ||
} | ||
|
||
const token = await getToken({ req: req as any }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@balazsorban44 Does this middleware will work with strategy: 'database'
?
I have similar middleware, but with getSession
request, because 'getToken' was null if i remember correct...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Only supports the "jwt" session strategy. We need to wait until databases at the Edge become mature enough to ensure a fast experience. (If you know of an Edge-compatible database, we would like if you proposed a new Adapter)"
mind sharing your sessions middleware function? 👀
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is pretty simple
export async function middleware(request: NextRequest) {
const cookie = request.headers.get('cookie')
const session = cookie
? await getSession({ req: { headers: { cookie } } as any })
: null
if (!session) {
return NextResponse.redirect(new URL('/api/auth/signin', request.url))
}
}
I tried to do this but for some reason it doesn't work... I always get redirected to Next-auth 's default login page...
However like some mentioned in this and other issues, if you are using TypeScript, the req in getToken is compatible with NextApiRequest, but not NextRequest... I don't know if there is some hidden logic there, but for me it works just fine if you don't define the type and just use NextRequest. However, since I wanted type safety, I just made this little change in @next-auth/jwt/index.d.ts. I imported this And changed the acceptable types in GetTokenParams --> req
Correct me if this is wrong and if this could break the app, but for now it works for me, and I had no problems what so ever. 👍 |
On build time it complains about the req when I deploy on Vercel, one way that I've found that worked was this
In that way, we still can use the token for the middleware autentication. |
Hi, please note that commenting on a merged PR is not going to be looked at. Please open a bug report with your reproduction if having issues. 🙏 |
This is currently an idea 💡 but it fixes #3037
To test it out, see #3657 (comment)
Useful resources:
Usage examples
Authentication only
You allow any logged-in user to access a page
Authorization
Certain conditions must be met for the user to continue, for example, to restrict an admin dashboard, you can do:
See the source code for the proposed API.
Suggestion: We could detect if
NEXTAUTH_SECRET
is present, sparing the user to fill an extra configuration field. (NOTE: This could be done inNextAuth
inpages/api/auth/[...nextauth]
as well)Open for feedback.