import React , { useEffect } from 'react' ; import nookies from 'nookies' ; import { AppProps , AppContext } from 'next/app' ; import { NextPageContext } from 'next' ; import { Maybe } from '@src/generated/graphql' ; import { SAFE_COOKIE_OPTIONS } from '@shared/safeCookieOptions' ; import Tokens from 'csrf' ; import { isServer } from '@src/modules/shared/SharedUtils' ; import { fetcher } from '@shared/fetcher' ; import { NEXT_DATA } from 'next/dist/next-server/lib/utils' ; declare global { interface Window { __NEXT_DATA__ : NEXT_DATA ; } } declare module 'http' { interface ServerResponse { locals : { csrfToken : string ; } ; } } const csrfSecretKey = '_csrf' ; export const getCSRFToken = ( ctx ? ) => { return isServer ( ) ? ctx ?. res ?. locals . csrfToken : window . __NEXT_DATA__ . props . csrfToken ; } ; const withCSRF = ( AppComponent ) => { const WithCSRF = ( props ) => { useEffect ( ( ) => { fetcher . setCSRFToken ( getCSRFToken ( ) ) ; } , [ ] ) ; return < AppComponent { ... props } / > ; } ; WithCSRF . getInitialProps = async ( appContext ) => { let csrfToken ; if ( isServer ( ) && appContext . ctx . req && appContext . ctx . res ) { const currentCookies = nookies . get ( appContext . ctx ) ; let csrfSecret = currentCookies [ csrfSecretKey ] ; const tokens = new Tokens ( ) ; if ( ! csrfSecret ) { csrfSecret = tokens . secretSync ( ) ; nookies . set ( appContext . ctx , csrfSecretKey , csrfSecret , SAFE_COOKIE_OPTIONS ) ; appContext . ctx . req . headers . cookie += `; ${ csrfSecretKey }=${ csrfSecret }` ; } csrfToken = tokens . create ( csrfSecret ) ; appContext . ctx . res . locals = { csrfToken } ; fetcher . setCSRFToken ( csrfToken ) ; } const pageProps = await AppComponent . getInitialProps ?. ( appContext ) ; return { ... pageProps , csrfToken } ; } ; return WithCSRF ; } ; export default withCSRF ;