@@ -15,9 +15,11 @@ function OAuthBasicExchangeAuthenticator(application,request,ttl,scopeFactory, r
1515 if ( parts . length !== 2 ) {
1616 return new ApiAuthRequestError ( { userMessage : 'Invalid Authorization value' , statusCode : 400 } ) ;
1717 }
18+
1819 if ( request . method !== 'POST' ) {
1920 return new ApiAuthRequestError ( { userMessage : 'Must use POST for token exchange, see http://tools.ietf.org/html/rfc6749#section-3.2' } ) ;
2021 }
22+
2123 this . id = parts [ 0 ] ;
2224 this . secret = parts [ 1 ] ;
2325 this . application = application ;
@@ -26,8 +28,8 @@ function OAuthBasicExchangeAuthenticator(application,request,ttl,scopeFactory, r
2628 this . requestedScope = requestedScope ;
2729}
2830
29- OAuthBasicExchangeAuthenticator . prototype . defaultScopeFactory = function defaultScopeFactory ( ) {
30- return '' ;
31+ OAuthBasicExchangeAuthenticator . prototype . defaultScopeFactory = function defaultScopeFactory ( account , requestedScope , callback ) {
32+ callback ( null , '' ) ;
3133} ;
3234
3335OAuthBasicExchangeAuthenticator . prototype . authenticate = function authenticate ( callback ) {
@@ -42,30 +44,72 @@ OAuthBasicExchangeAuthenticator.prototype.authenticate = function authenticate(c
4244 ( apiKey . account . status === 'ENABLED' )
4345 ) {
4446 var result = new AuthenticationResult ( apiKey , self . application . dataStore ) ;
47+
4548 result . forApiKey = apiKey ;
4649 result . application = self . application ;
47- result . tokenResponse = self . buildTokenResponse ( apiKey ) ;
48- callback ( null , result ) ;
50+
51+ self . buildTokenResponse ( apiKey , function onTokenResponse ( err , tokenResponse ) {
52+ if ( err ) {
53+ callback ( err ) ;
54+ return ;
55+ }
56+
57+ result . tokenResponse = tokenResponse ;
58+
59+ callback ( null , result ) ;
60+ } ) ;
4961 } else {
5062 callback ( new ApiAuthRequestError ( { userMessage : 'Invalid Client Credentials' , error : 'invalid_client' , statusCode : 401 } ) ) ;
5163 }
5264 }
5365 } ) ;
5466} ;
5567
56- OAuthBasicExchangeAuthenticator . prototype . buildTokenResponse = function buildTokenResponse ( apiKey ) {
68+ OAuthBasicExchangeAuthenticator . prototype . buildTokenResponse = function buildTokenResponse ( apiKey , callback ) {
5769 var self = this ;
58- var scope = self . scopeFactory ( apiKey . account , self . requestedScope ) ;
59- // TODO v1.0.0 - remove string option for tokens, should be array only
60- return {
61- "access_token" : self . buildAccesstoken ( apiKey . account ) ,
62- "token_type" :"bearer" ,
63- "expires_in" : self . ttl ,
64- "scope" : Array . isArray ( scope ) ? scope . join ( ' ' ) : scope
65- } ;
70+
71+ var account = apiKey . account ;
72+ var requestedScope = self . requestedScope ;
73+
74+ function retrieveScopeFactoryResult ( callback ) {
75+ var hasBeenCalled = false ;
76+
77+ function callbackWithResult ( err , scope ) {
78+ if ( hasBeenCalled ) {
79+ throw new Error ( 'Callback has already been called once. Assert that your scopeFactory doesn\'t return a result while also calling the callback.' ) ;
80+ }
81+
82+ hasBeenCalled = true ;
83+
84+ callback ( err , scope ) ;
85+ }
86+
87+ var optionalResult = self . scopeFactory ( account , requestedScope , callbackWithResult ) ;
88+
89+ // For backward-compatibility: If we have a result then call the callback immediately,
90+ // else expect it to be handled by the scopeFactory function.
91+ if ( optionalResult || optionalResult === '' ) {
92+ callbackWithResult ( null , optionalResult ) ;
93+ }
94+ }
95+
96+ retrieveScopeFactoryResult ( function onScopeResolved ( err , scopeResult ) {
97+ if ( err ) {
98+ callback ( err ) ;
99+ return ;
100+ }
101+
102+ // TODO v1.0.0 - remove string option for tokens, should be array only
103+ callback ( null , {
104+ access_token : self . buildAccessToken ( account , scopeResult ) ,
105+ token_type : 'bearer' ,
106+ expires_in : self . ttl ,
107+ scope : Array . isArray ( scopeResult ) ? scopeResult . join ( ' ' ) : scopeResult
108+ } ) ;
109+ } ) ;
66110} ;
67111
68- OAuthBasicExchangeAuthenticator . prototype . buildAccesstoken = function buildAccesstoken ( account ) {
112+ OAuthBasicExchangeAuthenticator . prototype . buildAccessToken = function buildAccessToken ( account , scope ) {
69113 var self = this ;
70114 var now = nowEpochSeconds ( ) ;
71115
@@ -76,8 +120,6 @@ OAuthBasicExchangeAuthenticator.prototype.buildAccesstoken = function buildAcces
76120 exp : now + self . ttl
77121 } ;
78122
79- var scope = self . scopeFactory ( account , self . requestedScope ) ;
80-
81123 if ( scope ) {
82124 // TODO v1.0.0 - remove string option, should be array only
83125 _jwt . scope = Array . isArray ( scope ) ? scope . join ( ' ' ) : scope ;
0 commit comments