Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6da0e30

Browse files
committed
Merge pull request totaljs#44 from aubergine10/master
Readme for BAA example
2 parents cae1ebb + 3ec8ae4 commit 6da0e30

File tree

1 file changed

+159
-0
lines changed

1 file changed

+159
-0
lines changed

authorization-www-basic/readme.md

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
## Example: Basic Access Authentication (BAA)
2+
3+
This example shows how to use [Basic Access Authentication](https://en.wikipedia.org/wiki/Basic_access_authentication) to authenticate users.
4+
5+
Features covered by this example:
6+
7+
* `controller.baa()` - read login details from request
8+
* `controller.baa('prompt')` - send login prompt on response (ask user to login)
9+
10+
See the `/controllers/default.js` for sample code.
11+
12+
> **Note:** BAA doesn't attempt to encrypt credentials and as such should only be used on HTTPS connections.
13+
14+
### Reading credentials
15+
16+
To read credentials, use the `.baa()` method in a route handler function:
17+
18+
```javascript
19+
function authorization() {
20+
var auth = this.baa(); // this === controller
21+
22+
// ...
23+
}
24+
```
25+
26+
This looks for the `Authorization: Basic <mime-encoded-userid-and-password>` HTTP header in the request, and returns an object containing relevant details:
27+
28+
```javascript
29+
auth.empty // if true, no credentials were found
30+
auth.user // the user name, if found
31+
auth.password // the password, if found
32+
```
33+
34+
### Requesting credentials
35+
36+
If the user hasn't logged in yet, the `auth.empty` property will be `true` (no username or password found)... so, we need to prompt them for those details:
37+
38+
```javascript
39+
function authorization() {
40+
41+
// ...
42+
43+
if (auth.empty) { // ask user to login
44+
this.baa('Admin Login Required.'); // or whatever prompt you want the user to see
45+
return;
46+
}
47+
48+
// ...
49+
}
50+
```
51+
52+
This sends a response back to the browser which has a `WWW-Authenticate` HTTP header like this:
53+
54+
```
55+
WWW-Authenticate: Basic realm="Admin Login Required."
56+
```
57+
58+
On seeing that header, the browser will display the prompt (`Admin Login Required.`) along with a basic login form with fields for username and password. When the user submits the form, the browser will retry the request, only this time it will have the required `Authorization` HTTP header that we are looking for.
59+
60+
### Validating credentials
61+
62+
The resulting request should include the login credentials, now all we need to do is validate them:
63+
64+
```javascript
65+
function authorization() {
66+
67+
// ...
68+
69+
// isValidLogin() would be custom function written by you
70+
// that checks whether user exists and also that the password
71+
// is correct for that user
72+
if ( isValidLogin( auth.user, auth.password ) ) {
73+
74+
// do authorised stuff
75+
76+
} else {
77+
78+
// ask them to login again?
79+
this.baa('Admin Login Required.');
80+
return;
81+
82+
// or maybe just throw a #401 error?
83+
this.view401('Invalid login details');
84+
return;
85+
86+
}
87+
88+
}
89+
```
90+
91+
### Bonus 1: Server-side caching
92+
93+
The browser will keep sending the `Authorization` header on subsequent requests for about 15 minutes, effectively keeping the user logged in (from user perspective). Downside is that, server-side, you have to re-check the credentials on every request. As such it's probably worth keeping a cache of validated credentials to avoid excessive database lookups, for example:
94+
95+
```javascript
96+
var baaCache = {};
97+
98+
function authorization() {
99+
100+
// ...
101+
102+
if ( (baaCache[auth.user] && baaCache[auth.user] === auth.password) || isValidLogin( auth.user, auth.password ) ) {
103+
104+
baaCache[auth.user] = auth.password; // cache
105+
106+
// do authorised stuff
107+
108+
} else {
109+
// ...
110+
}
111+
}
112+
113+
function housekeeping(tick) {
114+
if (tick % 5 === 0) // every 5 mins clear cache
115+
baaCache = {};
116+
}
117+
118+
// add this to export.install() at top of script:
119+
F.on('service', housekeeping)
120+
121+
// also add an export.uninstall() to remove the listener
122+
export.uninstall = function() {
123+
F.removeListener('service', housekeeping);
124+
}
125+
```
126+
### Bonus 2: URI authentication
127+
128+
The `.baa()` method only checks request HTTP headers for credentials, it doesn't check for credentials in the URI like this:
129+
130+
```
131+
https://user:[email protected]/
132+
```
133+
134+
If you wish to accept credentials in the URI, use `.req.uri.auth`:
135+
136+
```javascript
137+
function authorization() {
138+
139+
// ...
140+
141+
if (auth.empty) { // check for URI auth first, before asking user to login
142+
143+
if (this.req.uri.auth) { // found credentials on auth, use those instead
144+
145+
let creds = this.req.uri.auth.split(':');
146+
auth.user = creds[0];
147+
auth.password = creds[1];
148+
auth.empty = false;
149+
150+
} else {
151+
this.baa('Admin Login Required.'); // or whatever prompt you want the user to see
152+
return;
153+
}
154+
155+
}
156+
157+
// ...
158+
}
159+
```

0 commit comments

Comments
 (0)