-
Notifications
You must be signed in to change notification settings - Fork 402
/
Copy pathauth.ts
186 lines (176 loc) · 5.41 KB
/
auth.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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next';
import { HandleLogin } from './login';
import { HandleLogout } from './logout';
import { HandleCallback } from './callback';
import { HandleProfile } from './profile';
import { HandlerError } from '../utils/errors';
/**
* If you want to add some custom behavior to the default auth handlers, you can pass in custom handlers for
* `login`, `logout`, `callback`, and `profile`. For example:
*
* ```js
* // pages/api/auth/[...auth0].js
* import { handleAuth, handleLogin } from '@auth0/nextjs-auth0';
* import { errorReporter, logger } from '../../../utils';
*
* export default handleAuth({
* async login(req, res) {
* try {
* // Pass in custom params to your handler
* await handleLogin(req, res, { authorizationParams: { customParam: 'foo' } });
* // Add your own custom logging.
* logger('Redirecting to login');
* } catch (error) {
* // Add you own custom error logging.
* errorReporter(error);
* res.status(error.status || 500).end();
* }
* }
* });
* ```
*
* Alternatively, you can customize the default handlers without overriding them. For example:
*
* ```js
* // pages/api/auth/[...auth0].js
* import { handleAuth, handleLogin } from '@auth0/nextjs-auth0';
*
* export default handleAuth({
* login: handleLogin({
* authorizationParams: { customParam: 'foo' } // Pass in custom params
* })
* });
* ```
*
* You can also create new handlers by customizing the default ones. For example:
*
* ```js
* // pages/api/auth/[...auth0].js
* import { handleAuth, handleLogin } from '@auth0/nextjs-auth0';
*
* export default handleAuth({
* signup: handleLogin({
* authorizationParams: { screen_hint: 'signup' }
* })
* });
* ```
*
* @category Server
*/
export type Handlers = ApiHandlers | ErrorHandlers;
type ApiHandlers = {
[key: string]: NextApiHandler;
};
type ErrorHandlers = {
onError?: OnError;
};
/**
* The main way to use the server SDK.
*
* Simply set the environment variables per {@link ConfigParameters} then create the file
* `pages/api/auth/[...auth0].js`. For example:
*
* ```js
* // pages/api/auth/[...auth0].js
* import { handleAuth } from '@auth0/nextjs-auth0';
*
* export default handleAuth();
* ```
*
* This will create 5 handlers for the following urls:
*
* - `/api/auth/login`: log the user in to your app by redirecting them to your identity provider.
* - `/api/auth/callback`: The page that your identity provider will redirect the user back to on login.
* - `/api/auth/logout`: log the user out of your app.
* - `/api/auth/me`: View the user profile JSON (used by the {@link UseUser} hook).
* - `/api/auth/unauthorized`: Returns a 401 for use by {@link WithMiddlewareAuthRequired} when protecting API routes.
*
* @category Server
*/
export type HandleAuth = (userHandlers?: Handlers) => NextApiHandler;
/**
* Error handler for the default auth routes.
*
* Use this to define an error handler for all the default routes in a single place. For example:
*
* ```js
* export default handleAuth({
* onError(req, res, error) {
* errorLogger(error);
* // You can finish the response yourself if you want to customize
* // the status code or redirect the user
* // res.writeHead(302, {
* // Location: '/custom-error-page'
* // });
* // res.end();
* }
* });
* ```
*
* @category Server
*/
export type OnError = (req: NextApiRequest, res: NextApiResponse, error: HandlerError) => Promise<void> | void;
/**
* @ignore
*/
const defaultOnError: OnError = (_req, res, error) => {
console.error(error);
res.status(error.status || 500).end();
};
/**
* This is a handler for use by {@link WithMiddlewareAuthRequired} when protecting an API route.
* Middleware can't return a response body, so an unauthorized request for an API route
* needs to rewrite to this handler.
* @ignore
*/
const unauthorized: NextApiHandler = (_req, res) => {
res.status(401).json({
error: 'not_authenticated',
description: 'The user does not have an active session or is not authenticated'
});
};
/**
* @ignore
*/
export default function handlerFactory({
handleLogin,
handleLogout,
handleCallback,
handleProfile
}: {
handleLogin: HandleLogin;
handleLogout: HandleLogout;
handleCallback: HandleCallback;
handleProfile: HandleProfile;
}): HandleAuth {
return ({ onError, ...handlers }: Handlers = {}): NextApiHandler<void> => {
const customHandlers: ApiHandlers = {
login: handleLogin,
logout: handleLogout,
callback: handleCallback,
me: (handlers as ApiHandlers).profile || handleProfile,
401: unauthorized,
...handlers
};
return async (req, res): Promise<void> => {
let {
query: { auth0: route }
} = req;
route = Array.isArray(route) ? route[0] : /* c8 ignore next */ route;
try {
const handler = route && customHandlers.hasOwnProperty(route) && customHandlers[route];
if (handler) {
await handler(req, res);
} else {
res.status(404).end();
}
} catch (error) {
await (onError || defaultOnError)(req, res, error as HandlerError);
if (!res.writableEnded) {
// 200 is the default, so we assume it has not been set in the custom error handler if it equals 200
res.status(res.statusCode === 200 ? 500 : res.statusCode).end();
}
}
};
};
}