-
Notifications
You must be signed in to change notification settings - Fork 0
/
simple_express3.js
156 lines (122 loc) · 4.82 KB
/
simple_express3.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// simple server with a protected resource at /secret secured by OAuth 2
var OAuth2Provider = require('oauth2-provider').OAuth2Provider,
express = require('express'),
MemoryStore = express.session.MemoryStore;
// hardcoded list of <client id, client secret> tuples
var myClients = {
'1': '1secret',
};
var app = express();
// temporary grant storage
var myGrants = {};
var myOAP = new OAuth2Provider({crypt_key: 'encryption secret', sign_key: 'signing secret'});
// before showing authorization page, make sure the user is logged in
myOAP.on('enforce_login', function(req, res, authorize_url, next) {
if(req.session.user) {
next(req.session.user);
} else {
res.writeHead(303, {Location: '/login?next=' + encodeURIComponent(authorize_url)});
res.end();
}
});
// render the authorize form with the submission URL
// use two submit buttons named "allow" and "deny" for the user's choice
myOAP.on('authorize_form', function(req, res, client_id, authorize_url) {
res.end('<html>this app wants to access your account... <form method="post" action="' + authorize_url + '"><button name="allow">Allow</button><button name="deny">Deny</button></form>');
});
// save the generated grant code for the current user
myOAP.on('save_grant', function(req, client_id, code, next) {
if(!(req.session.user in myGrants))
myGrants[req.session.user] = {};
myGrants[req.session.user][client_id] = code;
next();
});
// remove the grant when the access token has been sent
myOAP.on('remove_grant', function(user_id, client_id, code) {
if(myGrants[user_id] && myGrants[user_id][client_id])
delete myGrants[user_id][client_id];
});
// find the user for a particular grant
myOAP.on('lookup_grant', function(client_id, client_secret, code, next) {
// verify that client id/secret pair are valid
if(client_id in myClients && myClients[client_id] == client_secret) {
for(var user in myGrants) {
var clients = myGrants[user];
if(clients[client_id] && clients[client_id] == code)
return next(null, user);
}
}
next(new Error('no such grant found'));
});
// embed an opaque value in the generated access token
myOAP.on('create_access_token', function(user_id, client_id, next) {
var data = 'blah'; // can be any data type or null
next(data);
});
// (optional) do something with the generated access token
myOAP.on('save_access_token', function(user_id, client_id, access_token) {
console.log('saving access token %s for user_id=%s client_id=%s', access_token, user_id, client_id);
});
// an access token was received in a URL query string parameter or HTTP header
myOAP.on('access_token', function(req, token, next) {
var TOKEN_TTL = 10 * 60 * 1000; // 10 minutes
if(token.grant_date.getTime() + TOKEN_TTL > Date.now()) {
req.session.user = token.user_id;
req.session.data = token.extra_data;
} else {
console.warn('access token for user %s has expired', token.user_id);
}
next();
});
// (optional) client authentication (xAuth) for trusted clients
myOAP.on('client_auth', function(client_id, client_secret, username, password, next) {
if(client_id == '1' && username == 'guest') {
var user_id = '1337';
return next(null, user_id);
}
return next(new Error('client authentication denied'));
});
app.use(express.logger());
app.use(express.bodyParser());
app.use(express.query());
app.use(express.cookieParser());
app.use(express.session({store: new MemoryStore({reapInterval: 5 * 60 * 1000}), secret: 'abracadabra'}));
app.use(myOAP.oauth());
app.use(myOAP.login());
app.get('/', function(req, res, next) {
console.dir(req.session);
res.end('home, logged in? ' + !!req.session.user);
});
app.get('/login', function(req, res, next) {
if(req.session.user) {
res.writeHead(303, {Location: '/'});
return res.end();
}
var next_url = req.query.next ? req.query.next : '/';
res.end('<html><form method="post" action="/login"><input type="hidden" name="next" value="' + next_url + '"><input type="text" placeholder="username" name="username"><input type="password" placeholder="password" name="password"><button type="submit">Login</button></form>');
});
app.post('/login', function(req, res, next) {
req.session.user = req.body.username;
res.writeHead(303, {Location: req.body.next || '/'});
res.end();
});
app.get('/logout', function(req, res, next) {
req.session.destroy(function(err) {
res.writeHead(303, {Location: '/'});
res.end();
});
});
app.get('/secret', function(req, res, next) {
if(req.session.user) {
res.end('proceed to secret lair, extra data: ' + JSON.stringify(req.session.data));
} else {
res.writeHead(403);
res.end('no');
}
});
app.listen(8081, function() {
console.log("Express server listening on port " + 8081);
});
function escape_entities(s) {
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
}