![Create React App Officially Deprecated Amid React 19 Compatibility Issues](https://cdn.sanity.io/images/cgdhsj6q/production/04fa08cf844d798abc0e1a6391c129363cc7e2ab-1024x1024.webp?w=400&fit=max&auto=format)
Security News
Create React App Officially Deprecated Amid React 19 Compatibility Issues
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
@significa/auth-next
Advanced tools
Auth-related functions to handle access and refresh tokens in NextJS projects
This is work in progress and only suitable for internal use.
This package solves JWT-based authentication by saving the refresh token in an http-only cookie (accessible only server-side) and the access-token + a session indicator with the expiration date in client-acessible cookies.
Generate a new github PAT (Classic Personal Access Token).
Grant read:packages
Download packages from GitHub Package Registry.
Run npm login --scope=@significa --registry=https://npm.pkg.github.com
.
In the interactive CLI set your GitHub handle as the username and the newly generated PAT as the password (email can be anything).
npm install @significa/auth-next
More info: Working with the GitHub npm registry.
Create a lib/auth.ts
file to create your auth's config.
This package exposes a main Auth
class that should be initialized with your project's configuration:
// lib/auth.ts
import { Auth } from '@significa/auth-next'
import { API_URL } from 'common/constants'
export const auth = new Auth({
accessTokenKey: 'project_token',
sessionIndicatorKey: 'project_session',
refreshTokenKey: 'project_refresh_token',
/* configuration for the handler in Next's API Routes */
serverHandlers: {
login: {
fetch: (email, password) => {
return fetch(`${API_URL}/auth/login`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
email,
password,
}),
})
},
parseResponse: async (res) => {
const { data } = await res.json()
return {
accessToken: data.access_token,
expires: data.expires,
refreshToken: data.refresh_token,
}
},
},
refresh: {
fetch: async (refreshToken: string) => {
return fetch(`${API_URL}/auth/refresh`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ refresh_token: refreshToken }),
})
},
parseResponse: async (res) => {
const { data } = await res.json()
return {
accessToken: data.access_token,
expires: data.expires,
refreshToken: data.refresh_token,
}
},
},
logout: {
fetch: async (refreshToken: string) => {
return fetch(`${API_URL}/auth/logout`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ refresh_token: refreshToken }),
})
},
},
},
})
If you're using Directus, you can use createDirectusHandlers
instead:
// lib/auth.ts
import { Auth, createDirectusHandlers } from '@significa/auth-next'
import { API_URL } from 'common/constants'
export const auth = new Auth({
accessTokenKey: 'project_token',
sessionIndicatorKey: 'project_session',
refreshTokenKey: 'project_refresh_token',
serverHandlers: createDirectusHandlers({
url: API_URL,
}),
})
Finally, you can create some aliases for page restrictions:
// still in lib/auth.ts
export const withRestriction = auth.restrictions.withRestriction
export const withSessionRefresh = auth.restrictions.withSessionRefresh
export const withGuestRestriction = withRestriction.bind(null, (isAuthed) =>
isAuthed ? '/app' : false
)
export const withAuthRestriction = withRestriction.bind(null, (isAuthed) =>
isAuthed ? false : '/login'
)
Create a pages/api/auth/[path].ts
file.
If you passed basePath
in your serverHandlers
config, make sure you create the file in the appropriate path
import { auth } from 'lib/auth'
export default auth.server.handler
auth.server.paths.login
.auth.server.paths.logout
.useLogin
and useLogout
hooksYou can create some hooks to centralize all the login/logout logic:
// useLogin.tsx
import { useRouter } from 'next/router'
import { useState } from 'react'
import { auth } from 'lib/auth'
export const useLogin = ({
onSuccess,
onError,
}: {
onSuccess?: () => void
onError?: () => void
} = {}) => {
const { push, query } = useRouter()
const [loading, setLoading] = useState(false)
const [error, setError] = useState(false)
const login = async ({
email,
password,
}: {
email: string
password: string
}) => {
setLoading(true)
try {
const res = await fetch(auth.server.paths.login, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email, password }),
})
if (!res.ok) throw new Error()
if (typeof onSuccess === 'function') {
onSuccess()
} else {
// push to app by default
push(typeof query.returnTo === 'string' ? query.returnTo : '/app')
}
} catch (error) {
setError(true)
onError?.()
} finally {
setLoading(false)
}
}
const resetError = () => {
if (error) setError(false)
}
return { login, loading, error, resetError }
}
// useLogout.tsx
import { useRouter } from 'next/router'
import { useState } from 'react'
import { auth } from 'lib/auth'
export const useLogout = () => {
const { push } = useRouter()
const [loading, setLoading] = useState(false)
const logout = async () => {
setLoading(true)
try {
const res = await fetch(auth.server.paths.logout)
if (!res.ok) throw new Error()
} catch (error) {
// at least clear client-side cookies
auth.client.clearAccessToken()
auth.client.clearSessionIndicator()
} finally {
// redirect anyway
push('/')
setLoading(false)
}
}
return { logout, loading }
}
Finally, you can use the aliases in 'lib/auth' to lock routes:
// pages/app/index.tsx
import { withAuthRestriction } from 'lib/auth'
const AppHomepage = () => <div>Hello from App</div>
export const getServerSideProps = withAuthRestriction()
export default AppHomepage
withRestriction
already refreshes the session if necessary but, if you need, you can trigger a session refresh server-side by using withSessionRefresh
:
// pages/index.tsx
import { withSessionRefresh } from 'lib/auth'
...
export const getServerSideProps = withSessionRefresh()
useRefreshSession
This package also exports a useRefreshSession
hook that can be used to make client-side refreshes at a certain interval or whenever the window gains focus:
// _app.tsx
import { useRefreshSession, getDateDistance } from '@significa/auth-next'
import { auth } from 'lib/auth'
function MyApp({ Component, pageProps }: AppProps) {
useRefreshSession({
refreshPath: auth.server.paths.refresh,
shouldRefresh: () => {
const expiryDate = auth.client.getSessionIndicator()
if (!expiryDate) return false
return getDateDistance(new Date(expiryDate)) <= 30
},
onRefresh: () => {
queryClient.invalidateQueries(useMeQuery.getKey())
},
})
})
return ...
}
FAQs
Auth-related functions to handle access and refresh tokens in NextJS projects
The npm package @significa/auth-next receives a total of 1 weekly downloads. As such, @significa/auth-next popularity was classified as not popular.
We found that @significa/auth-next demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.
Security News
The Linux Foundation is warning open source developers that compliance with global sanctions is mandatory, highlighting legal risks and restrictions on contributions.