diff --git a/examples/with-cookie-auth/README.md b/examples/with-cookie-auth/README.md index a3659ff3c02ea..4834825416d31 100644 --- a/examples/with-cookie-auth/README.md +++ b/examples/with-cookie-auth/README.md @@ -1,52 +1,5 @@ -# Example app utilizing cookie-based authentication +This example has been deprecated and removed in favor of one of the following examples: -In this example, we authenticate users and store a token in a cookie. The example only shows how the user session works, keeping a user logged in between pages. - -This example is backend agnostic and uses [isomorphic-unfetch](https://www.npmjs.com/package/isomorphic-unfetch) to do the API calls on the client and the server. - -The repo includes a minimal passwordless backend built with the new [API Routes support](https://github.com/zeit/next.js/pull/7296) (`pages/api`), [Micro](https://www.npmjs.com/package/micro) and the [GitHub API](https://developer.github.com/v3/). The backend allows the user to log in with their GitHub username. - -Session is synchronized across tabs. If you logout your session gets removed on all the windows as well. We use the HOC `withAuthSync` for this. - -The helper function `auth` helps to retrieve the token across pages and redirects the user if not token was found. - -## Deploy your own - -Deploy the example using [ZEIT Now](https://zeit.co/now): - -[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/next.js/tree/canary/examples/with-cookie-auth) - -## How to use - -### Using `create-next-app` - -Execute [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example: - -```bash -npm init next-app --example with-cookie-auth with-cookie-auth-app -# or -yarn create next-app --example with-cookie-auth with-cookie-auth-app -``` - -### Download manually - -Download the example [or clone the repo](https://github.com/zeit/next.js): - -```bash -curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-cookie-auth -cd with-cookie-auth -``` - -### Run locally - -After you clone the repository you can install the dependencies, run `yarn dev` and start hacking! You'll be able to see the application running locally as if it were deployed. - -```bash -$ cd with-cookie-auth -$ (with-cookie-auth/) yarn install -$ (with-cookie-auth/) yarn dev -``` - -### Deploy - -Deploy it to the cloud with [ZEIT Now](https://zeit.co/import?filter=next.js&utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)). +- [auth0](https://github.com/zeit/next.js/tree/canary/examples/auth0) +- [with-cookie-auth-fauna](https://github.com/zeit/next.js/tree/canary/examples/with-cookie-auth-fauna) +- [with-passport](https://github.com/zeit/next.js/tree/canary/examples/with-passport) diff --git a/examples/with-cookie-auth/components/header.js b/examples/with-cookie-auth/components/header.js deleted file mode 100644 index 12be142cb8940..0000000000000 --- a/examples/with-cookie-auth/components/header.js +++ /dev/null @@ -1,58 +0,0 @@ -import Link from 'next/link' -import { logout } from '../utils/auth' - -const Header = () => ( -
- - -
-) - -export default Header diff --git a/examples/with-cookie-auth/components/layout.js b/examples/with-cookie-auth/components/layout.js deleted file mode 100644 index 29f59e09b2cd6..0000000000000 --- a/examples/with-cookie-auth/components/layout.js +++ /dev/null @@ -1,40 +0,0 @@ -import React from 'react' -import Head from 'next/head' -import Header from './header' - -const Layout = props => ( - <> - - With Cookies - - -
- -
-
{props.children}
-
- -) - -export default Layout diff --git a/examples/with-cookie-auth/package.json b/examples/with-cookie-auth/package.json deleted file mode 100644 index fff16cca1ef83..0000000000000 --- a/examples/with-cookie-auth/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "with-cookie-auth", - "scripts": { - "dev": "next", - "build": "next build", - "start": "next start" - }, - "dependencies": { - "isomorphic-unfetch": "latest", - "js-cookie": "latest", - "next": "latest", - "next-cookies": "latest", - "react": "latest", - "react-dom": "latest" - } -} diff --git a/examples/with-cookie-auth/pages/api/login.js b/examples/with-cookie-auth/pages/api/login.js deleted file mode 100644 index 3de8ac26b5f63..0000000000000 --- a/examples/with-cookie-auth/pages/api/login.js +++ /dev/null @@ -1,26 +0,0 @@ -import fetch from 'isomorphic-unfetch' - -export default async (req, res) => { - const { username } = await req.body - console.log('username', username) - const url = `https://api.github.com/users/${username}` - - try { - const response = await fetch(url) - - if (response.ok) { - const { id } = await response.json() - return res.status(200).json({ token: id }) - } else { - // https://github.com/developit/unfetch#caveats - const error = new Error(response.statusText) - error.response = response - throw error - } - } catch (error) { - const { response } = error - return response - ? res.status(response.status).json({ message: response.statusText }) - : res.status(400).json({ message: error.message }) - } -} diff --git a/examples/with-cookie-auth/pages/api/profile.js b/examples/with-cookie-auth/pages/api/profile.js deleted file mode 100644 index 4e9ef27a68cac..0000000000000 --- a/examples/with-cookie-auth/pages/api/profile.js +++ /dev/null @@ -1,33 +0,0 @@ -import fetch from 'isomorphic-unfetch' - -export default async (req, res) => { - if (!('authorization' in req.headers)) { - return res.status(401).send('Authorization header missing') - } - - const auth = await req.headers.authorization - - try { - const { token } = JSON.parse(auth) - const url = `https://api.github.com/user/${token}` - - const response = await fetch(url) - - if (response.ok) { - const js = await response.json() - // Need camelcase in the frontend - const data = Object.assign({}, { avatarUrl: js.avatar_url }, js) - return res.status(200).json({ data }) - } else { - // https://github.com/developit/unfetch#caveats - const error = new Error(response.statusText) - error.response = response - throw error - } - } catch (error) { - const { response } = error - return response - ? res.status(response.status).json({ message: response.statusText }) - : res.status(400).json({ message: error.message }) - } -} diff --git a/examples/with-cookie-auth/pages/index.js b/examples/with-cookie-auth/pages/index.js deleted file mode 100644 index c2f29b0d8e9f2..0000000000000 --- a/examples/with-cookie-auth/pages/index.js +++ /dev/null @@ -1,29 +0,0 @@ -import React from 'react' -import Layout from '../components/layout' - -const Home = () => ( - -

Cookie-based authentication example

- -

Steps to test the functionality:

- -
    -
  1. Click login and enter your GitHub username.
  2. -
  3. - Click home and click profile again, notice how your session is being - used through a token stored in a cookie. -
  4. -
  5. - Click logout and try to go to profile again. You'll get redirected to - the `/login` route. -
  6. -
- -
-) - -export default Home diff --git a/examples/with-cookie-auth/pages/login.js b/examples/with-cookie-auth/pages/login.js deleted file mode 100644 index 6a8b8d426e6d4..0000000000000 --- a/examples/with-cookie-auth/pages/login.js +++ /dev/null @@ -1,105 +0,0 @@ -import React, { useState } from 'react' -import fetch from 'isomorphic-unfetch' -import Layout from '../components/layout' -import { login } from '../utils/auth' - -const Login = () => { - const [userData, setUserData] = useState({ username: '', error: '' }) - - const handleSubmit = async event => { - event.preventDefault() - setUserData(Object.assign({}, userData, { error: '' })) - - const username = userData.username - const url = '/api/login' - - try { - const response = await fetch(url, { - method: 'POST', - - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ username }), - }) - if (response.status === 200) { - const { token } = await response.json() - await login({ token }) - } else { - console.log('Login failed.') - // https://github.com/developit/unfetch#caveats - let error = new Error(response.statusText) - error.response = response - throw error - } - } catch (error) { - console.error( - 'You have an error in your code or there are Network issues.', - error - ) - - const { response } = error - setUserData( - Object.assign({}, userData, { - error: response ? response.statusText : error.message, - }) - ) - } - } - - return ( - -
-
- - - - setUserData( - Object.assign({}, userData, { username: event.target.value }) - ) - } - /> - - - - {userData.error &&

Error: {userData.error}

} -
-
- -
- ) -} - -export default Login diff --git a/examples/with-cookie-auth/pages/profile.js b/examples/with-cookie-auth/pages/profile.js deleted file mode 100644 index 1f3f081f323d2..0000000000000 --- a/examples/with-cookie-auth/pages/profile.js +++ /dev/null @@ -1,75 +0,0 @@ -import React from 'react' -import Router from 'next/router' -import fetch from 'isomorphic-unfetch' -import nextCookie from 'next-cookies' -import Layout from '../components/layout' -import { withAuthSync } from '../utils/auth' -import getHost from '../utils/get-host' - -const Profile = props => { - const { name, login, bio, avatarUrl } = props.data - - return ( - - Avatar -

{name}

-

{login}

-

{bio}

- - -
- ) -} - -Profile.getInitialProps = async ctx => { - const { token } = nextCookie(ctx) - const apiUrl = getHost(ctx.req) + '/api/profile' - - const redirectOnError = () => - typeof window !== 'undefined' - ? Router.push('/login') - : ctx.res.writeHead(302, { Location: '/login' }).end() - - try { - const response = await fetch(apiUrl, { - credentials: 'include', - headers: { - Authorization: JSON.stringify({ token }), - }, - }) - - if (response.ok) { - const js = await response.json() - console.log('js', js) - return js - } else { - // https://github.com/developit/unfetch#caveats - return await redirectOnError() - } - } catch (error) { - // Implementation or Network error - return redirectOnError() - } -} - -export default withAuthSync(Profile) diff --git a/examples/with-cookie-auth/utils/auth.js b/examples/with-cookie-auth/utils/auth.js deleted file mode 100644 index 1778788bdfaed..0000000000000 --- a/examples/with-cookie-auth/utils/auth.js +++ /dev/null @@ -1,66 +0,0 @@ -import { useEffect } from 'react' -import Router from 'next/router' -import nextCookie from 'next-cookies' -import cookie from 'js-cookie' - -export const login = ({ token }) => { - cookie.set('token', token, { expires: 1 }) - Router.push('/profile') -} - -export const auth = ctx => { - const { token } = nextCookie(ctx) - - // If there's no token, it means the user is not logged in. - if (!token) { - if (typeof window === 'undefined') { - ctx.res.writeHead(302, { Location: '/login' }) - ctx.res.end() - } else { - Router.push('/login') - } - } - - return token -} - -export const logout = () => { - cookie.remove('token') - // to support logging out from all windows - window.localStorage.setItem('logout', Date.now()) - Router.push('/login') -} - -export const withAuthSync = WrappedComponent => { - const Wrapper = props => { - const syncLogout = event => { - if (event.key === 'logout') { - console.log('logged out from storage!') - Router.push('/login') - } - } - - useEffect(() => { - window.addEventListener('storage', syncLogout) - - return () => { - window.removeEventListener('storage', syncLogout) - window.localStorage.removeItem('logout') - } - }, []) - - return - } - - Wrapper.getInitialProps = async ctx => { - const token = auth(ctx) - - const componentProps = - WrappedComponent.getInitialProps && - (await WrappedComponent.getInitialProps(ctx)) - - return { ...componentProps, token } - } - - return Wrapper -} diff --git a/examples/with-cookie-auth/utils/get-host.js b/examples/with-cookie-auth/utils/get-host.js deleted file mode 100644 index 511de07674a43..0000000000000 --- a/examples/with-cookie-auth/utils/get-host.js +++ /dev/null @@ -1,14 +0,0 @@ -// This is not production ready, (except with providers that ensure a secure host, like Now) -// For production consider the usage of environment variables and NODE_ENV -function getHost(req) { - if (!req) return '' - - const { host } = req.headers - - if (host.startsWith('localhost')) { - return `http://${host}` - } - return `https://${host}` -} - -export default getHost