88const async = require ( 'async' ) ;
99const errors = require ( 'restify-errors' ) ;
1010const jwt = require ( 'jsonwebtoken' ) ;
11- const { unless} = require ( 'express-unless' ) ;
11+ const { unless } = require ( 'express-unless' ) ;
1212
13- const DEFAULT_REVOKED_FUNCTION = ( _ , __ , cb ) => {
14- return cb ( null , false ) ;
15- } ;
13+ const DEFAULT_REVOKED_FUNCTION = ( _ , __ , cb ) => cb ( null , false ) ;
1614
17- /**
18- * @param {any } object
19- * @return {boolean }
20- */
21- function isFunction ( object ) {
22- return Object . prototype . toString . call ( object ) === '[object Function]' ;
23- }
15+ const isFunction = ( object ) => typeof object === 'function' ;
2416
25- /**
26- * @param {string } secret
27- * @return {function(*, *, *): * }
28- */
29- function wrapStaticSecretInCallback ( secret ) {
30- return ( _ , __ , cb ) => {
31- return cb ( null , secret ) ;
32- } ;
33- }
17+ const wrapStaticSecretInCallback = ( secret ) => ( _ , __ , cb ) => cb ( null , secret ) ;
3418
3519module . exports = ( options ) => {
36- if ( ! options || ! options . secret ) throw new Error ( 'secret should be set' ) ;
37-
38- let secretCallback = options . secret ;
39-
40- if ( ! isFunction ( secretCallback ) ) {
41- secretCallback = wrapStaticSecretInCallback ( secretCallback ) ;
20+ if ( ! options || ! options . secret ) {
21+ throw new Error ( 'secret should be set' ) ;
4222 }
4323
44- const isRevokedCallback = options . isRevoked || DEFAULT_REVOKED_FUNCTION ;
24+ const secretCallback = isFunction ( options . secret )
25+ ? options . secret
26+ : wrapStaticSecretInCallback ( options . secret ) ;
4527
46- const _requestProperty = options . userProperty ||
47- options . requestProperty ||
48- 'user' ;
49-
50- // eslint-disable-next-line max-len
51- const credentialsRequired = typeof options . credentialsRequired === 'undefined' ?
52- true :
53- options . credentialsRequired ;
28+ const isRevokedCallback = options . isRevoked || DEFAULT_REVOKED_FUNCTION ;
29+ const requestProperty = options . userProperty || options . requestProperty || 'user' ;
30+ const credentialsRequired = options . credentialsRequired !== false ;
5431
5532 const middleware = ( req , res , next ) => {
5633 let token ;
5734
58- if (
59- req . method === 'OPTIONS' &&
60- req . headers . hasOwnProperty ( 'access-control-request-headers' )
61- ) {
62- const hasAuthInAccessControl = ! ! ~ req . headers [
63- 'access-control-request-headers'
64- ]
35+ // Handle CORS preflight requests
36+ if ( req . method === 'OPTIONS' && req . headers [ 'access-control-request-headers' ] ) {
37+ const hasAuthInAccessControl = req . headers [ 'access-control-request-headers' ]
6538 . split ( ',' )
66- . map ( ( header ) => {
67- return header . trim ( ) ;
68- } )
69- . indexOf ( 'authorization' ) ;
39+ . map ( header => header . trim ( ) )
40+ . includes ( 'authorization' ) ;
7041
71- if ( hasAuthInAccessControl ) {
72- return next ( ) ;
73- }
42+ if ( hasAuthInAccessControl ) return next ( ) ;
7443 }
7544
76- if ( options . getToken && typeof options . getToken === 'function' ) {
77- try {
78- token = options . getToken ( req ) ;
79- } catch ( e ) {
80- return next ( e ) ;
81- }
82- } else if ( req . headers && req . headers . authorization ) {
83- const parts = req . headers . authorization . split ( ' ' ) ;
84- if ( parts . length === 2 ) {
85- const scheme = parts [ 0 ] ;
86- const credentials = parts [ 1 ] ;
87-
88- if ( / ^ (?: B e a r e r | J W T ) $ / i. test ( scheme ) ) {
89- token = credentials ;
90- } else {
91- return next (
92- new errors . InvalidCredentialsError (
93- 'Format is Authorization: Bearer [token] or Jwt [token]' ,
94- ) ,
95- ) ;
96- }
97- } else {
98- return next (
99- new errors . InvalidCredentialsError (
100- 'Format is Authorization: Bearer [token] or Jwt [token]' ,
101- ) ,
102- ) ;
103- }
45+ // Get the token from the request
46+ try {
47+ token = options . getToken ? options . getToken ( req ) : extractToken ( req ) ;
48+ } catch ( e ) {
49+ return next ( e ) ;
10450 }
10551
52+ // Check if token is required
10653 if ( ! token ) {
10754 if ( credentialsRequired ) {
108- return next (
109- new errors . InvalidCredentialsError (
110- 'No authorization token was found' ,
111- ) ,
112- ) ;
113- } else {
114- return next ( ) ;
55+ return next ( new errors . InvalidCredentialsError ( 'No authorization token was found' ) ) ;
11556 }
57+ return next ( ) ;
11658 }
11759
118- let dToken ;
119-
60+ let decodedToken ;
12061 try {
121- dToken = jwt . decode ( token , { complete : true } ) || { } ;
122- } catch ( e ) {
62+ decodedToken = jwt . decode ( token , { complete : true } ) || { } ;
63+ } catch {
12364 return next ( new errors . InvalidCredentialsError ( 'The token is corrupted' ) ) ;
12465 }
12566
12667 async . parallel ( [
127- ( callback ) => { // getSecret
128- const arity = secretCallback . length ;
129- if ( arity === 4 ) {
130- secretCallback ( req , dToken . header , dToken . payload , callback ) ;
131- } else { // arity == 3
132- secretCallback ( req , dToken . payload , callback ) ;
133- }
134- } ,
135- ( callback ) => { // checkRevoked
136- isRevokedCallback ( req , dToken . payload , callback ) ;
137- } ,
138- ] , ( err , results ) => {
139- if ( err ) {
140- return next ( err ) ;
141- }
142- const revoked = results [ 1 ] ;
68+ ( callback ) => getSecret ( secretCallback , req , decodedToken , callback ) ,
69+ ( callback ) => checkRevoked ( isRevokedCallback , req , decodedToken , callback ) ,
70+ ] , ( err , [ secret , revoked ] ) => {
71+ if ( err ) return next ( err ) ;
72+
14373 if ( revoked ) {
144- return next (
145- new errors . UnauthorizedError (
146- 'The token has been revoked.' ,
147- ) ,
148- ) ;
74+ return next ( new errors . UnauthorizedError ( 'The token has been revoked.' ) ) ;
14975 }
15076
151- const secret = results [ 0 ] ;
152-
77+ // Verify the token
15378 jwt . verify ( token , secret , options , ( err , decoded ) => {
15479 if ( err && credentialsRequired ) {
155- return ( err . name === 'TokenExpiredError' ) ?
156- next ( new errors . UnauthorizedError ( 'The token has expired' ) ) :
157- next ( new errors . InvalidCredentialsError ( err ) ) ;
80+ return next ( err . name === 'TokenExpiredError'
81+ ? new errors . UnauthorizedError ( 'The token has expired' )
82+ : new errors . InvalidCredentialsError ( err ) ) ;
15883 }
159- req [ _requestProperty ] = decoded ;
84+ req [ requestProperty ] = decoded ;
16085 next ( ) ;
16186 } ) ;
16287 } ) ;
16388 } ;
16489
90+ const extractToken = ( req ) => {
91+ const authHeader = req . headers ?. authorization ;
92+ if ( ! authHeader ) return null ;
93+
94+ const parts = authHeader . split ( ' ' ) ;
95+ if ( parts . length === 2 && / ^ ( B e a r e r | J W T ) $ / i. test ( parts [ 0 ] ) ) {
96+ return parts [ 1 ] ;
97+ }
98+
99+ throw new errors . InvalidCredentialsError ( 'Format is Authorization: Bearer [token] or Jwt [token]' ) ;
100+ } ;
101+
102+ const getSecret = ( callback , req , token , done ) => {
103+ const arity = callback . length ;
104+ return arity === 4
105+ ? callback ( req , token . header , token . payload , done )
106+ : callback ( req , token . payload , done ) ;
107+ } ;
108+
109+ const checkRevoked = ( callback , req , token , done ) => callback ( req , token . payload , done ) ;
110+
165111 middleware . unless = unless ;
166112 return middleware ;
167- } ;
113+ } ;
0 commit comments