-
Notifications
You must be signed in to change notification settings - Fork 402
/
Copy pathwith-page-auth-required.ts
129 lines (124 loc) · 3.89 KB
/
with-page-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
import { GetServerSideProps, GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
import { Claims, SessionCache } from '../session';
import { assertCtx } from '../utils/assert';
import { ParsedUrlQuery } from 'querystring';
/**
* If you wrap your `getServerSideProps` with {@link WithPageAuthRequired} your props object will be augmented with
* the user property, which will be the user's {@link Claims}.
*
* ```js
* // pages/profile.js
* import { withPageAuthRequired } from '@auth0/nextjs-auth0';
*
* export default function Profile({ user }) {
* return <div>Hello {user.name}</div>;
* }
*
* export const getServerSideProps = withPageAuthRequired();
* ```
*
* @category Server
*/
export type GetServerSidePropsResultWithSession<P = any> = GetServerSidePropsResult<P & { user: Claims }>;
/**
* A page route that has been augmented with {@link WithPageAuthRequired}.
*
* @category Server
*/
export type PageRoute<P, Q extends ParsedUrlQuery = ParsedUrlQuery> = (
cts: GetServerSidePropsContext<Q>
) => Promise<GetServerSidePropsResultWithSession<P>>;
/**
* If you have a custom returnTo url you should specify it in `returnTo`.
*
* You can pass in your own `getServerSideProps` method, the props returned from this will be
* merged with the user props. You can also access the user session data by calling `getSession`
* inside of this method. For example:
*
* ```js
* // pages/protected-page.js
* import { getSession, withPageAuthRequired } from '@auth0/nextjs-auth0';
*
* export default function ProtectedPage({ user, customProp }) {
* return <div>Protected content</div>;
* }
*
* export const getServerSideProps = withPageAuthRequired({
* // returnTo: '/unauthorized',
* async getServerSideProps(ctx) {
* // access the user session if needed
* // const session = await getSession(ctx.req, ctx.res);
* return {
* props: {
* // customProp: 'bar',
* }
* };
* }
* });
* ```
*
* @category Server
*/
export type WithPageAuthRequiredOptions<
P extends { [key: string]: any } = { [key: string]: any },
Q extends ParsedUrlQuery = ParsedUrlQuery
> = {
getServerSideProps?: GetServerSideProps<P, Q>;
returnTo?: string;
};
/**
* Wrap your `getServerSideProps` with this method to make sure the user is authenticated before
* visiting the page.
*
* ```js
* // pages/protected-page.js
* import { withPageAuthRequired } from '@auth0/nextjs-auth0';
*
* export default function ProtectedPage() {
* return <div>Protected content</div>;
* }
*
* export const getServerSideProps = withPageAuthRequired();
* ```
*
* If the user visits `/protected-page` without a valid session, it will redirect the user to the
* login page. Then they will be returned to `/protected-page` after login.
*
* @category Server
*/
export type WithPageAuthRequired = <
P extends { [key: string]: any } = { [key: string]: any },
Q extends ParsedUrlQuery = ParsedUrlQuery
>(
opts?: WithPageAuthRequiredOptions<P, Q>
) => PageRoute<P, Q>;
/**
* @ignore
*/
export default function withPageAuthRequiredFactory(
loginUrl: string,
getSessionCache: () => SessionCache
): WithPageAuthRequired {
return ({ getServerSideProps, returnTo } = {}) =>
async (ctx) => {
assertCtx(ctx);
const sessionCache = getSessionCache();
const session = await sessionCache.get(ctx.req, ctx.res);
if (!session?.user) {
return {
redirect: {
destination: `${loginUrl}?returnTo=${encodeURIComponent(returnTo || ctx.resolvedUrl)}`,
permanent: false
}
};
}
let ret: any = { props: {} };
if (getServerSideProps) {
ret = await getServerSideProps(ctx);
}
if (ret.props instanceof Promise) {
return { ...ret, props: ret.props.then((props: any) => ({ user: session.user, ...props })) };
}
return { ...ret, props: { user: session.user, ...ret.props } };
};
}