Skip to content

Commit 17da2da

Browse files
author
Leon Strauss
committed
implemented custom response bodies
1 parent 4589403 commit 17da2da

3 files changed

Lines changed: 58 additions & 9 deletions

File tree

README.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ The middleware will now check incoming requests to match the credentials
3232
The middleware will check incoming requests for a basic auth (`Authorization`)
3333
header, parse it and check if the credentials are legit.
3434

35-
**If a request is found to not be authorized**, it will respond with HTTP 401 and an empty body.
35+
**If a request is found to not be authorized**, it will respond with HTTP 401
36+
and a configurable (default empty) body.
3637

3738
**If a request is successfully authorized**, an `auth` property will be added to the request,
3839
containing an object with `user` and `password` properties, filled with the credentials.
@@ -96,6 +97,26 @@ function myAsyncAuthorizer(username, password, cb) {
9697
}
9798
```
9899

100+
### Unauthorized Response Body
101+
102+
Per default, the response body for unauthorized responses will be empty. It can
103+
be configured using the `unauthorizedResponse` option. You can either pass a
104+
simple string, which will be used as the response body, or a function that gets
105+
passed the express request object and is expected to return the response body:
106+
107+
```js
108+
app.use(basicAuth({
109+
users: { 'Foo': 'bar' },
110+
unauthorizedResponse: getUnauthorizedResponse
111+
}));
112+
113+
function getUnauthorizedResponse(req) {
114+
return req.auth
115+
? ('Credentials ' + req.auth.user + ':' + req.auth.password + ' rejected')
116+
: 'No credentials provided';
117+
}
118+
```
119+
99120
### Challenge
100121

101122
Per default the middleware will not add a `WWW-Authenticate` challenge header to
@@ -125,8 +146,7 @@ try out the requests and play around with the options.
125146

126147
## To Do
127148

128-
- Allow customization of unauthorized response body
149+
- Allow response body to be JSON (auto detect?)
129150
- Allow to set a realm for the challenge
130151
- Some kind of automated testing with the example server
131-
- Maybe add some optional callback to be called for unauthorized requests (for security logging)
132152
- Decide what should be included in `1.0.0`

example.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,16 @@ var asyncAuth = basicAuth({
4242
authorizeAsync: true
4343
});
4444

45+
//Uses a custom response body function
46+
var customBodyAuth = basicAuth({
47+
users: { 'Foo': 'bar' },
48+
unauthorizedResponse: getUnauthorizedResponse
49+
});
50+
51+
//Uses a static response body
52+
var staticBodyAuth = basicAuth({
53+
unauthorizedResponse: 'Haaaaaha'
54+
});
4555

4656
app.get('/static', staticUserAuth, function(req, res) {
4757
res.status(200).send('You passed');
@@ -59,6 +69,14 @@ app.get('/async', asyncAuth, function(req, res) {
5969
res.status(200).send('You passed');
6070
});
6171

72+
app.get('/custombody', customBodyAuth, function(req, res) {
73+
res.status(200).send('You passed');
74+
});
75+
76+
app.get('/staticbody', staticBodyAuth, function(req, res) {
77+
res.status(200).send('You passed');
78+
});
79+
6280
app.listen(8080, function() {
6381
console.log("Listening!");
6482
});
@@ -75,3 +93,7 @@ function myAsyncAuthorizer(username, password, cb) {
7593
else
7694
return cb(null, false)
7795
}
96+
97+
function getUnauthorizedResponse(req) {
98+
return req.auth ? ('Credentials ' + req.auth.user + ':' + req.auth.password + ' rejected') : 'No credentials provided';
99+
}

index.js

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,14 @@ function buildMiddleware(options) {
66
var users = options.users || {};
77
var authorizer = options.authorizer || staticUsersAuthorizer;
88
var isAsync = options.authorizeAsync != undefined ? !!options.authorizeAsync : false;
9+
var getResponseBody = options.unauthorizedResponse;
910

11+
if(!getResponseBody)
12+
getResponseBody = function() { return ''; };
13+
else if(typeof getResponseBody == 'string')
14+
getResponseBody = function() { return options.unauthorizedResponse };
15+
16+
assert(typeof getResponseBody == 'function', 'Expected a string or function for the unauthorizedResponse option');
1017
assert(typeof users == 'object', 'Expected an object for the basic auth users, found ' + typeof users + ' instead');
1118
assert(typeof authorizer == 'function', 'Expected a function for the basic auth authorizer, found ' + typeof authorizer + ' instead');
1219

@@ -24,16 +31,16 @@ function buildMiddleware(options) {
2431
if(!authentication)
2532
return unauthorized();
2633

27-
if(isAsync)
28-
return authorizer(authentication.name, authentication.pass, authorizerCallback);
29-
else if(!authorizer(authentication.name, authentication.pass))
30-
return unauthorized();
31-
3234
req.auth = {
3335
user: authentication.name,
3436
password: authentication.pass
3537
};
3638

39+
if(isAsync)
40+
return authorizer(authentication.name, authentication.pass, authorizerCallback);
41+
else if(!authorizer(authentication.name, authentication.pass))
42+
return unauthorized();
43+
3744
next();
3845

3946
function unauthorized() {
@@ -42,7 +49,7 @@ function buildMiddleware(options) {
4249
if(challenge)
4350
res.set('WWW-Authenticate', 'Basic');
4451

45-
return res.send('');
52+
return res.send(getResponseBody(req));
4653
}
4754

4855
function authorizerCallback(err, approved) {

0 commit comments

Comments
 (0)