From 9546762c06d163008e24d73d69e26979a4488799 Mon Sep 17 00:00:00 2001 From: Aiji Uejima Date: Fri, 6 Aug 2021 11:40:17 +0900 Subject: [PATCH 1/3] feat: adding `failSafe` option to the IP inspection --- src/ip.ts | 6 ++++-- src/types.ts | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/ip.ts b/src/ip.ts index 694e1a8..75b61cd 100644 --- a/src/ip.ts +++ b/src/ip.ts @@ -17,7 +17,9 @@ export const inspectIp = ( } export const ip: Operator = async (fort, ctx) => { - if (fort.inspectBy !== 'ip' || !ctx.req.headers['x-forwarded-for']) - return false + if (fort.inspectBy !== 'ip') return false + if (!ctx.req.headers['x-forwarded-for']) + return !(fort.failSafe ?? process.env.NODE_ENV === 'production') + return inspectIp(fort.ips, ctx.req.headers['x-forwarded-for']) } diff --git a/src/types.ts b/src/types.ts index aa9127c..5dc13f1 100644 --- a/src/types.ts +++ b/src/types.ts @@ -3,6 +3,7 @@ import { GetServerSidePropsContext } from 'next' export type InspectByIp = { inspectBy: 'ip' ips: string | Array + failSafe?: boolean } export type InspectByFirebase = { From 12e07d71828246195c4408ec95fdfe9c843517a1 Mon Sep 17 00:00:00 2001 From: Aiji Uejima Date: Fri, 6 Aug 2021 11:40:35 +0900 Subject: [PATCH 2/3] test: update test --- src/__tests__/ip.spec.ts | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/__tests__/ip.spec.ts b/src/__tests__/ip.spec.ts index a0fd0c3..867941d 100644 --- a/src/__tests__/ip.spec.ts +++ b/src/__tests__/ip.spec.ts @@ -2,6 +2,8 @@ import { inspectIp, ip } from '../ip' import { Fort } from '../types' import { GetServerSidePropsContext } from 'next' +const OLD_ENV = { ...process.env } + describe('ip', () => { test('inspectIp', () => { expect(inspectIp('123.1.1.1', undefined)).toEqual(false) @@ -18,6 +20,9 @@ describe('ip', () => { }) describe('ip', () => { + beforeAll(() => { + process.env = { ...OLD_ENV } + }) test('"inspectBy" is not "ip"', () => { return ip( { inspectBy: 'firebase' } as Fort, @@ -34,7 +39,24 @@ describe('ip', () => { } as unknown as GetServerSidePropsContext ).then((res) => expect(res).toEqual(true)) }) - test('"headers" dose not have "x-forwarded-for"', () => { + test('"headers" dose not have "x-forwarded-for" and failSafe is set true', () => { + return ip( + { inspectBy: 'ip', failSafe: true } as Fort, + { + req: { headers: {} } + } as unknown as GetServerSidePropsContext + ).then((res) => expect(res).toEqual(false)) + }) + test('"headers" dose not have "x-forwarded-for" and failSafe is set false', () => { + return ip( + { inspectBy: 'ip', failSafe: false } as Fort, + { + req: { headers: {} } + } as unknown as GetServerSidePropsContext + ).then((res) => expect(res).toEqual(true)) + }) + test('"headers" dose not have "x-forwarded-for" and failSafe is Not set when runs on production', () => { + process.env.NODE_ENV = 'production' return ip( { inspectBy: 'ip' } as Fort, { @@ -42,5 +64,14 @@ describe('ip', () => { } as unknown as GetServerSidePropsContext ).then((res) => expect(res).toEqual(false)) }) + test('"headers" dose not have "x-forwarded-for" and failSafe is Not set when runs on NOT production', () => { + process.env.NODE_ENV = 'development' + return ip( + { inspectBy: 'ip' } as Fort, + { + req: { headers: {} } + } as unknown as GetServerSidePropsContext + ).then((res) => expect(res).toEqual(true)) + }) }) }) From 90b01da1e33f770c945add5d99c688048d21507a Mon Sep 17 00:00:00 2001 From: Aiji Uejima Date: Fri, 6 Aug 2021 11:40:51 +0900 Subject: [PATCH 3/3] docs: update README --- README.md | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 52a39ae..791f736 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ module.exports = withPlugins([ ### When controlling by IP -Control by IP of access source (x-forwarded-for). +Control by IP of request source (x-forwarded-for). Specify the IPs to be allowed as a string or an array of strings, which can be written in CIDR format. ```js @@ -89,12 +89,19 @@ const withFortress = require('next-fortress')({ { inspectBy: 'ip', ips: ['11.22.33.0/24', '111.222.0.0/16'], // It can be written in CIDR format. + failSafe: true, // See description below. // ...controlMode } ] }) ``` +It uses `x-forwarded-for` to get the IP of the requestor. Therefore, it is not possible to control by IP in the development environment. +You can use `failSafe` to control whether the request is controlled or passed through in the case that such an IP could not be gotten. +- `failSafe?: boolean`: The default value is `process.env.NODE_ENV === 'production'`. + - `true`: If it fails to get the IP, it must control the request according to the control mode. + - `false`: If it fails to get the IP, the request will be passed through. + #### Redirect ```js const withFortress = require('next-fortress')({ @@ -113,7 +120,7 @@ const withFortress = require('next-fortress')({ }) ``` -#### Access Block +#### Request Block ```js const withFortress = require('next-fortress')({ forts: [ @@ -173,7 +180,7 @@ const withFortress = require('next-fortress')({ **Control Mode** - `redirect`: See [Redirect](#redirect) -- `block`: See [Access Block](#access-block) +- `block`: See [Request Block](#request-block) - `rewrite`: See [Rewrite](#rewrite) Put useFortressWithFirebase in your page/_app.jsx. @@ -211,7 +218,7 @@ const withFortress = require('next-fortress')({ **Control Mode** - `redirect`: See [Redirect](#redirect) -- `block`: See [Access Block](#access-block) +- `block`: See [Request Block](#request-block) - `rewrite`: See [Rewrite](#rewrite) Add `ssr: true` to the client side `Amplify.configure`. @@ -243,7 +250,7 @@ const withFortress = require('next-fortress')({ **Control Mode** - `redirect`: See [Redirect](#redirect) -- `block`: See [Access Block](#access-block) +- `block`: See [Request Block](#request-block) - `rewrite`: See [Rewrite](#rewrite) --- @@ -307,7 +314,7 @@ const withFortress = require('next-fortress')({ ## :construction: Caution -**Please do not use `next/link` to generate links to pages subject to access control.** +**Please do not use `next/link` to generate links to pages you want to control access to.** The link tag generated by `next/link` will request the target page for a js file when clicked. Unfortunately, it is not possible to control access to that URL.