flixoflax
08/23/2022, 10:19 AMrp_st
08/23/2022, 10:43 AMflixoflax
08/23/2022, 10:43 AMflixoflax
08/23/2022, 10:45 AMflixoflax
08/23/2022, 10:46 AMimport { useRouter } from 'next/router'
import { ReactElement, useEffect, useState } from 'react'
import { useSessionContext } from 'supertokens-auth-react/recipe/session'
import { isEmailVerified as tpIsEmailVerified } from 'supertokens-auth-react/recipe/thirdpartyemailpassword'
const AuthWrapper = ({ children }: { children: ReactElement }) => {
const sessionContext = useSessionContext()
const router = useRouter()
const [verified, setVerified] = useState<boolean>(false)
useEffect(() => {
console.log('running useEffect')
const redirectToPath = new URL(window.location.href).searchParams.get(
'redirectToPath'
)
async function isEmailVerified() {
const { isVerified } = await tpIsEmailVerified()
setVerified(isVerified)
}
isEmailVerified()
if (sessionContext.loading === false) {
if (sessionContext.doesSessionExist) {
const atp = sessionContext.accessTokenPayload
const { isUsernameSet } = atp
if (isUsernameSet === false) {
router.replace({
pathname: '/auth/set-username',
query: { redirectToPath },
})
}
if (verified === false) {
router.replace({
pathname: '/auth/verify-email',
query: { redirectToPath },
})
}
if (
router.asPath.includes('/auth') &&
verified === true &&
isUsernameSet === true
) {
router.replace(redirectToPath || '/')
}
} else {
router.replace({
pathname: '/auth/signin',
query: { redirectToPath },
})
}
}
}, [router, sessionContext, verified])
if (sessionContext.loading === true) {
return null
}
return children
}
export default AuthWrapper
rp_st
08/23/2022, 10:47 AMflixoflax
08/23/2022, 10:47 AMporcellus
08/23/2022, 10:50 AMflixoflax
08/23/2022, 10:50 AMporcellus
08/23/2022, 10:52 AMisEmailVerified
(or setVerified
)?flixoflax
08/23/2022, 10:54 AMflixoflax
08/23/2022, 10:55 AMporcellus
08/23/2022, 10:58 AMloading
?flixoflax
08/23/2022, 10:59 AMflixoflax
08/23/2022, 10:59 AMporcellus
08/23/2022, 11:01 AMisEmailVerified
before the session is loaded. Also, the loading state is mostly for SSR support and anything you wrap with <SessionAuth requireAuth={true>
should not be affected by it at all.porcellus
08/23/2022, 11:02 AMloading
in your components?flixoflax
08/23/2022, 11:03 AMflixoflax
08/23/2022, 11:03 AMisEmailVerified
below the if(sessionContext.doesSessionExist)
and it's still an infinite loopporcellus
08/23/2022, 11:04 AMflixoflax
08/23/2022, 11:04 AMflixoflax
08/23/2022, 11:05 AMuseEffect
hook run infiniteflixoflax
08/23/2022, 11:05 AMporcellus
08/23/2022, 11:06 AMporcellus
08/23/2022, 11:06 AMflixoflax
08/23/2022, 11:07 AMflixoflax
08/23/2022, 11:07 AMflixoflax
08/23/2022, 11:07 AMporcellus
08/23/2022, 11:07 AMporcellus
08/23/2022, 11:09 AM/auth
route, and a session doesn't exists, then this useEffect
will keep calling router.replace
porcellus
08/23/2022, 11:10 AMflixoflax
08/23/2022, 11:11 AMflixoflax
08/23/2022, 11:11 AMflixoflax
08/23/2022, 11:11 AMporcellus
08/23/2022, 11:12 AMflixoflax
08/23/2022, 11:16 AMflixoflax
08/23/2022, 11:16 AMflixoflax
08/23/2022, 11:16 AMflixoflax
08/23/2022, 11:23 AMflixoflax
08/23/2022, 11:25 AMconst AuthWrapper = ({ children }: { children: ReactElement }) => {
const sessionContext = useSessionContext()
const router = useRouter()
useEffect(() => {
console.log('running useEffect')
const redirectToPath = new URL(window.location.href).searchParams.get(
'redirectToPath'
)
if (sessionContext.loading === false) {
if (sessionContext.doesSessionExist) {
const atp = sessionContext.accessTokenPayload
const { isUsernameSet, isEmailVerified } = atp
if (isUsernameSet === false) {
console.log('Username is not set')
if (!router.asPath.includes('/auth/set-username')) {
router.replace({
pathname: '/auth/set-username',
query: { redirectToPath },
})
}
}
if (isEmailVerified === false) {
if (!router.asPath.includes('/auth/verify-email')) {
router.replace({
pathname: '/auth/verify-email',
query: { redirectToPath },
})
}
}
if (
router.asPath.includes('/auth') &&
isEmailVerified === true &&
isUsernameSet === true
) {
router.replace(redirectToPath || '/')
}
} else if (!router.asPath.includes('/auth')) {
router.replace({
pathname: '/auth/signin',
query: { redirectToPath },
})
}
}
}, [router, sessionContext]
if (sessionContext.loading === true) {
return null
}
return children
}
export default AuthWrapper
The email part only works because I save the thing in the accesstokenpayload on session creation ....porcellus
08/23/2022, 11:26 AMisEmailVerified
from the access token?flixoflax
08/23/2022, 11:26 AMflixoflax
08/23/2022, 11:26 AMporcellus
08/23/2022, 11:27 AMset-username
and then redirect to auth/verify-email
porcellus
08/23/2022, 11:27 AMflixoflax
08/23/2022, 11:33 AMflixoflax
08/23/2022, 11:37 AMflixoflax
08/23/2022, 11:37 AMflixoflax
08/23/2022, 11:37 AMflixoflax
08/23/2022, 11:38 AMflixoflax
08/23/2022, 11:38 AMflixoflax
08/23/2022, 11:38 AMporcellus
08/23/2022, 11:39 AMcreateNewSession
?flixoflax
08/23/2022, 11:40 AMflixoflax
08/23/2022, 11:41 AMflixoflax
08/23/2022, 11:41 AMOverride: &tpepmodels.OverrideStruct{
EmailVerificationFeature: &evmodels.OverrideStruct{
APIs: func(originalImplementation evmodels.APIInterface) evmodels.APIInterface {
originalVerifyEmailPOST := *originalImplementation.VerifyEmailPOST
(*originalImplementation.VerifyEmailPOST) = func(token string, options evmodels.APIOptions, userContext supertokens.UserContext) (evmodels.VerifyEmailPOSTResponse, error) {
resp, err := originalVerifyEmailPOST(token, options, userContext)
if err != nil {
return evmodels.VerifyEmailPOSTResponse{}, err
}
if resp.OK != nil {
// TODO: Update ATP
}
return resp, nil
}
return originalImplementation
},
},
},
flixoflax
08/23/2022, 11:42 AMflixoflax
08/23/2022, 11:42 AMflixoflax
08/23/2022, 11:42 AMporcellus
08/23/2022, 11:44 AMporcellus
08/23/2022, 11:45 AMporcellus
08/23/2022, 11:45 AMporcellus
08/23/2022, 11:46 AMflixoflax
08/23/2022, 11:47 AMflixoflax
08/23/2022, 11:48 AMflixoflax
08/23/2022, 11:49 AMverified
has to be in the dependency array of useEffect
porcellus
08/23/2022, 11:55 AM[sessionContext.loading, sessionContext.doesSessionExist]
for that)
2. redirect in the other oneporcellus
08/23/2022, 11:57 AMflixoflax
08/23/2022, 11:57 AMporcellus
08/23/2022, 12:00 PMrouter.replace
taking effect after you render children
. there are multiple solutions, the simplest (IMHO) is using an extra state variable (showChildren
) that you can set to true after you run your checks for redirection.flixoflax
08/23/2022, 12:02 PMflixoflax
08/23/2022, 12:02 PMflixoflax
08/23/2022, 12:35 PMflixoflax
08/23/2022, 12:36 PMflixoflax
08/23/2022, 12:36 PMrp_st
08/23/2022, 12:36 PMflixoflax
08/23/2022, 12:40 PMflixoflax
08/23/2022, 12:40 PMrp_st
08/23/2022, 12:41 PMrp_st
08/23/2022, 12:41 PMrp_st
08/23/2022, 12:41 PMflixoflax
08/23/2022, 12:45 PMOverride: &tpepmodels.OverrideStruct{
EmailVerificationFeature: &evmodels.OverrideStruct{
APIs: func(originalImplementation evmodels.APIInterface) evmodels.APIInterface {
originalVerifyEmailPOST := *originalImplementation.VerifyEmailPOST
(*originalImplementation.VerifyEmailPOST) = func(token string, options evmodels.APIOptions, userContext supertokens.UserContext) (evmodels.VerifyEmailPOSTResponse, error) {
resp, err := originalVerifyEmailPOST(token, options, userContext)
if err != nil {
return evmodels.VerifyEmailPOSTResponse{}, err
}
if resp.OK != nil {
// TODO: Update ATP
}
return resp, nil
}
return originalImplementation
},
},
},
This is what I have. The response has no attribute session.... so how would I do this?porcellus
08/23/2022, 12:47 PMrp_st
08/23/2022, 12:47 PMflixoflax
08/23/2022, 12:49 PMflixoflax
08/23/2022, 12:49 PMrp_st
08/23/2022, 12:50 PM