@@ -44,6 +44,7 @@ import * as url from 'url';
44
44
import * as http from 'http' ;
45
45
import * as jwt from 'jsonwebtoken' ;
46
46
import * as zlib from 'zlib' ;
47
+ import * as Promise from 'promise' ;
47
48
import urlJoin = require( 'url-join' ) ;
48
49
49
50
var pjson = require ( '../../package.json' ) ;
@@ -98,6 +99,7 @@ export class ChatConnector implements IConnector, IBotStorage {
98
99
private accessTokenExpires : number ;
99
100
private botConnectorOpenIdMetadata : OpenIdMetadata ;
100
101
private emulatorOpenIdMetadata : OpenIdMetadata ;
102
+ private refreshingToken : Promise . IThenable < string > ;
101
103
102
104
constructor ( protected settings : IChatConnectorSettings = { } ) {
103
105
if ( ! this . settings . endpoint ) {
@@ -693,33 +695,40 @@ export class ChatConnector implements IConnector, IBotStorage {
693
695
}
694
696
695
697
private refreshAccessToken ( cb : ( err : Error , accessToken : string ) => void ) : void {
696
- var opt : request . Options = {
697
- method : 'POST' ,
698
- url : this . settings . endpoint . refreshEndpoint ,
699
- form : {
700
- grant_type : 'client_credentials' ,
701
- client_id : this . settings . appId ,
702
- client_secret : this . settings . appPassword ,
703
- scope : this . settings . endpoint . refreshScope
704
- }
705
- } ;
706
- this . addUserAgent ( opt ) ;
707
- request ( opt , ( err , response , body ) => {
708
- if ( ! err ) {
709
- if ( body && response . statusCode < 300 ) {
710
- // Subtract 5 minutes from expires_in so they'll we'll get a
711
- // new token before it expires.
712
- var oauthResponse = JSON . parse ( body ) ;
713
- this . accessToken = oauthResponse . access_token ;
714
- this . accessTokenExpires = new Date ( ) . getTime ( ) + ( ( oauthResponse . expires_in - 300 ) * 1000 ) ;
715
- cb ( null , this . accessToken ) ;
716
- } else {
717
- cb ( new Error ( 'Refresh access token failed with status code: ' + response . statusCode ) , null ) ;
718
- }
719
- } else {
720
- cb ( err , null ) ;
721
- }
722
- } ) ;
698
+ // Get token only on first access. Other callers will block while waiting for token.
699
+ if ( ! this . refreshingToken ) {
700
+ this . refreshingToken = new Promise < string > ( ( resolve , reject ) => {
701
+ var opt : request . Options = {
702
+ method : 'POST' ,
703
+ url : this . settings . endpoint . refreshEndpoint ,
704
+ form : {
705
+ grant_type : 'client_credentials' ,
706
+ client_id : this . settings . appId ,
707
+ client_secret : this . settings . appPassword ,
708
+ scope : this . settings . endpoint . refreshScope
709
+ }
710
+ } ;
711
+ this . addUserAgent ( opt ) ;
712
+ request ( opt , ( err , response , body ) => {
713
+ if ( ! err ) {
714
+ if ( body && response . statusCode < 300 ) {
715
+ // Subtract 5 minutes from expires_in so they'll we'll get a
716
+ // new token before it expires.
717
+ var oauthResponse = JSON . parse ( body ) ;
718
+ this . accessToken = oauthResponse . access_token ;
719
+ this . accessTokenExpires = new Date ( ) . getTime ( ) + ( ( oauthResponse . expires_in - 300 ) * 1000 ) ;
720
+ this . refreshingToken = undefined ;
721
+ resolve ( this . accessToken ) ;
722
+ } else {
723
+ reject ( new Error ( 'Refresh access token failed with status code: ' + response . statusCode ) ) ;
724
+ }
725
+ } else {
726
+ reject ( err ) ;
727
+ }
728
+ } ) ;
729
+ } )
730
+ }
731
+ this . refreshingToken . then ( ( token ) => cb ( null , token ) , ( err ) => cb ( err , null ) ) ;
723
732
}
724
733
725
734
public getAccessToken ( cb : ( err : Error , accessToken : string ) => void ) : void {
0 commit comments