@zeushq/nextjs-zidentity
Version:
Next.js SDK for signin in with Zeus Identity
127 lines (121 loc) • 4.06 kB
text/typescript
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';
/**
* 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 '@zeushq/nextjs-zidentity';
*
* export default function Profile({ user }) {
* return <div>Hello {user.name}</div>;
* }
*
* export const getServerSideProps = withPageAuthRequired();
* ```
*
* @category Server
*/
export type GetServerSidePropsResultWithSession = GetServerSidePropsResult<{
user?: Claims | null;
[key: string]: any;
}>;
/**
* A page route that has been augmented with {@link WithPageAuthRequired}
*
* @category Server
*/
export type PageRoute = (cts: GetServerSidePropsContext) => Promise<GetServerSidePropsResultWithSession>;
/**
* 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, eg:
*
* ```js
* // pages/protected-page.js
* import { withPageAuthRequired } from '@zeushq/nextjs-zidentity';
*
* export default function ProtectedPage({ user, customProp }) {
* return <div>Protected content</div>;
* }
*
* export const getServerSideProps = withPageAuthRequired({
* returnTo: '/foo',
* async getServerSideProps(ctx) {
* return { props: { customProp: 'bar' } };
* }
* });
* ```
*
* @category Server
*/
export type WithPageAuthRequiredOptions = { getServerSideProps?: GetServerSideProps; 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 '@zeushq/nextjs-zidentity';
*
* 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 = {
(opts?: WithPageAuthRequiredOptions): PageRoute;
<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 } };
};
};
}