Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs/examples/with iron session updates #30956

Merged
merged 4 commits into from
Nov 9, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 13 additions & 22 deletions examples/with-iron-session/README.md
Original file line number Diff line number Diff line change
@@ -1,34 +1,25 @@
# Example application using [`next-iron-session`](https://github.com/vvo/next-iron-session)
# Example application using [`iron-session`](https://github.com/vvo/iron-session)

---

<p align="center"><b>Online demo at <a href="https://next-iron-session.vercel.app/">https://next-iron-session.vercel.app/</a> 👀</b></p>
<p align="center"><b>👀 Online demo at <a href="https://iron-session-example.vercel.app/">https://iron-session-example.vercel.app</a></b></p>

---

This example creates an authentication system that uses a **signed and encrypted cookie to store session data**. It relies on [`next-iron-session`](https://github.com/vvo/next-iron-session).

It uses current best practices for authentication in the Next.js ecosystem.

On the next-iron-session repository (https://github.com/vvo/next-iron-session) you'll find:
This example creates an authentication system that uses a **signed and encrypted cookie to store session data**. It relies on [`iron-session`](https://github.com/vvo/iron-session).

- full API documentation and explanations on how it works
- [TypeScript example](https://github.com/vvo/next-iron-session/tree/master/examples/next-typescript)
- [JavaScript example](https://github.com/vvo/next-iron-session/tree/master/examples/next.js)
- [Express.js example](https://github.com/vvo/next-iron-session/tree/master/examples/express)
It uses current best practices for authentication in the Next.js ecosystem and replicates parts of how the Vercel dashboard is built.

**Features:**
**Features of the example:**

- [Static Generation](https://nextjs.org/docs/basic-features/pages#static-generation-recommended) (SG), recommended example
- [Server-side Rendering](https://nextjs.org/docs/basic-features/pages#server-side-rendering) (SSR) example in case you need it
- Logged in status synchronized between browser windows/tabs using **`useUser`** hook and [`swr`](https://swr.vercel.app/) module
- Layout based on the user's logged-in/out status
- Session data is signed and encrypted in a cookie
- [API Routes](https://nextjs.org/docs/api-routes/dynamic-api-routes) and [getServerSideProps](https://nextjs.org/docs/basic-features/data-fetching#getserversideprops-server-side-rendering) examples.
- The logged in status is synchronized between browser windows/tabs using **`useUser`** hook and the [`swr`](https://swr.vercel.app/).
- The layout is based on the user's logged-in/out status.
- The session data is signed and encrypted in a cookie (this is done automatically by `iron-session`).

[`next-iron-session`](https://github.com/vvo/next-iron-session) also supports:
[`iron-session`](https://github.com/vvo/iron-session) also provides:

- Express / Connect middlewares
- Multiple encryption keys (passwords) to allow for seamless updates or just password rotation
- An Express middleware, which can be used in any Node.js HTTP framework.
- Multiple encryption keys (passwords) to allow for seamless updates or just password rotation.
- Full TypeScript support, including session data.

## Preview

Expand Down
43 changes: 0 additions & 43 deletions examples/with-iron-session/components/Form.js

This file was deleted.

43 changes: 43 additions & 0 deletions examples/with-iron-session/components/Form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { FormEvent } from 'react'

export default function Form({
errorMessage,
onSubmit,
}: {
errorMessage: string
onSubmit: (e: FormEvent<HTMLFormElement>) => void
}) {
return (
<form onSubmit={onSubmit}>
<label>
<span>Type your GitHub username</span>
<input type="text" name="username" required />
</label>

<button type="submit">Login</button>

{errorMessage && <p className="error">{errorMessage}</p>}

<style jsx>{`
form,
label {
display: flex;
flex-flow: column;
}
label > span {
font-weight: 600;
}
input {
padding: 8px;
margin: 0.3rem 0 1rem;
border: 1px solid #ccc;
border-radius: 4px;
}
.error {
color: brown;
margin: 1rem 0 0;
}
`}</style>
</form>
)
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from 'react'
import Link from 'next/link'
import useUser from '../lib/useUser'
import useUser from 'lib/useUser'
import { useRouter } from 'next/router'
import fetchJson from '../lib/fetchJson'
import Image from 'next/image'
import fetchJson from 'lib/fetchJson'

const Header = () => {
export default function Header() {
const { user, mutateUser } = useUser()
const router = useRouter()

return (
<header>
<nav>
Expand All @@ -16,20 +17,34 @@ const Header = () => {
<a>Home</a>
</Link>
</li>
{!user?.isLoggedIn && (
{user?.isLoggedIn === false && (
<li>
<Link href="/login">
<a>Login</a>
</Link>
</li>
)}
{user?.isLoggedIn && (
{user?.isLoggedIn === true && (
<>
<li>
<Link href="/profile-sg">
<a>
<img src={user.avatarUrl} width={20} height={20} /> Profile
(Static Generation, recommended)
<span
style={{
marginRight: '.3em',
verticalAlign: 'middle',
borderRadius: '100%',
overflow: 'hidden',
}}
>
<Image
src={user.avatarUrl}
width={32}
height={32}
alt=""
/>
</span>
Profile (Static Generation, recommended)
</a>
</Link>
</li>
Expand All @@ -56,8 +71,13 @@ const Header = () => {
</>
)}
<li>
<a href="https://github.com/vvo/next-iron-session">
<img src="/GitHub-Mark-Light-32px.png" width="32" height="32" />
<a href="https://github.com/vvo/iron-session">
<Image
src="/GitHub-Mark-Light-32px.png"
width="32"
height="32"
alt=""
/>
</a>
</li>
</ul>
Expand Down Expand Up @@ -99,5 +119,3 @@ const Header = () => {
</header>
)
}

export default Header
45 changes: 0 additions & 45 deletions examples/with-iron-session/components/Layout.js

This file was deleted.

39 changes: 39 additions & 0 deletions examples/with-iron-session/components/Layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import Head from 'next/head'
import Header from 'components/Header'

export default function Layout({ children }: { children: React.ReactNode }) {
return (
<>
<Head>
<title>With Iron Session</title>
</Head>
<style jsx global>{`
*,
*::before,
*::after {
box-sizing: border-box;
}

body {
margin: 0;
color: #333;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, Noto Sans, sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
}

.container {
max-width: 65rem;
margin: 1.5rem auto;
padding-left: 1rem;
padding-right: 1rem;
}
`}</style>
<Header />

<main>
<div className="container">{children}</div>
</main>
</>
)
}
23 changes: 0 additions & 23 deletions examples/with-iron-session/lib/fetchJson.js

This file was deleted.

52 changes: 52 additions & 0 deletions examples/with-iron-session/lib/fetchJson.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
export default async function fetchJson<JSON = unknown>(
input: RequestInfo,
init?: RequestInit
): Promise<JSON> {
const response = await fetch(input, init)

// if the server replies, there's always some data in json
// if there's a network error, it will throw at the previous line
const data = await response.json()

// response.ok is true when res.status is 2xx
// https://developer.mozilla.org/en-US/docs/Web/API/Response/ok
if (response.ok) {
return data
}

throw new FetchError({
message: response.statusText,
response,
data,
})
}

export class FetchError extends Error {
response: Response
data: {
message: string
}
constructor({
message,
response,
data,
}: {
message: string
response: Response
data: {
message: string
}
}) {
// Pass remaining arguments (including vendor specific ones) to parent constructor
super(message)

// Maintains proper stack trace for where our error was thrown (only available on V8)
if (Error.captureStackTrace) {
Error.captureStackTrace(this, FetchError)
}

this.name = 'FetchError'
this.response = response
this.data = data ?? { message: message }
}
}
14 changes: 0 additions & 14 deletions examples/with-iron-session/lib/session.js

This file was deleted.