Skip to content

Commit

Permalink
feat: implement frameGuard
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Oct 26, 2019
1 parent c4be74b commit 2dcc00a
Show file tree
Hide file tree
Showing 5 changed files with 134 additions and 1 deletion.
44 changes: 44 additions & 0 deletions adonis-typings/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* @adonisjs/shield
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare module '@ioc:Adonis/Addons/Shield' {
export type XFrameOptions = {
enabled: boolean,
action?: 'DENY' | 'SAMEORIGIN',
} | {
enabled: boolean,
action?: 'ALLOW-FROM',
domain: string,
}

// X-Content-Type-Options
export type ContentTypeSniffingOptions = {
enabled: boolean,
}

// HTTP Strict Transport Security (HSTS)
export type HstsOptions = {
enabled: boolean,
maxAge: string | number,
includeSubDomains: boolean,
preload: boolean,
}

// X-XSS-Protection
export type XSSOptions = {
enabled: boolean,
enableOnOldIE: boolean,
reportUri: string,
}

// X-Download-Options
export type IENoOpenOptions = {
enabled: boolean,
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"author": "virk",
"license": "MIT",
"devDependencies": {
"@adonisjs/http-server": "^1.3.1",
"@adonisjs/mrm-preset": "^2.1.0",
"@types/node": "^12.7.5",
"commitizen": "^4.0.3",
Expand Down
42 changes: 42 additions & 0 deletions src/frameGuard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* @adonisjs/shield
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

/// <reference path="../adonis-typings/index.ts" />

import { XFrameOptions } from '@ioc:Adonis/Addons/Shield'
import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'

const ALLOWED_ACTIONS = ['DENY', 'ALLOW-FROM', 'SAMEORIGIN']

/**
* Adds `X-Frame-Options` header based upon given user options
*/
export function frameGuard (options: XFrameOptions) {
if (!options.enabled) {
return function frameGuardMiddlewareFn (_ctx: HttpContextContract) {
}
}

const action = ((options.action || 'SAMEORIGIN').toUpperCase() as typeof options.action)!
if (!ALLOWED_ACTIONS.includes(action)) {
throw new Error('Action must be one of "DENY", "ALLOW-FROM" or "SAMEORGIGIN"')
}

if (action === 'ALLOW-FROM' && !options['domain']) {
throw new Error('Domain value is required when using action as "ALLOW-FROM"')
}

const result = action === 'ALLOW-FROM'
? `${action} ${options['domain']}`
: action

return function frameGuardMiddlewareFn ({ response }: HttpContextContract) {
response.header('X-Frame-Options', result)
}
}
43 changes: 43 additions & 0 deletions test/frame-guard.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* @adonisjs/shield
*
* (c) Harminder Virk <virk@adonisjs.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

import test from 'japa'
import { HttpContext } from '@adonisjs/http-server/build/standalone'
import { frameGuard } from '../src/frameGuard'

test.group('FrameGuard', () => {
test('return noop function when enabled is false', (assert) => {
const middlewareFn = frameGuard({ enabled: false })
const ctx = HttpContext.create('/', {}, {}, {}, {})
middlewareFn(ctx)

assert.isUndefined(ctx.response.getHeader('X-Frame-Options'))
})

test('raise error when action type is incorrect', (assert) => {
const middlewareFn = () => frameGuard({ enabled: true, action: 'FOO' } as any)
assert.throw(middlewareFn, 'Action must be one of "DENY", "ALLOW-FROM" or "SAMEORGIGIN"')
})

test('set X-Frame-Options header', (assert) => {
const middlewareFn = frameGuard({ enabled: true })
const ctx = HttpContext.create('/', {}, {}, {}, {})
middlewareFn(ctx)

assert.equal(ctx.response.getHeader('X-Frame-Options'), 'SAMEORIGIN')
})

test('set X-Frame-Options header for allow from action', (assert) => {
const middlewareFn = frameGuard({ enabled: true, action: 'ALLOW-FROM', domain: 'foo.com' })
const ctx = HttpContext.create('/', {}, {}, {}, {})
middlewareFn(ctx)

assert.equal(ctx.response.getHeader('X-Frame-Options'), 'ALLOW-FROM foo.com')
})
})
5 changes: 4 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
{
"extends": "./node_modules/@adonisjs/mrm-preset/_tsconfig"
"extends": "./node_modules/@adonisjs/mrm-preset/_tsconfig",
"files": [
"./node_modules/@adonisjs/http-server/build/adonis-typings/index.d.ts"
]
}

0 comments on commit 2dcc00a

Please sign in to comment.