rsnext/examples/with-cookie-auth/www/pages/login.js
Juan Olvera 798ae043ac Example with cookie auth (#5821)
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)
2018-12-14 23:05:54 +01:00

97 lines
2.2 KiB
JavaScript

import { Component } from 'react'
import Layout from '../components/layout'
import { login } from '../utils/auth'
class Login extends Component {
static getInitialProps ({ req }) {
const apiUrl = process.browser
? `https://${window.location.host}/api/login.js`
: `https://${req.headers.host}/api/login.js`
return { apiUrl }
}
constructor (props) {
super(props)
this.state = { username: '', error: '' }
this.handleChange = this.handleChange.bind(this)
this.handleSubmit = this.handleSubmit.bind(this)
}
handleChange (event) {
this.setState({ username: event.target.value })
}
async handleSubmit (event) {
event.preventDefault()
const username = this.state.username
const url = this.props.apiUrl
login({ username, url }).catch(() =>
this.setState({ error: 'Login failed.' })
)
}
render () {
return (
<Layout>
<div className='login'>
<form onSubmit={this.handleSubmit}>
<label htmlFor='username'>GitHub username</label>
<input
type='text'
id='username'
name='username'
value={this.state.username}
onChange={this.handleChange}
/>
<button type='submit'>Login</button>
<p className={`error ${this.state.error && 'show'}`}>
{this.state.error && `Error: ${this.state.error}`}
</p>
</form>
</div>
<style jsx>{`
.login {
max-width: 340px;
margin: 0 auto;
padding: 1rem;
border: 1px solid #ccc;
border-radius: 4px;
}
form {
display: flex;
flex-flow: column;
}
label {
font-weight: 600;
}
input {
padding: 8px;
margin: 0.3rem 0 1rem;
border: 1px solid #ccc;
border-radius: 4px;
}
.error {
margin: 0.5rem 0 0;
display: none;
color: brown;
}
.error.show {
display: block;
}
`}</style>
</Layout>
)
}
}
export default Login