Skip to content

Commit

Permalink
Merge pull request #21 from aiji42/cognito-2
Browse files Browse the repository at this point in the history
Cognito (revival)
  • Loading branch information
aiji42 authored Aug 5, 2021
2 parents a935d94 + 0950b95 commit 97b52d1
Show file tree
Hide file tree
Showing 33 changed files with 2,785 additions and 667 deletions.
1 change: 1 addition & 0 deletions .idea/next-fortress.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

131 changes: 127 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ npm install --save next-fortress

## Usage
Write `withFortress` in `next.config.js`.

```js
// next.config.js
const withFortress = require('next-fortress')({
Expand Down Expand Up @@ -45,11 +46,17 @@ const withFortress = require('next-fortress')({
}
})

module.export = withFortress({
module.exports = withFortress({
// write your next.js configuration values.
})
```
- `forts: Fort[]`: See [Use Case](#use-case).
- `host?: string`: In order to inspect the request and control the response, a reverse proxy is launched internally. Therefore, it is necessary to specify the host of the target deployment itself. The Default value is `process.env.VERCEL_URL ?? '0.0.0.0'`
- `firebase?: FirebaseAdminCredential`: See [When controlling by Firebase auth](#when-controlling-by-firebase-auth).
- `prepared?: boolean`: See [About the file for inspection](#about-the-file-for-inspection). The Default value is `false`
If you are using next-compose-plugins
```js
// next.config.js
Expand Down Expand Up @@ -236,7 +243,72 @@ const withFortress = require('next-fortress')({
### When controlling by Cognito
WIP
If you are using Cognito, then the setup is very simple.
```js
// next.config.js
const withFortress = require('next-fortress')({
forts: [
{
inspectBy: 'cognito',
// ...controllMode1
}
]
})
```
Add `ssr: true` to the client side `Amplify.configure`.
```tsx
Amplify.configure({
// ... your configurations,
ssr: true
})
```
#### Redirect
```js
const withFortress = require('next-fortress')({
forts: [
{
inspectBy: 'cognito',
mode: 'redirect',
source: '/need-login/:path*', // from
destination: '/login', // to
statuCode: 307, // optional (default is 302)
}
]
})
```
#### Block
```js
const withFortress = require('next-fortress')({
forts: [
{
inspectBy: 'cognito',
mode: 'block',
source: '/need-login/:path*', // from
statuCode: 401, // optional (default is 400)
}
]
})
```
#### Rewrite
```js
const withFortress = require('next-fortress')({
forts: [
{
inspectBy: 'cognito',
mode: 'rewrite',
source: '/need-login/:slug', // from
destination: '/:slug', // to
}
]
})
```
---
Expand All @@ -246,12 +318,63 @@ WIP
---
### When controlling by Other Auth Providers
### When Customizing the inspection method
WIP
It is possible to self-define the method of inspecting requests.
For `prepare: true`, see [About the file for inspection](#about-the-file-for-inspection).
```js
// next.config.js
const withFortress = require('next-fortress')({
forts: [
{
inspectBy: 'custom',
// ...controllMode
}
],
prepare: true
})
```
Customize `pages/_fortress/[__key].js` as follows.
```ts
// pages/_fortress/[__key].js
import { Inspector } from 'next-fortress/build/inspector'
import { controller } from 'next-fortress/build/controller'

// (fort: Fort, ctx: GetServerSideContext) => Promise<boolean>
const customInspector = async (fort, ctx) => {
// Write your custom inspect method
// Return true when directing the request to normal content, false when causing it to fallback.
}
const inspector = new Inspector().add(customInspector)

export const getServerSideProps = async (ctx) => {
return controller(inspector, ctx)
}
const Fortress = () => null
export default Fortress
```
---
## About the file for inspection
This plugin will automatically add `pages/_fortress/[__key].js` when the server is started.
It is used to inspect requests and control responses based on the `forts` you set.
It will always be overwritten on server starts to keep up with changes in the plugin.
If for some reason you want to prevent overwriting (e.g. custom processing), or if you can't create that file automatically (e.g. monorepo configuration), you can switch to manual by adding `parepare: true` to the configuration.
```js
const withFortress = require('next-fortress')({
forts: [
{ ... }
],
prepared: true
})
```
## :construction: Caution
**Please do not use `next/link` to generate links to pages subject to access control.**
Expand Down
7 changes: 6 additions & 1 deletion example/.env.local.sample
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,9 @@ NEXT_PUBLIC_FIREBASE_STORAGE_BAKET=
NEXT_PUBLIC_FIREBASE_MESSAGE_SENDER_ID=
NEXT_PUBLIC_FIREBASE_APP_ID=
FIREBASE_PRIVATE_KEY=
FIREBASE_CLIENT_EMAIL=
FIREBASE_CLIENT_EMAIL=
NEXT_PUBLIC_COGNITO_IDENTITY_POOL_ID=
NEXT_PUBLIC_COGNITO_REGION=
NEXT_PUBLIC_COGNITO_USER_POOL_ID=
NEXT_PUBLIC_COGNITO_USER_POOL_WEB_CLIENT_ID=
NEXT_PUBLIC_COGNITO_DOMAIN=
10 changes: 9 additions & 1 deletion example/next.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,17 @@ const withFortress = require('next-fortress')({
inspectBy: 'firebase',
mode: 'redirect',
destination: '/firebase'
},
{
source: '/cognito/:path',
inspectBy: 'cognito',
mode: 'redirect',
destination: '/cognito'
}
],
host: process.env.VERCEL_URL ?? 'http://localhost:3000',
host: process.env.VERCEL_ENV === 'production'
? 'next-fortress.vercel.app'
: (process.env.VERCEL_URL ?? 'http://localhost:3000'),
firebase: {
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
Expand Down
9 changes: 3 additions & 6 deletions example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,13 @@
"lint": "next lint"
},
"dependencies": {
"add": "^2.0.6",
"aws-amplify": "^4.2.2",
"firebase": "^8.8.1",
"firebase-admin": "^9.11.0",
"next": "11.0.1",
"next-fortress": "1.3.0",
"nookies": "^2.5.2",
"next-fortress": "^1.3.0",
"prismjs": "^1.24.1",
"react": "^17.0.2",
"react-dom": "17.0.2",
"yarn": "^1.22.11"
"react-dom": "17.0.2"
},
"devDependencies": {
"@types/prismjs": "^1.16.6",
Expand Down
22 changes: 22 additions & 0 deletions example/src/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,28 @@ import { useFortressWithFirebase } from 'next-fortress/build/client'
import firebase from 'firebase/app'
import 'prismjs/themes/prism-tomorrow.css'
import '../styles/globals.css'
import Amplify from 'aws-amplify'

Amplify.configure({
aws_cognito_identity_pool_id:
process.env.NEXT_PUBLIC_COGNITO_IDENTITY_POOL_ID,
aws_cognito_region: process.env.NEXT_PUBLIC_COGNITO_REGION,
aws_user_pools_id: process.env.NEXT_PUBLIC_COGNITO_USER_POOL_ID,
aws_user_pools_web_client_id:
process.env.NEXT_PUBLIC_COGNITO_USER_POOL_WEB_CLIENT_ID,
oauth: {
domain: process.env.NEXT_PUBLIC_COGNITO_DOMAIN,
scope: ['openid', 'profile', 'email'],
redirectSignIn: process.env.NEXT_PUBLIC_VERCEL_URL
? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}/cognito`
: 'http://localhost:3000/cognito',
redirectSignOut: process.env.NEXT_PUBLIC_VERCEL_URL
? `https://${process.env.NEXT_PUBLIC_VERCEL_URL}/cognito`
: 'http://localhost:3000/cognito',
responseType: 'code'
},
ssr: true
})

function MyApp({ Component, pageProps }: AppProps) {
useFortressWithFirebase(firebase)
Expand Down
16 changes: 12 additions & 4 deletions example/src/pages/_fortress/[__key].ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
export { getServerSideProps } from 'next-fortress/build/inspect'
const Inspect = () => null

export default Inspect
import { Inspector } from 'next-fortress/build/inspector'
import { controller } from 'next-fortress/build/controller'
import { GetServerSideProps } from 'next'
import { ip } from 'next-fortress/build/ip'
import { firebase } from 'next-fortress/build/firebase'
import { cognito } from 'next-fortress/build/cognito'
const inspector = new Inspector().add(ip).add(firebase).add(cognito)
export const getServerSideProps: GetServerSideProps = async (ctx) => {
return controller(inspector, ctx)
}
const Fortress = () => null
export default Fortress
93 changes: 93 additions & 0 deletions example/src/pages/cognito/authed.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import styles from '../../styles/Home.module.css'
import Head from 'next/head'
import Image from 'next/image'
import { useEffect, useState, VFC } from 'react'
import Prism from 'prismjs'
import { Auth } from 'aws-amplify'

const Authed: VFC = () => {
const [session, setSession] = useState<undefined | { username: string }>()
useEffect(() => {
Prism.highlightAll()
Auth.currentAuthenticatedUser()
.then(setSession)
.catch(() => setSession(undefined))
}, [])
return (
<div className={styles.container}>
<Head>
<title>My Page | Cognito Example | Next Fortress</title>
<link rel="icon" href="/favicon.ico" />
</Head>

<main className={styles.main}>
<h1 className={styles.title}>Next Fortress</h1>
<h2>My Page</h2>

<p>
<strong>Hi! {session?.username}</strong>
</p>
<p>This page is accessible only to logged-in users.</p>

<div className={styles.grid}>
<button className={styles.card} onClick={() => Auth.signOut()}>
<h2>Logout</h2>
<p>You will be redirected to the page you were on.</p>
</button>
</div>

<hr />
<p>This concise code brings access control to this page.</p>
<pre style={{ maxWidth: 800, width: '100%' }}>
<code className="language-javascript">
{`//next.config.js
const withFortress = require('next-fortress')({
forts: [
{
inspectBy: 'cognito',
mode: 'redirect',
source: '/cognito/:path',
destination: '/cognito'
}
]
})
module.exports = withFortress({})
`}
</code>
</pre>

<pre style={{ maxWidth: 800, width: '100%' }}>
<code className="language-javascript">
{`//pages/_app.tsx
import Amplify from 'aws-amplify'
Amplify.configure({
// ..., your configure
ssr: true
})
function MyApp({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
`}
</code>
</pre>
</main>

<footer className={styles.footer}>
<a
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Powered by{' '}
<span className={styles.logo}>
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
</span>
</a>
</footer>
</div>
)
}

export default Authed
Loading

0 comments on commit 97b52d1

Please sign in to comment.