mirror of
https://github.com/terribleplan/next.js.git
synced 2024-01-19 02:48:18 +00:00
798ae043ac
Fixes #153 This is my attempt at https://github.com/zeit/next.js/issues/153 Following @rauchg instructions: - it uses an authentication helper across pages which returns a token if there's one - it has session synchronization across tabs - <strike>I deployed a passwordless backend on `now.sh` (https://with-cookie-api.now.sh, [src](https://github.com/j0lv3r4/next.js-with-cookies-api))</strike> The backend is included in the repository and you can deploy everything together by running `now` Also, from reviewing other PRs, I made sure to: - use [isomorphic-unfetch](https://www.npmjs.com/package/isomorphic-unfetch). - use [next-cookies](https://www.npmjs.com/package/next-cookies). Here's a little demo: ![GIF](https://i.imgur.com/067Ph56.gif)
85 lines
2 KiB
JavaScript
85 lines
2 KiB
JavaScript
import { Component } from 'react'
|
|
import Router from 'next/router'
|
|
import nextCookie from 'next-cookies'
|
|
import cookie from 'js-cookie'
|
|
import fetch from 'isomorphic-unfetch'
|
|
|
|
export const login = async ({ username, url }) => {
|
|
try {
|
|
const response = await fetch(url, {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ username })
|
|
})
|
|
if (response.ok) {
|
|
const { token } = await response.json()
|
|
cookie.set('token', token, { expires: 1 })
|
|
Router.push('/profile')
|
|
} else {
|
|
console.log('Login failed.')
|
|
// https://github.com/developit/unfetch#caveats
|
|
let error = new Error(response.statusText)
|
|
error.response = response
|
|
return Promise.reject(error)
|
|
}
|
|
} catch (error) {
|
|
console.error(
|
|
'You have an error in your code or there are Network issues.',
|
|
error
|
|
)
|
|
throw new Error(error)
|
|
}
|
|
}
|
|
|
|
export const logout = () => {
|
|
cookie.remove('token')
|
|
// to support logging out from all windows
|
|
window.localStorage.setItem('logout', Date.now())
|
|
Router.push('/login')
|
|
}
|
|
|
|
export function withAuthSync (WrappedComponent) {
|
|
return class extends Component {
|
|
constructor (props) {
|
|
super(props)
|
|
|
|
this.syncLogout = this.syncLogout.bind(this)
|
|
}
|
|
componentDidMount () {
|
|
window.addEventListener('storage', this.syncLogout)
|
|
}
|
|
|
|
componentWillUnmount () {
|
|
window.removeEventListener('storage', this.syncLogout)
|
|
window.localStorage.removeItem('logout')
|
|
}
|
|
|
|
syncLogout (event) {
|
|
if (event.key === 'logout') {
|
|
console.log('logged out from storage!')
|
|
Router.push('/login')
|
|
}
|
|
}
|
|
|
|
render () {
|
|
return <WrappedComponent {...this.props} />
|
|
}
|
|
}
|
|
}
|
|
|
|
export default ctx => {
|
|
const { token } = nextCookie(ctx)
|
|
|
|
if (ctx.req && !token) {
|
|
ctx.res.writeHead(302, { Location: '/login' })
|
|
ctx.res.end()
|
|
return
|
|
}
|
|
|
|
if (!token) {
|
|
Router.push('/login')
|
|
}
|
|
|
|
return token
|
|
}
|