@@ -106,6 +106,7 @@ class OracleDb {
106
106
this . shutdown = nodbUtil . callbackify ( shutdown ) . bind ( _oracledb ) ;
107
107
this . startup = nodbUtil . callbackify ( startup ) . bind ( _oracledb ) ;
108
108
this . initOracleClient = this . initOracleClient . bind ( _oracledb ) ;
109
+ this . _accessTokenHandler = this . _accessTokenHandler . bind ( _oracledb ) ;
109
110
}
110
111
111
112
// temporary method for determining if an object is a date until
@@ -114,6 +115,22 @@ class OracleDb {
114
115
return util . isDate ( val ) ;
115
116
}
116
117
118
+ // handler for access token callbacks
119
+ async _accessTokenHandler ( userFn , externalObj , refresh ) {
120
+ let accessToken ;
121
+ try {
122
+ let result = userFn ( refresh ) ;
123
+ if ( result instanceof Promise ) {
124
+ result = await result ;
125
+ }
126
+
127
+ _checkToken ( result ) ;
128
+ accessToken = result ;
129
+ } finally {
130
+ this . _returnAccessToken ( externalObj , accessToken ) ;
131
+ }
132
+ }
133
+
117
134
// retrieves a pool from the pool cache (synchronous method)
118
135
getPool ( poolAlias ) {
119
136
let pool ;
@@ -175,6 +192,21 @@ async function createPool(poolAttrs) {
175
192
throw new Error ( nodbUtil . getErrorMessage ( 'NJS-046' , poolAlias ) ) ;
176
193
}
177
194
195
+ if ( poolAttrs . accessToken !== undefined ) {
196
+ // cannot set username or password for token based authentication
197
+ if ( poolAttrs . user !== undefined ||
198
+ poolAttrs . password !== undefined ) {
199
+ throw new Error ( nodbUtil . getErrorMessage ( 'NJS-084' ) ) ;
200
+ }
201
+
202
+ // homogeneous and externalAuth must be set to true for token based
203
+ // authentication
204
+ if ( poolAttrs . homogeneous === false ||
205
+ poolAttrs . externalAuth === false ) {
206
+ throw new Error ( nodbUtil . getErrorMessage ( 'NJS-085' ) ) ;
207
+ }
208
+ }
209
+
178
210
// create an adjusted set of pool attributes to pass to the C layer; the
179
211
// session callback must be removed if it is a JavaScript function and the
180
212
// queue timeout is used to specify the maximum amount of time that the C
@@ -192,44 +224,33 @@ async function createPool(poolAttrs) {
192
224
adjustedPoolAttrs . queueTimeout = this . queueTimeout ;
193
225
}
194
226
195
- // Need to prevent another call in the same stack from succeeding, otherwise
196
- // two pools could be created with the same poolAlias and the second one that
197
- // comes back would overwrite the first in the cache.
198
- if ( poolAlias ) {
199
- tempUsedPoolAliases [ poolAlias ] = true ;
200
- }
201
-
202
- if ( adjustedPoolAttrs . accessToken !== undefined ) {
203
- // token and privateKey must be set for token based
204
- // authentication
205
- if ( adjustedPoolAttrs . accessToken . token === undefined ||
206
- adjustedPoolAttrs . accessToken . token === '' ||
207
- adjustedPoolAttrs . accessToken . privateKey === undefined ||
208
- adjustedPoolAttrs . accessToken . privateKey === '' ) {
209
- throw new Error ( nodbUtil . getErrorMessage ( 'NJS-084' ) ) ;
227
+ // token based authentication
228
+ if ( poolAttrs . accessToken !== undefined ) {
229
+ // accessTokenCallback is depricated from node-oracledb 5.5
230
+ if ( poolAttrs . accessTokenCallback !== undefined &&
231
+ typeof poolAttrs . accessToken === 'function' ) {
232
+ throw new Error ( nodbUtil . getErrorMessage ( 'NJS-088' ) ) ;
210
233
}
211
234
212
- // cannot set username or password for token based authentication
213
- if ( adjustedPoolAttrs . user !== undefined ||
214
- adjustedPoolAttrs . password !== undefined ) {
215
- throw new Error ( nodbUtil . getErrorMessage ( 'NJS-084' ) ) ;
216
- }
235
+ let accessToken ;
236
+ if ( typeof poolAttrs . accessToken === 'function' ) {
237
+ adjustedPoolAttrs . accessTokenCallback = poolAttrs . accessToken ;
238
+ accessToken = await poolAttrs . accessToken ( false ) ;
217
239
218
- // homogeneous and externalAuth must be set to true for token based
219
- // authentication
220
- if ( adjustedPoolAttrs . homogeneous === false ||
221
- adjustedPoolAttrs . externalAuth === false ) {
222
- throw new Error ( nodbUtil . getErrorMessage ( 'NJS-085' ) ) ;
240
+ if ( _isTokenExpired ( accessToken ) ) {
241
+ accessToken = await poolAttrs . accessToken ( true ) ;
242
+ }
243
+ } else {
244
+ accessToken = poolAttrs . accessToken ;
223
245
}
224
-
225
- adjustedPoolAttrs . token = adjustedPoolAttrs . accessToken . token ;
226
- adjustedPoolAttrs . privateKey =
227
- adjustedPoolAttrs . accessToken . privateKey ;
246
+ _checkToken ( accessToken , adjustedPoolAttrs ) ;
228
247
}
229
248
230
- if ( adjustedPoolAttrs . accessToken === undefined &&
231
- adjustedPoolAttrs . accessTokenCallback !== undefined ) {
232
- throw new Error ( nodbUtil . getErrorMessage ( 'NJS-084' ) ) ;
249
+ // Need to prevent another call in the same stack from succeeding, otherwise
250
+ // two pools could be created with the same poolAlias and the second one that
251
+ // comes back would overwrite the first in the cache.
252
+ if ( poolAlias ) {
253
+ tempUsedPoolAliases [ poolAlias ] = true ;
233
254
}
234
255
235
256
try {
@@ -305,15 +326,6 @@ async function getConnection(a1) {
305
326
// otherwise, create a new standalone connection
306
327
} else {
307
328
if ( connAttrs . accessToken !== undefined ) {
308
- // token and privateKey must be set for token based
309
- // authentication
310
- if ( connAttrs . accessToken . token === undefined ||
311
- connAttrs . accessToken . token === '' ||
312
- connAttrs . accessToken . privateKey === undefined ||
313
- connAttrs . accessToken . privateKey === '' ) {
314
- throw new Error ( nodbUtil . getErrorMessage ( 'NJS-084' ) ) ;
315
- }
316
-
317
329
// cannot set username or password for token based authentication
318
330
if ( connAttrs . user !== undefined ||
319
331
connAttrs . password !== undefined ) {
@@ -325,9 +337,17 @@ async function getConnection(a1) {
325
337
throw new Error ( nodbUtil . getErrorMessage ( 'NJS-086' ) ) ;
326
338
}
327
339
328
- connAttrs . token = connAttrs . accessToken . token ;
329
- connAttrs . privateKey =
330
- connAttrs . accessToken . privateKey ;
340
+ let accessToken ;
341
+ if ( typeof connAttrs . accessToken === 'function' ) {
342
+ accessToken = await connAttrs . accessToken ( false ) ;
343
+
344
+ if ( _isTokenExpired ( accessToken ) ) {
345
+ accessToken = await connAttrs . accessToken ( true ) ;
346
+ }
347
+ } else {
348
+ accessToken = connAttrs . accessToken ;
349
+ }
350
+ _checkToken ( accessToken , connAttrs ) ;
331
351
}
332
352
333
353
try {
@@ -427,6 +447,78 @@ async function startup(a1, a2) {
427
447
}
428
448
429
449
450
+ //-----------------------------------------------------------------------------
451
+ // _isTokenExpiredUtil()
452
+ // Function to check validity and expiry of token
453
+ //-----------------------------------------------------------------------------
454
+ function _isTokenExpiredUtil ( accessToken ) {
455
+ nodbUtil . assert ( typeof accessToken === 'string' , 'NJS-084' , 1 ) ;
456
+
457
+ if ( accessToken . split ( '.' ) [ 1 ] === undefined ) {
458
+ throw new Error ( nodbUtil . getErrorMessage ( 'NJS-084' ) ) ;
459
+ }
460
+
461
+ const base64Url = accessToken . split ( '.' ) [ 1 ] ;
462
+ const base64 = base64Url . replace ( / - / g, '+' ) . replace ( / _ / g, '/' ) ;
463
+ const buff = Buffer . from ( base64 , 'base64' ) ;
464
+ const payloadInit = buff . toString ( 'ascii' ) ;
465
+
466
+ let expiry = JSON . parse ( payloadInit ) . exp ;
467
+ nodbUtil . assert ( expiry != undefined , 'NJS-084' ) ;
468
+ expiry = expiry * 1000 ;
469
+
470
+ return ( new Date ( ) . getTime ( ) > expiry ) ;
471
+ }
472
+
473
+
474
+ //-----------------------------------------------------------------------------
475
+ // _isTokenExpired()
476
+ // Function to check validity of token parameter
477
+ //-----------------------------------------------------------------------------
478
+ function _isTokenExpired ( accessToken ) {
479
+ switch ( typeof accessToken ) {
480
+ case 'string' :
481
+ if ( accessToken === '' ) {
482
+ throw new Error ( nodbUtil . getErrorMessage ( 'NJS-084' ) ) ;
483
+ }
484
+
485
+ return _isTokenExpiredUtil ( accessToken ) ;
486
+ case 'object' :
487
+ if ( accessToken . token === undefined ||
488
+ accessToken . token === '' ||
489
+ accessToken . privateKey === undefined ||
490
+ accessToken . privateKey === '' ) {
491
+ throw new Error ( nodbUtil . getErrorMessage ( 'NJS-084' ) ) ;
492
+ }
493
+
494
+ return _isTokenExpiredUtil ( accessToken . token ) ;
495
+ default :
496
+ throw new Error ( nodbUtil . getErrorMessage ( 'NJS-084' ) ) ;
497
+ }
498
+ }
499
+
500
+
501
+ //-----------------------------------------------------------------------------
502
+ // _checkToken()
503
+ // Function to check validity of token parameter
504
+ //-----------------------------------------------------------------------------
505
+ function _checkToken ( accessToken , attrs ) {
506
+ if ( _isTokenExpired ( accessToken ) ) {
507
+ throw new Error ( nodbUtil . getErrorMessage ( 'NJS-087' ) ) ;
508
+ }
509
+
510
+ if ( attrs === undefined )
511
+ return ;
512
+
513
+ if ( typeof accessToken === 'string' ) {
514
+ attrs . token = accessToken ;
515
+ } else {
516
+ attrs . token = accessToken . token ;
517
+ attrs . privateKey = accessToken . privateKey ;
518
+ }
519
+ }
520
+
521
+
430
522
// create instance which will be exported
431
523
let oracleDbInst = new OracleDb ( ) ;
432
524
0 commit comments