Skip to content

Instantly share code, notes, and snippets.

@akinncar
Last active November 3, 2023 01:51
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save akinncar/69dded022a7977d15d26349b5996ad06 to your computer and use it in GitHub Desktop.
Save akinncar/69dded022a7977d15d26349b5996ad06 to your computer and use it in GitHub Desktop.
AuthContext with NextJs + Nookies
import {
createContext,
ReactNode,
useContext,
useEffect,
useState,
} from 'react'
import { setCookie, parseCookies, destroyCookie } from 'nookies'
import Router from 'next/router'
import { BroadcastChannel } from 'broadcast-channel'
import { api } from '../services/api'
import { success, error } from '../components/Toast'
type User = {
email: string
}
type SignInCredentials = {
email: string
password: string
}
type AuthContextData = {
signIn: (credentials: SignInCredentials) => Promise<void>
signOut: () => void
user?: User
isAuthenticated: boolean
}
type AuthProviderProps = {
children: ReactNode
}
const AuthContext = createContext({} as AuthContextData)
let authChannel: BroadcastChannel
export function signOut() {
destroyCookie(undefined, 'simon.token')
destroyCookie(undefined, 'simon.refreshToken')
authChannel.postMessage('signOut')
Router.push('/')
}
export function AuthProvider({ children }: AuthProviderProps) {
const [user, setUser] = useState<User>()
const isAuthenticated = !!user
useEffect(() => {
authChannel = new BroadcastChannel('auth')
authChannel.onmessage = (message) => {
switch (message.data) {
case 'signOut':
Router.push('/')
break
case 'signIn':
Router.push('/users')
break
default:
break
}
}
}, [])
useEffect(() => {
const { 'simon.token': token } = parseCookies()
if (token) {
api
.get('/users/me')
.then((response) => {
const { user } = response.data
setUser(user)
})
.catch(() => {
signOut()
})
}
}, [])
async function signIn({ email, password }: SignInCredentials) {
try {
const response = await api.post('/login', {
email,
pass: password,
})
const { token } = response.data
setCookie(undefined, 'simon.token', token, {
maxAge: 60 * 60 * 24 * 30, // 30 days
path: '/',
})
setUser({
email,
})
api.defaults.headers.Authorization = `Bearer ${token}`
Router.push('/users')
authChannel.postMessage('signIn')
success('Logado com sucesso!')
} catch (err) {
error(err.response.data.error || err.message)
}
}
return (
<AuthContext.Provider value={{ isAuthenticated, user, signIn, signOut }}>
{children}
</AuthContext.Provider>
)
}
export const useAuth = () => useContext(AuthContext)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment