@@ -40,37 +40,58 @@ export class AnonymousAuthService implements IAuthService {
4040 }
4141}
4242
43+ interface StaticCredentialsAuthOptions {
44+ /** Custom ssl sertificates. If you use it in driver, you must use it here too */
45+ sslCredentials ?: ISslCredentials ;
46+ /**
47+ * Timeout for token request in milliseconds
48+ * @default 10 * 1000
49+ */
50+ tokenRequestTimeout ?: number ;
51+ /** Expiration time for token in milliseconds
52+ * @default 6 * 60 * 60 * 1000
53+ */
54+ tokenExpirationTimeout ?: number
55+ }
4356
4457export class StaticCredentialsAuthService implements IAuthService {
45- private tokenExpirationTimeout = 30 * 60 * 1000 ;
46- private tokenRequestTimeout = 10 * 1000 ;
47- private tokenTimestamp : DateTime | null ;
48- private token : string = '' ;
49- private tokenUpdateInProgress : Boolean = false ;
58+ private readonly tokenRequestTimeout = 10 * 1000 ;
59+ private readonly tokenExpirationTimeout = 6 * 60 * 60 * 1000 ;
60+ private tokenTimestamp : DateTime | null ;
61+ private token : string = "" ;
62+ private tokenUpdatePromise : Promise < any > | null = null ;
5063 private user : string ;
5164 private password : string ;
52- private endpoint : string
53- private sslCredentials : ISslCredentials | undefined
65+ private endpoint : string ;
66+ private sslCredentials : ISslCredentials | undefined ;
5467
5568 private readonly GrpcService = class extends GrpcService < Ydb . Auth . V1 . AuthService > {
5669 constructor ( endpoint : string , sslCredentials ?: ISslCredentials ) {
57- super ( endpoint , ' Ydb.Auth.V1.AuthService' , Ydb . Auth . V1 . AuthService , sslCredentials )
70+ super ( endpoint , " Ydb.Auth.V1.AuthService" , Ydb . Auth . V1 . AuthService , sslCredentials ) ;
5871 }
5972
6073 login ( request : Ydb . Auth . ILoginRequest ) {
61- return this . api . login ( request )
74+ return this . api . login ( request ) ;
6275 }
6376
64- destroy ( ) { this . api . end ( ) }
65-
66- }
77+ destroy ( ) {
78+ this . api . end ( ) ;
79+ }
80+ } ;
6781
68- constructor ( user : string , password : string , endpoint : string , sslCredentials ?: ISslCredentials ) {
82+ constructor (
83+ user : string ,
84+ password : string ,
85+ endpoint : string ,
86+ options ?: StaticCredentialsAuthOptions
87+ ) {
88+ this . tokenTimestamp = null ;
6989 this . user = user ;
7090 this . password = password ;
7191 this . endpoint = endpoint ;
72- this . sslCredentials = sslCredentials
73- this . tokenTimestamp = null ;
92+ this . sslCredentials = options ?. sslCredentials ;
93+ if ( options ?. tokenRequestTimeout ) this . tokenRequestTimeout = options . tokenRequestTimeout ;
94+ if ( options ?. tokenExpirationTimeout ) this . tokenExpirationTimeout = options . tokenExpirationTimeout ;
7495 }
7596
7697 private get expired ( ) {
@@ -80,45 +101,38 @@ export class StaticCredentialsAuthService implements IAuthService {
80101 }
81102
82103 private async sendTokenRequest ( ) : Promise < AuthServiceResult > {
83- let runtimeAuthService = new this . GrpcService ( this . endpoint , this . sslCredentials )
104+ let runtimeAuthService = new this . GrpcService ( this . endpoint , this . sslCredentials ) ;
84105 try {
85106 const tokenPromise = runtimeAuthService . login ( {
86107 user : this . user ,
87- password : this . password
108+ password : this . password ,
88109 } ) ;
89110 const response = await withTimeout < Ydb . Auth . LoginResponse > ( tokenPromise , this . tokenRequestTimeout ) ;
90111 const result = AuthServiceResult . decode ( getOperationPayload ( response ) ) ;
91- runtimeAuthService . destroy ( )
92- return result
112+ runtimeAuthService . destroy ( ) ;
113+ return result ;
93114 } catch ( error ) {
94- throw new Error ( "Can't login by user and password " + String ( error ) )
115+ throw new Error ( "Can't login by user and password " + String ( error ) ) ;
95116 }
96-
97117 }
98118
99119 private async updateToken ( ) {
100- this . tokenUpdateInProgress = true
101- const { token} = await this . sendTokenRequest ( ) ;
120+ const { token } = await this . sendTokenRequest ( ) ;
102121 if ( token ) {
103122 this . token = token ;
104123 this . tokenTimestamp = DateTime . utc ( ) ;
105- this . tokenUpdateInProgress = false
106124 } else {
107- this . tokenUpdateInProgress = false
108- throw new Error ( 'Received empty token from credentials!' ) ;
125+ throw new Error ( "Received empty token from credentials!" ) ;
109126 }
110127 }
111128
112- private async waitUntilTokenUpdated ( ) {
113- while ( this . tokenUpdateInProgress ) { await sleep ( 1 ) }
114- return
115- }
116-
117129 public async getAuthMetadata ( ) : Promise < grpc . Metadata > {
118- if ( this . expired ) {
119- // block updateToken calls while token updating
120- if ( this . tokenUpdateInProgress ) await this . waitUntilTokenUpdated ( )
121- else await this . updateToken ( ) ;
130+ if ( this . expired || this . tokenUpdatePromise ) {
131+ if ( ! this . tokenUpdatePromise ) {
132+ this . tokenUpdatePromise = this . updateToken ( ) ;
133+ }
134+ await this . tokenUpdatePromise ;
135+ this . tokenUpdatePromise = null ;
122136 }
123137 return makeCredentialsMetadata ( this . token ) ;
124138 }
0 commit comments