Skip to content

Commit 3d3b78b

Browse files
authored
Merge pull request #15 from leaonline/async
Async support for OAuth2 Server 5.x
2 parents d16c280 + 0bae3f3 commit 3d3b78b

File tree

10 files changed

+318
-318
lines changed

10 files changed

+318
-318
lines changed

.gitignore

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
# folders
2-
node_modules/
32
packages/
43

5-
# ide specific
6-
.idea
7-
.vscode
4+
85

96
# config files
107
productionSettings.json
@@ -135,4 +132,3 @@ SemikolonPlus*
135132
# meteor package specific
136133
.meteor/local
137134
.meteor/meteorite
138-
.npm

.versions

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,70 @@
1-
accounts-base@2.2.3
2-
accounts-password@2.3.1
1+
accounts-base@2.2.10
2+
accounts-password@2.4.0
33
allow-deny@1.1.1
4-
babel-compiler@7.9.0
4+
babel-compiler@7.10.5
55
babel-runtime@1.5.1
66
base64@1.0.12
77
binary-heap@1.0.11
8-
boilerplate-generator@1.7.1
8+
boilerplate-generator@1.7.2
99
caching-compiler@1.2.2
10-
callback-hook@1.4.0
11-
check@1.3.1
10+
callback-hook@1.5.1
11+
check@1.3.2
1212
coffeescript@1.0.17
1313
dburles:mongo-collection-instances@0.1.3
14-
ddp@1.4.0
15-
ddp-client@2.5.0
14+
ddp@1.4.1
15+
ddp-client@2.6.1
1616
ddp-common@1.4.0
17-
ddp-rate-limiter@1.1.0
18-
ddp-server@2.5.0
19-
diff-sequence@1.1.1
20-
dynamic-import@0.7.2
21-
ecmascript@0.16.2
22-
ecmascript-runtime@0.8.0
17+
ddp-rate-limiter@1.2.1
18+
ddp-server@2.7.0
19+
diff-sequence@1.1.2
20+
dynamic-import@0.7.3
21+
ecmascript@0.16.8
22+
ecmascript-runtime@0.8.1
2323
ecmascript-runtime-client@0.12.1
2424
ecmascript-runtime-server@0.11.0
25-
ejson@1.1.2
26-
email@2.2.1
27-
fetch@0.1.1
28-
geojson-utils@1.0.10
25+
ejson@1.1.3
26+
email@2.2.5
27+
fetch@0.1.4
28+
geojson-utils@1.0.11
2929
http@1.4.4
3030
id-map@1.1.1
3131
inter-process-messaging@0.1.1
3232
jkuester:http@2.1.0
33-
leaonline:oauth2-server@4.2.1
33+
leaonline:oauth2-server@5.0.0
3434
lmieulet:meteor-coverage@3.2.0
3535
lmieulet:meteor-legacy-coverage@0.1.0
3636
lmieulet:meteor-packages-coverage@0.1.0
37-
local-test:leaonline:oauth2-server@4.2.1
37+
local-test:leaonline:oauth2-server@5.0.0
3838
localstorage@1.2.0
39-
logging@1.3.1
40-
meteor@1.10.0
39+
logging@1.3.3
40+
meteor@1.11.5
4141
meteortesting:browser-tests@1.3.5
4242
meteortesting:mocha@2.0.3
4343
meteortesting:mocha-core@8.0.1
44-
minimongo@1.8.0
45-
modern-browsers@0.1.8
46-
modules@0.18.0
47-
modules-runtime@0.13.0
48-
mongo@1.15.0
44+
minimongo@1.9.3
45+
modern-browsers@0.1.10
46+
modules@0.20.0
47+
modules-runtime@0.13.1
48+
mongo@1.16.8
4949
mongo-decimal@0.1.3
5050
mongo-dev-server@1.1.0
5151
mongo-id@1.0.8
52-
npm-mongo@4.3.1
52+
npm-mongo@4.17.2
5353
ordered-dict@1.1.0
5454
practicalmeteor:chai@1.9.2_3
55-
promise@0.12.0
56-
random@1.2.0
57-
rate-limit@1.0.9
58-
react-fast-refresh@0.2.3
59-
reactive-var@1.0.11
55+
promise@0.12.2
56+
random@1.2.1
57+
rate-limit@1.1.1
58+
react-fast-refresh@0.2.8
59+
reactive-var@1.0.12
6060
reload@1.3.1
6161
retry@1.1.0
6262
routepolicy@1.1.1
63-
service-configuration@1.3.0
6463
sha@1.0.9
65-
socket-stream-client@0.5.0
66-
tracker@1.2.0
67-
underscore@1.0.10
64+
socket-stream-client@0.5.2
65+
tracker@1.3.3
66+
typescript@4.9.5
67+
underscore@1.6.0
6868
url@1.3.2
69-
webapp@1.13.1
70-
webapp-hashing@1.1.0
69+
webapp@1.13.8
70+
webapp-hashing@1.1.1

lib/oauth.js

Lines changed: 82 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ export class OAuth2Server {
6363
*/
6464
constructor ({ serverOptions = {}, model, routes, debug } = {}) {
6565
check(serverOptions, OptionsSchema.serverOptions)
66-
66+
if (debug) {
67+
console.debug('[OAuth2Server]: create new instance')
68+
console.debug('[OAuth2Server]: serveroptions', serverOptions)
69+
}
6770
this.instanceId = Random.id()
6871
this.config = {
6972
serverOptions: Object.assign({}, OAuth2ServerDefaults.serverOptions, serverOptions),
@@ -120,9 +123,8 @@ export class OAuth2Server {
120123
* @param secret
121124
* @returns {}
122125
*/
123-
registerClient ({ title, homepage, description, privacyLink, redirectUris, grants, clientId, secret }) {
124-
const self = this
125-
return Promise.await(self.model.createClient({
126+
async registerClient ({ title, homepage, description, privacyLink, redirectUris, grants, clientId, secret }) {
127+
return this.model.createClient({
126128
title,
127129
homepage,
128130
description,
@@ -131,45 +133,44 @@ export class OAuth2Server {
131133
grants,
132134
clientId,
133135
secret
134-
}))
136+
})
135137
}
136138

137139
authorizeHandler (options) {
138140
const self = this
139-
return function (req, res, next) {
141+
return async function (req, res, next) {
140142
const request = new Request(req)
141143
const response = new Response(res)
142-
return self.oauth.authorize(request, response, options)
143-
.then(function (code) {
144-
res.locals.oauth = { code: code }
145-
next()
146-
})
147-
.catch(function (err) {
148-
// handle error condition
149-
res.writeHead(500)
150-
res.end(err)
151-
})
144+
145+
try {
146+
const code = await self.oauth.authorize(request, response, options)
147+
res.locals.oauth = { code: code }
148+
next()
149+
} catch (err) {
150+
res.writeHead(500)
151+
res.end(err)
152+
}
152153
}
153154
}
154155

155156
authenticateHandler (options) {
156157
const self = this
157-
return function (req, res, next) {
158+
return async function (req, res, next) {
158159
const request = new Request(req)
159160
const response = new Response(res)
160-
return self.oauth.authenticate(request, response, options)
161-
.then(function (token) {
162-
req.data = Object.assign({}, req.data, token)
163-
next()
164-
})
165-
.catch(function (err) {
166-
return errorHandler(res, {
167-
status: err.status,
168-
error: err.name,
169-
description: err.message,
170-
debug: self.debug
171-
})
161+
162+
try {
163+
const token = await self.oauth.authenticate(request, response, options)
164+
req.data = Object.assign({}, req.data, token)
165+
next()
166+
} catch (err) {
167+
return errorHandler(res, {
168+
status: err.status,
169+
error: err.name,
170+
description: err.message,
171+
debug: self.debug
172172
})
173+
}
173174
}
174175
}
175176

@@ -214,10 +215,11 @@ const initRoutes = (self, { accessTokenUrl = '/oauth/token', authorizeUrl = '/oa
214215
return true
215216
}
216217

217-
const getValidatedClient = (req, res) => {
218+
const getValidatedClient = async (req, res) => {
218219
const clientId = req.method.toLowerCase() === 'get' ? req.query.client_id : req.body.client_id
219220
const secret = req.method.toLowerCase() === 'get' ? req.query.client_secret : req.body.client_secret
220-
const client = Promise.await(self.model.getClient(clientId, secret))
221+
const client = await self.model.getClient(clientId, secret)
222+
221223
if (!client) {
222224
// unauthorized_client - The client is not authorized to request an authorization code using this method.
223225
return errorHandler(res, {
@@ -228,6 +230,7 @@ const initRoutes = (self, { accessTokenUrl = '/oauth/token', authorizeUrl = '/oa
228230
debug: self.debug
229231
})
230232
}
233+
231234
return client
232235
}
233236

@@ -279,7 +282,7 @@ const initRoutes = (self, { accessTokenUrl = '/oauth/token', authorizeUrl = '/oa
279282
// If there is something wrong with the syntax of the request, such as the redirect_uri or client_id is invalid,
280283
// then it’s important not to redirect the user and instead you should show the error message directly.
281284
// This is to avoid letting your authorization server be used as an open redirector.
282-
route('get', authorizeUrl, function (req, res, next) {
285+
route('get', authorizeUrl, async function (req, res, next) {
283286
if (!validateParams(req.query, requiredAuthorizeGetParams, self.debug)) {
284287
return errorHandler(res, {
285288
status: 400,
@@ -293,7 +296,7 @@ const initRoutes = (self, { accessTokenUrl = '/oauth/token', authorizeUrl = '/oa
293296
const validResponseType = validateResponseType(req, res)
294297
if (!validResponseType) return
295298

296-
const client = getValidatedClient(req, res)
299+
const client = await getValidatedClient(req, res)
297300
if (!client) return
298301

299302
const redirectUri = getValidatedRedirectUri(req, res, client)
@@ -305,7 +308,7 @@ const initRoutes = (self, { accessTokenUrl = '/oauth/token', authorizeUrl = '/oa
305308
// STEP 2: ADD USER TO THE REQUEST
306309
// validate all inputs again, since all inputs
307310
// could have been manipulated within form
308-
route('post', authorizeUrl, function (req, res, next) {
311+
route('post', authorizeUrl, async function (req, res, next) {
309312
if (!validateParams(req.body, requiredAuthorizePostParams, self.debug)) {
310313
return errorHandler(res, {
311314
error: 'invalid_request',
@@ -316,7 +319,7 @@ const initRoutes = (self, { accessTokenUrl = '/oauth/token', authorizeUrl = '/oa
316319
})
317320
}
318321

319-
const client = getValidatedClient(req, res)
322+
const client = await getValidatedClient(req, res)
320323
if (!client) return
321324

322325
const validRedirectUri = getValidatedRedirectUri(req, res, client)
@@ -366,7 +369,7 @@ const initRoutes = (self, { accessTokenUrl = '/oauth/token', authorizeUrl = '/oa
366369
// - on allow, assign the client_id to the user's authorized clients
367370
// - on deny, ...?
368371
// - construct the redirect query and redirect to the redirect_uri
369-
route('post', authorizeUrl, function (req, res /*, next */) {
372+
route('post', authorizeUrl, async function (req, res /*, next */) {
370373
const request = new Request(req)
371374
const response = new Response(res)
372375
const authorizeOptions = {
@@ -377,37 +380,36 @@ const initRoutes = (self, { accessTokenUrl = '/oauth/token', authorizeUrl = '/oa
377380
}
378381
}
379382

380-
return self.oauth.authorize(request, response, authorizeOptions)
381-
.then(bind(function (code) {
382-
const query = new URLSearchParams({
383-
code: code.authorizationCode,
384-
user: req.user.id,
385-
state: req.body.state
386-
})
387-
388-
const finalRedirectUri = `${req.body.redirect_uri}?${query}`
383+
try {
384+
const code = await self.oauth.authorize(request, response, authorizeOptions)
385+
const query = new URLSearchParams({
386+
code: code.authorizationCode,
387+
user: req.user.id,
388+
state: req.body.state
389+
})
389390

390-
res.statusCode = 302
391-
res.setHeader('Location', finalRedirectUri)
392-
res.end()
393-
}))
394-
.catch(function (err) {
395-
errorHandler(res, {
396-
originalError: err,
397-
error: err.name,
398-
description: err.message,
399-
status: err.statusCode,
400-
state: req.body.state,
401-
debug: self.debug
402-
})
391+
const finalRedirectUri = `${req.body.redirect_uri}?${query}`
392+
393+
res.statusCode = 302
394+
res.setHeader('Location', finalRedirectUri)
395+
res.end()
396+
} catch (err) {
397+
errorHandler(res, {
398+
originalError: err,
399+
error: err.name,
400+
description: err.message,
401+
status: err.statusCode,
402+
state: req.body.state,
403+
debug: self.debug
403404
})
405+
}
404406
})
405407

406408
// STEP 4: GENERATE ACCESS TOKEN RESPONSE
407409
// - validate params
408410
// - validate authorization code
409411
// - issue accessToken and refreshToken
410-
route('post', accessTokenUrl, function (req, res, next) {
412+
route('post', accessTokenUrl, async function (req, res, /* next */) {
411413
if (!validateParams(req.body, requiredAccessTokenPostParams, self.debug)) {
412414
return errorHandler(res, {
413415
status: 400,
@@ -421,30 +423,29 @@ const initRoutes = (self, { accessTokenUrl = '/oauth/token', authorizeUrl = '/oa
421423
const request = new Request(req)
422424
const response = new Response(res)
423425

424-
return self.oauth.token(request, response)
425-
.then(function (token) {
426-
res.writeHead(200, {
427-
'Content-Type': 'application/json',
428-
'Cache-Control': 'no-store',
429-
Pragma: 'no-cache'
430-
})
431-
const body = JSON.stringify({
432-
access_token: token.accessToken,
433-
token_type: 'bearer',
434-
expires_in: token.accessTokenExpiresAt,
435-
refresh_token: token.refreshToken
436-
})
437-
res.end(body)
426+
try {
427+
const token = await self.oauth.token(request, response)
428+
res.writeHead(200, {
429+
'Content-Type': 'application/json',
430+
'Cache-Control': 'no-store',
431+
Pragma: 'no-cache'
438432
})
439-
.catch(function (err) {
440-
return errorHandler(res, {
441-
error: 'unauthorized_client',
442-
description: err.message,
443-
state: req.body.state,
444-
debug: self.debug,
445-
status: err.statusCode
446-
})
433+
const body = JSON.stringify({
434+
access_token: token.accessToken,
435+
token_type: 'bearer',
436+
expires_in: token.accessTokenExpiresAt,
437+
refresh_token: token.refreshToken
438+
})
439+
res.end(body)
440+
} catch (err) {
441+
return errorHandler(res, {
442+
error: 'unauthorized_client',
443+
description: err.message,
444+
state: req.body.state,
445+
debug: self.debug,
446+
status: err.statusCode
447447
})
448+
}
448449
})
449450

450451
route('use', fallbackUrl, function (req, res, next) {

0 commit comments

Comments
 (0)