-
Notifications
You must be signed in to change notification settings - Fork 397
/
with-page-auth-required.ts
131 lines (126 loc) · 4.3 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
130
131
import { GetServerSideProps, GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
import { Claims, GetSession } from '../session';
import { assertCtx } from '../utils/assert';
import React, { ComponentType } from 'react';
import {
WithPageAuthRequiredOptions as WithPageAuthRequiredCSROptions,
WithPageAuthRequiredProps
} from '../frontend/with-page-auth-required';
import { withPageAuthRequired as withPageAuthRequiredCSR } from '../frontend';
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 | null }>;
/**
* A page route that has been augmented with {@link WithPageAuthRequired}
*
* @category Server
*/
export type PageRoute<P, Q extends 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, eg:
*
* ```js
* // pages/protected-page.js
* import { withPageAuthRequired } from '@auth0/nextjs-auth0';
*
* export default function ProtectedPage({ user, customProp }) {
* return <div>Protected content</div>;
* }
*
* export const getServerSideProps = withPageAuthRequired({
* returnTo: '/foo',
* async getServerSideProps(ctx) {
* // access the user session
* const session = getSession(ctx.req, ctx.res);
* return { props: { customProp: 'bar' } };
* }
* });
* ```
*
* @category Server
*/
export type WithPageAuthRequiredOptions<P = 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, Q extends ParsedUrlQuery>(opts?: WithPageAuthRequiredOptions<P, Q>): PageRoute<P, Q>;
<P extends WithPageAuthRequiredProps>(
Component: ComponentType<P>,
options?: WithPageAuthRequiredCSROptions
): React.FC<P>;
};
/**
* @ignore
*/
export default function withPageAuthRequiredFactory(loginUrl: string, getSession: GetSession): WithPageAuthRequired {
return (
optsOrComponent: WithPageAuthRequiredOptions | ComponentType<WithPageAuthRequiredProps> = {},
csrOpts?: WithPageAuthRequiredCSROptions
): any => {
if (typeof optsOrComponent === 'function') {
return withPageAuthRequiredCSR(optsOrComponent, csrOpts);
}
const { getServerSideProps, returnTo } = optsOrComponent;
return async (ctx: GetServerSidePropsContext): Promise<GetServerSidePropsResultWithSession> => {
assertCtx(ctx);
const session = getSession(ctx.req, ctx.res);
if (!session?.user) {
// 10 - redirect
// 9.5.4 - unstable_redirect
// 9.4 - res.setHeaders
return {
redirect: {
destination: `${loginUrl}?returnTo=${encodeURIComponent(returnTo || ctx.resolvedUrl)}`,
permanent: false
}
};
}
let ret: any = { props: {} };
if (getServerSideProps) {
ret = await getServerSideProps(ctx);
}
return { ...ret, props: { ...ret.props, user: session.user } };
};
};
}