Skip to content

Commit

Permalink
add support for restricting access using basic auth
Browse files Browse the repository at this point in the history
based on:
* upstream PR 96
    vercel/serve-handler#96
  • Loading branch information
warren-bank committed Dec 22, 2021
1 parent ada288d commit 7313d92
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 23 deletions.
25 changes: 21 additions & 4 deletions lib/schemas/deployment/config-static.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ module.exports = {
properties: {
source: {
type: 'string',
maxLength: 100,
minLength: 1
minLength: 1,
maxLength: 100
},
headers: {
type: 'array',
Expand All @@ -39,13 +39,13 @@ module.exports = {
type: 'object',
required: ['key', 'value'],
properties: {
key: {
'key': {
type: 'string',
minLength: 1,
maxLength: 128,
pattern: "^[a-zA-Z0-9_!#$%&'*+.^`|~-]+$"
},
value: {
'value': {
type: 'string',
minLength: 1,
maxLength: 2048,
Expand Down Expand Up @@ -79,6 +79,23 @@ module.exports = {
},
'etag': {
type: 'boolean'
},
'auth': {
type: 'object',
required: ['name', 'pass'],
properties: {
'name': {
type: 'string',
minLength: 1,
maxLength: 255
},
'pass': {
type: 'string',
minLength: 1,
maxLength: 255
}
},
additionalProperties: false
}
},
additionalProperties: false
Expand Down
14 changes: 14 additions & 0 deletions lib/serve-handler/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ You can use any of the following options:
| [`renderSingle`](#rendersingle-boolean) | If a directory only contains one file, render it |
| [`symlinks`](#symlinks-boolean) | Resolve symlinks instead of rendering a 404 error |
| [`etag`](#etag-boolean) | Calculate a strong `ETag` response header, instead of `Last-Modified` |
| [`auth`](#auth-object) | Restrict access using basic auth |

### public (String)

Expand Down Expand Up @@ -296,6 +297,19 @@ Sending an `ETag` header is disabled by default and can be enabled like this:
}
```

### auth (Object)

Restrict access to visitors using basic auth, which presents a username/password challenge prompt.

The required username/password combination can be configured like this:

```js
"auth": {
"name": "required_username",
"pass": "required_password"
}
```

## Error templates

The handler will automatically determine the right error format if one occurs and then sends it to the client in that format.
Expand Down
1 change: 1 addition & 0 deletions lib/serve-handler/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
],
"dependencies": {
"@recent-cli/resolve-lnk": "0.0.2",
"basic-auth": "2.0.1",
"bytes": "3.0.0",
"content-disposition": "0.5.2",
"fast-url-parser": "1.1.3",
Expand Down
27 changes: 27 additions & 0 deletions lib/serve-handler/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const contentDisposition = require('content-disposition')
const isPathInside = require('path-is-inside')
const parseRange = require('range-parser')
const lnk = require('@recent-cli/resolve-lnk')
const auth = require('basic-auth')

// Other
const directoryTemplate = require('./directory')
Expand Down Expand Up @@ -501,6 +502,14 @@ const getError = (val=400) => {
}
break

case 401:
error = {
statusCode,
code: 'access_denied',
message: 'Access Denied'
}
break

case 404:
error = {
statusCode,
Expand Down Expand Up @@ -787,6 +796,24 @@ module.exports = async (request, response, config = {}, methods = {}) => {
return
}

// Basic Authentication
if (config.auth) {
if ((config.auth instanceof Object) && config.auth.name && config.auth.pass) {
const credentials = auth(request)

if (!credentials || !(credentials instanceof Object) || (credentials.name !== config.auth.name) || (credentials.pass !== config.auth.pass)) {
response.setHeader('WWW-Authenticate', 'Basic realm="User Visible Realm"')

return process_error(getError(401))
}
}
else {
const err = new Error('Basic Authentication is enabled, but "config.auth" is not correctly configured')

return process_error(getError(err))
}
}

if (paths.real.stats && paths.real.stats.isDirectory()) {
let directory = null
let singleFile = null
Expand Down
59 changes: 40 additions & 19 deletions package-lock.json

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

0 comments on commit 7313d92

Please sign in to comment.