-
Notifications
You must be signed in to change notification settings - Fork 386
/
with-middleware-auth-required.ts
148 lines (143 loc) · 4.37 KB
/
with-middleware-auth-required.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import { NextMiddleware, NextRequest, NextResponse } from 'next/server';
import { SessionCache } from '../session';
import { GetConfig } from '../config';
import { Auth0NextRequest } from '../http';
/**
* Pass custom options to {@link WithMiddlewareAuthRequired}.
*
* @category Server
*/
export type WithMiddlewareAuthRequiredOptions = {
middleware?: NextMiddleware;
returnTo?: string | ((req: NextRequest) => Promise<string> | string);
};
/**
* Protect your pages with Next.js Middleware. For example:
*
* To protect all your routes:
*
* ```js
* // middleware.js
* import { withMiddlewareAuthRequired } from '@auth0/nextjs-auth0/edge';
*
* export default withMiddlewareAuthRequired();
* ```
*
* To protect specific routes:
*
* ```js
* // middleware.js
* import { withMiddlewareAuthRequired } from '@auth0/nextjs-auth0/edge';
*
* export default withMiddlewareAuthRequired();
*
* export const config = {
* matcher: '/about/:path*',
* };
* ```
* For more info see: https://nextjs.org/docs/advanced-features/middleware#matching-paths
*
* To run custom middleware for authenticated users:
*
* ```js
* // middleware.js
* import { withMiddlewareAuthRequired, getSession } from '@auth0/nextjs-auth0/edge';
*
* export default withMiddlewareAuthRequired(async function middleware(req) {
* const res = NextResponse.next();
* const user = await getSession(req, res);
* res.cookies.set('hl', user.language);
* return res;
* });
* ```
*
* To provide a custom `returnTo` url to login:
*
* ```js
* // middleware.js
* import { withMiddlewareAuthRequired, getSession } from '@auth0/nextjs-auth0/edge';
*
* export default withMiddlewareAuthRequired({
* returnTo: '/foo',
* // Custom middleware is provided with the `middleware` config option
* async middleware(req) { return NextResponse.next(); }
* });
* ```
*
* You can also provide a method for `returnTo` that takes the req as an argument.
*
* ```js
* // middleware.js
* import { withMiddlewareAuthRequired, getSession } from '@auth0/nextjs-auth0/edge';
*
* export default withMiddlewareAuthRequired({
* returnTo(req) { return `${req.nextURL.basePath}${req.nextURL.pathname}`};
* });
* ```
*
* @category Server
*/
export type WithMiddlewareAuthRequired = (
middlewareOrOpts?: NextMiddleware | WithMiddlewareAuthRequiredOptions
) => NextMiddleware;
/**
* @ignore
*/
export default function withMiddlewareAuthRequiredFactory(
getConfig: GetConfig,
sessionCache: SessionCache
): WithMiddlewareAuthRequired {
return function withMiddlewareAuthRequired(opts?): NextMiddleware {
return async function wrappedMiddleware(...args) {
const [req] = args;
const {
routes: { login, callback }
} = await getConfig(new Auth0NextRequest(req));
let middleware: NextMiddleware | undefined;
const { pathname, origin, search } = req.nextUrl;
let returnTo = `${pathname}${search}`;
if (typeof opts === 'function') {
middleware = opts;
} else if (opts) {
middleware = opts.middleware;
returnTo = (typeof opts.returnTo === 'function' ? await opts.returnTo(req) : opts.returnTo) || returnTo;
}
const ignorePaths = [login, callback, '/_next', '/favicon.ico'];
if (ignorePaths.some((p) => pathname.startsWith(p))) {
return;
}
const authRes = NextResponse.next();
const session = await sessionCache.get(req, authRes);
if (!session?.user) {
if (pathname.startsWith('/api')) {
return NextResponse.json(
{
error: 'not_authenticated',
description: 'The user does not have an active session or is not authenticated'
},
{ status: 401 }
);
}
return NextResponse.redirect(new URL(`${login}?returnTo=${encodeURIComponent(returnTo)}`, origin));
}
const res = await (middleware && middleware(...args));
if (res) {
const nextRes = new NextResponse(res.body, res);
const cookies = authRes.cookies.getAll();
if ('cookies' in res) {
for (const cookie of res.cookies.getAll()) {
nextRes.cookies.set(cookie);
}
}
for (const cookie of cookies) {
if (!nextRes.cookies.get(cookie.name)) {
nextRes.cookies.set(cookie);
}
}
return nextRes;
} else {
return authRes;
}
};
};
}